본문 바로가기
SK shieldus Rookies 16기

[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(11일차)

by Challenge programmers 2023. 11. 6.

오늘 학습 주제

1. 시큐어코딩 - 시간 및 상태

2. 시큐어코딩 -  에러처리

3. 시큐어코딩 -  코드 오류

4. 시큐어코딩 -  캡슐화

5. 시큐어코딩 -  API 오용

 

 

 

 

시큐어 코딩 - 시간 및 상태


 

동시 또는 거의 동시에 여러 코드 수행을 지원하는 병렬 시스템이나

하나 이상의 프로세스가 동작되는 환경에서

시간 및 상태를 부적절하게 관리하여

발생할 수 있는 보안약점

 

 

- 경쟁 조건: 검사 시점과 사용 시점[TOCTOU] -

경쟁 조건: 검사 시점과 사용 시점[TOCTOU]
정의 하나의 자원에 대해 동시에 검사시점과 사용시점이 달라 생기는 보안 약점
발생되는 문제 동기화 오류, 교착상태 등
원리 자원을 사용하는 시점과 검사하는 시점이 다르기 때문에,
검사하는 시점(Time Of Check)에
존재하던 자원이 사용하던 시점 (Time Of Use)에
사라지는 등 자원의 상태가 변하는 경우가 발생
예방법 • 변수, 파일과 같은 공유자원을 여러 프로세스가 접근하여 사용할 경우 동기화 구문을 사용하여
  한 번에 하나의 프로세스만 접근 허가

• 성능에 미치는 영향을 최소화하기 위해 임계영역(critical section) 주변만 동기화 구문을 사용

• 파이썬의 Lock 객체 사용 시 lock.acquire()로 자원을 잠그고 lock.release()로 자원을
  해제해야 하며, 이 부분을 with 문을 사용해 간단하게 표현 가능

 

========================================= 안전하지 않은 코드 =========================================
	def write_shared_file(filename, content):
		# 멀티스레드 환경에서는 다른 사용자들의 작업에 따라 파일이 사라질 수
		# 있기 때문에 공유 자원에 대해서는 검사와 사용을 동시에 해야 한다.
		if os.path.isfile(filename) is True:


=========================================== 안전한 코드 =============================================
	lock = threading.Lock()
	def write_shared_file(filename, content):
		# lock을 이용하여 여러 사용자가 동시에 파일에 접근하지 못하도록 제한
		with lock:

 

[ 문제점 ]

공유된 파일을 사용할 때 파일을 불러온 후 실제로 파일을 사용하는 부분이 실행되기 전

짧은 시간에도  다른 사용자 또는 프로그램에 의해 파일이 사라져 원하는 기능을 실행 불가

 

[ 해결 ]

파일 검사 후 파일이 삭제되거나 변동되는 것을 예방하기 위해 lock을 사용하여

각 쓰레드에서 공유 자원에 접근하는 것을 통제

lock을 acquire하면 해당 쓰레드만 공유 데이터에 접근 할 수 있고,

lock을 release 해야만 다른 쓰레드에서 공유 데이터에 접근 가능

 

- 종료되지 않는 반복문 또는 재귀 함수 -

종료되지 않는 반복문 또는 재귀 함수
정의 무한루프에 빠진 반복문과 재귀 함수로 인해 자원 고갈이 유발되어
시스템의 정상적인 서비스를 방해하는 보안 약점
발생되는 문제 자원 고갈
원리 재귀 함수의 순환 횟수를 제어하지 못해 할당된 메모리나 프로그램 스택 등의 자원을
개발자가 의도한 범위를 과도하게 초과
예방법 • 모든 재귀 호출 시 호출 횟수를 제한하거나 재귀 함수 종료 조건을 명확히 정의해
  호출을 제어

• 파이썬의 recursionlimit 제한은 스택 오버플로우 발생을 막기 위한 방법으로,
  recursionlimit 값을 과도하게 큰 값으로 설정하지 않아야 함

 

========================================= 안전하지 않은 코드 =========================================
	def factorial(num):
		# 재귀함수 탈출조건을 설정하지 않아 동작 중 에러 발생
		return num * factorial(num – 1)

=========================================== 안전한 코드 =============================================
	def factorial(num):
		# 재귀함수 사용 시에는 탈출 조건을 명시해야 한다.
		if (num == 0):
			return 1
		else:
			return num * factorial(num - 1)

 

[ 문제점 ]

함수 내부에서 자신을 호출하는 함수로 재귀문을 빠져 나오는 조건을

정의하고 있지 않아 시스템 장애를 유발

 

[ 해결 ]

특정 조건 또는 횟수에 따라 재귀 코드 실행을 중단해

프로그램이 무한 반복에 빠지지 않도록 예방

 

 

시큐어 코딩 - 에러 처리


 

에러를 처리하지 않거나, 불충분하게 처리하여

에러 정보에 중요정보(시스템 내부정보 등)가 포함될 때

발생 할 수 있는 보안약점

 

 

- 오류 메시지 정보노출 -

오류 메시지 정보 노출
정의 민감한 정보를 포함하는 오류 메시지를 생성해
외부에 제공하여 발생하는 보안 약점
발생되는 문제 프로그램 내부 구조 유출
원리 예외발생 시 예외 이름이나 추적 메시지 (traceback)를 출력하는 경우
응용 프로그램이 실행환경, 사용자 등 관련 데이터에 대한 민감한 정보를 포함하는
오류 메시지를 생성해 외부에 제공
예방법 • 오류 메시지는 정해진 사용자에게 유용한 최소한의 정보만 포함하도록 함

• 소스코드에서 예외 상황은 내부적 으로 처리하고 사용자에게 시스템 내부 정보 등
  민감한 정보를 포함하는 오류를 출력하지 않고 미리 정의된 메시지를 제공하도록 설정

 

========================================= 안전하지 않은 코드 =========================================
	# config/urls.py
	# 별도의 에러 페이지를 선언하지 않아 django의 기본 에러 페이지를 출력한다

=========================================== 안전한 코드 =============================================
	# config/urls.py
	from django.conf.urls import handler400, handler403, handler404, handler500
	# 사용자 정의 에러 페이지를 지정하고
	# views.py에 사용자 정의 에러 페이지에 대한 코드를 구현하여 사용한다
	handler400 = "blog.views.error400"
	handler403 = "blog.views.error403"  
	handler404 = "blog.views.error404"
	handler500 = "blog.views.error500“

 

[ 문제점 ]

사용자 요청을 정상적으로 처리할 수 없는 경우 에러 페이지에 디버그 정보 또는 서버의 정보가 노출

어플리케이션 배포 시 DEBUG 모드를 True로 설정하고 배포할 경우 시스템의 주요 정보가 노출

 

 

[ 해결 ]

제공되는 에러 페이지 핸들러를 이용해 별도의 에러 페이지를 생성하여

사용자에게 표현하고 서버의 정보노출을 최소화

 

========================================= 안전하지 않은 코드 =========================================
	# 에러메시지를 통해 스택 정보가 노출.
	traceback.print_exc()

=========================================== 안전한 코드 =============================================
	# 에러 코드와 정보를 별도로 정의하고 최소 정보만 로깅
	logger.error('ERROR-01:통신에러')

 

[ 문제점 ]

traceback을 사용하여 에러 스택을 표준 출력으로 표시해 정보가 노출

 

 

[ 해결 ]

오류 처리 시 에러 이름이나 에러 추적 정보가 노출되지 않도록 처리

 

 

- 오류상황 대응 부재 -

오류상황 대응 부재
정의 오류가 발생할 수 있는 부분을 확인하였으나
오류에 대해 예외 처리를 하지 않을 경우 발생하는 보안 약점
발생되는 문제 소프트웨어의 안정성, 신뢰성, 보안성에 부정적인 영향
원리 공격자는 오류 상황을 악용해 개발자가 의도하지 않은 방향으로
프로그램 동작 유도
예방법 • 오류가 발생할 수 있는 부분에 대하여 제어문(try-except)을 사용해 적절하게 예외 처리

 

========================================= 안전하지 않은 코드 =========================================
	def encryption(key_id, plain_text):
		static_key = {'key':b'0000000000000000', 'iv':b'0000000000000000'}
		try:
			static_key = static_keys[key_id]
		except IndexError:
			# key 선택 중 오류 발생 시 기본으로 설정된 암호화 키인
			# ‘0000000000000000’ 으로 암호화가 수행된다.
			pass

=========================================== 안전한 코드 =============================================
	def encryption(key_id, plain_text):
		static_key = {'key':b'0000000000000000', 'iv':b'0000000000000000'}
		try:
			static_key = static_keys[key_id]
		except IndexError:
			# key 선택 중 오류 발생 시 랜덤으로 암호화 키를 생성하도록 설정
			static_key = {'key': secrets.token_bytes(16), 'iv': secrets.token_bytes(16)}
			static_keys.append(static_key

 

[ 문제점 ]

try 블록에서 발생하는 오류를 포착(except)하고 있지만

그 오류에 대해서 아무 조치를 하지 않는 상황

 

[ 해결 ]

반드시 예외 처리 구문을 추가

 

 

- 부적절한 예외 처리 -   

부적절한 예외 처리
정의 예외 상황에 대한 조건을 적절하게 검사 하지 않을 경우
발생하는 보안 약점
발생되는 문제 소프트웨어의 안정성과 신뢰성을 저하
원리 예외 상황에 대한 적절한 대응이 이뤄지지 않거나,
사용자에게 충분한 정보를 제공하지 않아 문제 야기
예방법 • 값을 반환하는 모든 함수의 결과값을 검사해야 함

• 결과값이 개발자가 의도했던 값인지 검사하고, 예외 처리를 사용하는 경우에
  광범위한 예외 처리 대신 구체적인 예외 처리를 수행함

 

========================================= 안전하지 않은 코드 =========================================
	# 예외처리를 세분화 할 수 있음에도 광범위하게 사용하여 예기치 않은
	# 문제가 발생할 수 있다
	except:
		print("Unexpected error ")

=========================================== 안전한 코드 =============================================
	# 발생할 수 있는 오류의 종류와 순서에 맞춰서 예외 처리 한다.
	except FileNotFoundError:
		print("file is not found")
	except OSError:
		print("cannot open file")
	except ValueError:
		print("Could not convert data to an integer.")

 

[ 문제점 ]

다양한 예외가 발생할 수 있음에도 불구하고 광범위한 예외 처리로

예외상황에 따른 적절한 조치가 부적절

 

[ 해결 ]

발생 가능한 예외를 세분화한 후 예외상황에 따라 적합하게 처리

 

 

 

 

시큐어 코딩 - 코드 오류


 

타입 변환 오류, 자원(메모리 등)의 부적절한 반환 등과 같이

개발자가 범할 수 있는 코딩 오류로 인해 유발 되는 보안약점

 

 

- Null Pointer 역참조 -

Null Pointer 역참조
정의 '일반적으로 그 객체가 널(Null)이 될 수 없다'라고 하는 가정을 위반했을 때
발생하는 보안 약점
발생되는 문제 크래쉬 유발, 프로그램의 비정상적인 동작
원리 포인터가 널 값을 가리킬 때, 해당 포인터를 사용하여 메모리에 접근
예방법 • None을 반환하는 함수를 사용하면 None과 다른 값(예: 0이나 빈 문자열)이
  조건문에서 False로 평가될 수 있기 때문에 실수하기 쉬움

• None이 될 수 있는 데이터를 참조하기 전에 해당 데이터의 값이 None 인지 검사하여
  시스템 오류를 줄일 수 있음

 

========================================= 안전하지 않은 코드 =========================================
	filename = request.POST.get('filename')
	# filename의 None 체크를 하지 않아 에러 발생 가능
	if (filename.count('.') > 0):

=========================================== 안전한 코드 =============================================
	filename = request.POST.get('filename')
	# filename이 None 인지 체크
	if filename is None or filename.strip() == "":
		return render(request, "/error.html", {"error": "파일 이름이 없습니다."})
	if (filename.count('.') > 0):

 

[ 문제점 ]

파이썬에서는 포인터를 사용하지는 않지만 데이터에 대한 적절한 검사를

수행하지 않을 경우 Null pointer와 유사한 None 값 참조 오류 발생

 

 

[ 해결 ]

참조하고자 하는 자원을 호출 시에는 반드시 개체가 None이 아닌지 검증

 

 

- 부적절한 자원 해제 -

부적절한 자원 해제
정의 프로그램 오류 또는 에러로 사용이 끝난 자원을 반환하지 못하는 경우에
발생 하는 보안 약점
발생되는 문제 프로그램 성능 저하, 시스템 안정성에 영향
원리 할당된 메모리를 해제하지 않거나, 사용한 파일과 소켓을 닫지 않을 경우
자원 반환을 놓친 경우에 시스템에서 자원을 계속 점유하여
자원 부족이나 불안정한 동장을 유발
예방법 • 자원을 획득하여 사용한 다음에는 반드시 자원을 해제 후 반환

 

========================================= 안전하지 않은 코드 =========================================
	# 예외 발생 상황 가정
 	raise Exception("Throwing the exception!")
	# try 절에서 할당한 자원이 반환(close)되기 전에
	# 예외가 발생하면 할당된 자원이 시스템에 반환되지 않음
	f.close()


=========================================== 안전한 코드 =============================================
		# 예외 발생 상황 가정
		raise Exception("Throwing the exception!")
	except Exception as e:
	...
	finally:
		# try 절에서 할당한 자원은
		# finally 절에서 시스템에 반환을 해야 한다
		f.close()

 

[ 문제점 ]

try 구문 내의 코드 실행 중 오류가 발생할 경우

close() 메소드가 실행되지 않아 사용한 자원이 반환되지 않음

 

 

[ 해결 ]

예외 상황이 발생하여 함수가 종료될 때, 예외의 발생 여부와 상관없이

항상 실행되는 finally 블록에서 할당 받은 모든 자원을 반환

   

 

- 신뢰할 수 없는 데이터의 역직렬화 -

신뢰할 수 없는 데이터의 역직렬화
정의 악의적인 목적을 가진 사용자가 제어할 수 있는 데이터를
역직렬화하는 과정에서 발생하는 보안 약점
발생되는 문제 무결성 침해, 원격 코드 실행, 서비스 거부 공격
원리 송신자가 네트워크를 이용해 직렬화된 정보를 수신자에게 전달하는 과정에서
공격자가 전송한 데이터 또는 저장된 스트림을 조작할 수 있는 경우
신뢰할 수 없는 역직렬화로 인한 공격 발생

직렬화(Serialization) - 프로그램에서 특정 클래스의 현재 인스턴스 상태를
다른 서버로 전달하기 위해 클래스의 인스턴스 정보를 바이트 스트림으로
복사하는 작업으로, 메모리상에서 실행되고 있는 객체의 상태를 그대로 복제해
파일로 저장하거나 수신 측에 전달
역직렬화(Deserialization) - 반대 연산으로 바이너리 파일(Binary File) 이나
바이트 스트림(Byte Stream) 으로부터 객체 구조로 복원하는 과정
예방법 • 초기화되지 않은 스택 메모리 영역의 변수는 임의값이라고 생각해서
  대수롭지 않게 생각할 수 있으나 사실은 이전 함수에서 사용되었던 내용을 포함

• 공격자는 이러한 약점을 사용하여 메모리에 저장되어 있는 값을 읽거나 특정 코드를 실행 가능

• 모든 변수를 사용 전에 반드시 올바른 초기 값을 할당함으로서 문제 예방

• 신뢰할 수 없는 데이터를 역직렬화 하지 않도록 응용 프로그램을 구성

• 민감 정보 또는 중요 정보 전송 시 암호화 통신을 적용할 수 없는 경우, 최소한 송신 측에서
  서명을 추가하고 수신 측에서 서명을 확인하여 데이터의 무결성을 검증

• 신뢰할 수 있는 데이터의 식별을 위해 역직렬화 대상의 데이터가 사전에 검증된 클래스(Class)만을
  포함하는지 검증하거나, 제한된 실행 권한만으로 역직렬화 코드를 실행

 

========================================= 안전하지 않은 코드 =========================================
	# 사용자로부터 입력받은 알 수 없는 데이터를 역직렬화
	pickled_userinfo = pickle.dump(request.POST.get('userinfo', ''))
	# 역직렬화(unpickle)
	user_obj = pickle.loads(pickled_userinfo)

=========================================== 안전한 코드 =============================================
	# 데이터 변조를 확인하기 위한 해시값
	hashed_pickle = request.POST.get("hashed_pickle", "")
	# 사용자로부터 입력받은 데이터를 직렬화(pickle)
	pickled_userinfo = pickle.dumps(request.POST.get("userinfo", ""))
	# HMAC 검증을 위한 비밀키는 생성
	m = hmac.new(key="secret_key".encode("utf-8"), digestmod=hashlib.sha512)
	# 직렬화된 사용자 입력값을 해싱
	m.update(pickled_userinfo)
	# 전달받은 해시값(hashed_pickle)과 직렬화 데이터(userinfo)의 해시값을 비교하여 검증
	if hmac.compare_digest(str(m.digest()), hashed_pickle):
		user_obj = pickle.loads(pickled_userinfo)
		return render(request, "/load_user_obj.html", {"obj": user_obj})
	else:
		return render(request, "/error.html", {"error": "신뢰할 수 없는 데이터입니다."}

 

[ 문제점 ]

신뢰할 수 없는 사용자로부터 입력 받은 코드를 역직렬화

 

 

[ 해결 ]

사용자로부터 전달받은 데이터를 HMAC을 이용하여

안전한 사용자로부터 온 것인지 검증한 후 역직렬화

     

 

 

   

시큐어 코딩 - 캡슐화


 

중요한 데이터 또는 기능성을 불충분하게 캡슐화하거나

잘못 사용함으로써 발생하는 보안약점

 

 

- 잘못된 세션에 의한 데이터 정보 노출 -

잘못된 세션에 의한 데이터 정보 노출
정의 다중 스레드 환경에서 정보를 저장하는 전역 변수가 포함되어 
서로 다른 세션에서 데이터가 공유되어 발생하는 보안 약점
발생되는 문제 크래쉬 유발, 프로그램의 비정상적인 동작
원리 여러 스레드가 동시에 싱글톤 객체에 접근할 때 발생

싱글톤 - 애플리케이션 전체에서 단 하나의 인스턴스만을 갖도록 보장하는 디자인 패턴
예방법 • 싱글톤 패턴을 사용하는 경우, 변수 범위(Scope)에 주의

• 특히 다중 스레드 환경에서 클래스 변수의 값은 하위 메소드와 공유되므로
  필요한 경우 인스턴스 변수로 선언하여 사용

 

========================================= 안전하지 않은 코드 =========================================
	class UserDescription:
		user_name = ''
	
   		def show_user_profile(self, request):
			# 클래스변수는 다른 세션과 공유되는 값이기 때문에 멀티스레드
			# 환경에서 공유되지 않아야 할 자원을 사용하는 경우
			# 다른 스레드 세션에 의해 데이터가 노출될 수 있다
			UserDescription.user_name = request.POST.get(‘name’, ‘’)

=========================================== 안전한 코드 =============================================
	def show_user_profile(self, name):
		# 인스턴스 변수로 사용해 스레드 간 공유되지 않도록 한다
		self.user_name = request.POST.get(‘name’, ‘’)

 

[ 문제점 ]

클래스 변수에 값을 할당할 경우 서로 다른 세션 간에 데이터가 공유되어

의도하지 않은 데이터가 전달

 

 

[ 해결 ]

공유가 금지된 변수는 인스턴스 변수로 선언하여 세션 간에 공유되지 않도록 조치

 

 

- 제거되지 않고 남은 디버그 코드 -

제거되지 않고 남은 디버그 코드
정의 디버그 코드가 남겨진 채로 배포될 경우 발생하는 보안 약점
발생되는 문제 공격자의 식별 과정 우회, 의도치 않은 정보 노출
원리 개발이 완료된 후 제거되지 않은 디버그 코드는 설정 등의 민감한 정보
또는 의도하지 않은 시스템 제어로 이어질 수 있는 정보를 담고 있어
공격으로 이용됨
예방법 • 소프트웨어 배포 전 반드시 디버그 코드를 확인 및 삭제

• Django 프레임워크의 경우 전역 수준에서 DEBUG 모드를 비활성화 하려면
  settings.py 파일에 설정을 하고 Flask 프레임워크는 app_run() 전에
  debug = False로 설정하면 됨

 

========================================= 안전하지 않은 코드 =========================================
	DEBUG = True

=========================================== 안전한 코드 =============================================
	DEBUG = False

 

[ 문제점 ]

개발 시 사용된 DEBUG 옵션이 True로 설정되어 있어 정보 노출 위험

 

 

[ 해결 ]

개발이 끝난 소스코드를 배포 및 운영할 경우에는 반드시 DEBUG 옵션을 False로 변경

 

========================================= 안전하지 않은 코드 =========================================
	app = Flask(__name__)
	# 디버그 모드 설정 방법1
	app.debug = True
	@app.route('/')
	def hello_world():
		return 'Hello World!'
	if __name__ == '__main__':
		app.run()
		# 디버그 모드 설정 방법2
		app.run(debug=True)

=========================================== 안전한 코드 =============================================
	app = Flask(__name__)
	app.debug = False
	@app.route('/')
	def hello_world():
		return 'Hello World!'
	if __name__ == '__main__':
		app.run()
		app.run(debug=False)

 

[ 문제점 ]

debug 모드가 True로 설정되어 정보 노출의 위험

 

 

[ 해결 ]

개발이 끝난 소스코드를 배포 및 운영 시 반드시 debug 옵션을 False로 변경

 

 

- Public 메소드로부터 반환된 Private 배열 -

Public 메소드로부터 반환된 Private 배열
정의 public으로 선언된 메소드에서 배열을 반환할 때
해당 배열의 객체가 공개되어 발생하는 보안 약점
발생되는 문제 배열에 담긴 정보 유출, 프로그램 오류 발생
원리 public으로 선언된 메소드에서 배열을 반환하면, 해당 배열의 참조 객체가
외부에 공개되어 외부에서 배열 수정과 객체 속성 변경이 가능
이러한 속성은 배열 뿐만 아니라 변경 가능한(mutable) 모든 객체에 해당
예방법 • private로 선언된 배열을 public으로 선언된 메소드로 반환하지 않도록 조치

• private 배열에 대한 복사본을 반환하도록 하고 배열의 원소에 대해서는 clone() 메소드를 통해
  복사된 원소를 저장하도록 해서 private 선언된 배열과 객체 속성에 대한 의도치 않은 수정을 방지

• 만약 배열의 원소가 String 타입 등과 같이 변경이 되지 않는 경우(immutable)에는
  private 배열의 복사본을 만들고 이를 반환하도록 작성

 

========================================= 안전하지 않은 코드 =========================================
	# private 배열을 리턴하는 public 메소드를 사용하는 경우 취약함
	def get_private_member(self):
		return self.__private_variable

=========================================== 안전한 코드 =============================================
	# private 배열을 반환하는 경우 [:]를 사용하여 외부와 내부의
	# 배열이 서로 참조되지 않도록 해야 한다
	def get_private_member(self):
		return self.__private_variable[:]

 

[ 문제점 ]

private 변수를 생성하고 이를 반환하는 public 메소드를 사용

외부에서 클래스 내에 숨겨져 있는 private 배열 값에 접근할 수 있는 문제점이 발생

 

 

[ 해결 ]

내부와 외부의 배열이 서로 참조되는 것을 예방하기 위해 [:]로

새로운 객체를 생성하여 값을 반환

 

 

- Private 배열에 Public 데이터 할당 -

Private 배열에 Public 데이터 할당 
정의 public으로 선언된 메소드의 인자가 private로 선언된 배열에 저장되면
 발생하는 보안 약점
발생되는 문제 객체의 무결성 위협
원리 public으로 선언된 메소드의 인자가 private로 선언된 배열에 저장되면
private 배열을 외부에서 접근하여 배열 수정과 객체 속성 변경이 가능
예방법 • public으로 선언된 메소드의 인자를 private 로 선언된 배열에 저장하지 않도록 조치

• 사용자가 전달한 값으로 클래스 외부에서 private 값을 변경해서는 안 되며,
  필요한 경우 별도의 인스턴스 변수로 정의하거나, 의도한 기능이라면
  전달된 값의 정상 여부를 검증한 후 적용

 

========================================= 안전하지 않은 코드 =========================================
	class UserObj:
		__private_variable = []

		def __init__(self):
			pass
    
    	# private 배열에 외부 값을 바로 대입하는 public 메소드를 사용하는
		# 경우 취약하다
		def set_private_member(self, input_list):
			self.__private_variable = input_list

=========================================== 안전한 코드 =============================================
	class UserObj:
		def __init__(self):
    		self.__privateVariable = []
	
		# private 배열에 외부 값을 바로 대입하는 경우 [:]를 사용하여
		# 외부와 내부의 배열이 서로 참조되지 않도록 해야 한다
		def set_private_member(self, input_list):
			self.__privateVariable = input_list[:]

 

[ 문제점 ]

__를 이용해서 파이썬의 내부 배열을 생성하고 외부 값을 대입하는 public 메소드를 사용

이 경우 특정 배열 타입에 따라 외부에서 private 배열을 변조할 수 있는 문제를 내포

 

 

[ 해결 ]

내부와 외부의 배열이 서로 참조되는 것을 예방하기 위해 [:]로

새로운 객체를 생성하여 값을 대입

 

 

 

 

시큐어 코딩 - API 오용


 

의도된 사용에 반하는 방법으로 API를 사용하거나,

보안에 취약한 API를 사용하여 발생할 수 있는 보안약점

 

 

- DNS lookup에 의존한 보안결정 -

DNS lookup에 의존한 보안결정
정의 DNS lookup에 의존하여  발생하는 보안 약점
발생되는 문제 서버 위장, 사용자와 특정 서버 간의 네트워크 트래픽이 공격자를 경유
원리 도메인명에 의존에서 보안결정(인증 및 접근 통제 등)을 하여
공격자가 DNS 엔트리를 속여 공격
예방법 • 보안결정에서 도메인명을 이용한 DNS lookup을 하지 않도록 한다

 

========================================= 안전하지 않은 코드 =========================================
	trusted_host = "trust.example.com"
	# 공격자에 의해 실행되는 서버의 DNS가 변경될 수 있으므로
	# 안전하지 않다
	if trusted_host == host_name:

=========================================== 안전한 코드 =============================================
	trusted_ip = "192.168.10.7“
	# 실제 서버의 IP 주소를 비교하여 DNS 변조에 대응
	dns_resolved_ip = socket.gethostbyname(host_domain_name)
	if trusted_ip == dns_resolved_ip:

 

[ 문제점 ]

도메인명을 통해 해당 요청을 신뢰할 수 있는지를 검사

공격자는 DNS 캐쉬 등을 조작해서 쉽게 이러한 보안 설정을 우회

 

 

[ 해결 ]

도메인명을 이용한 비교를 하지 말고 IP 주소를 직접 비교하도록 수정