오늘 학습 주제
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 주소를 직접 비교하도록 수정
'SK shieldus Rookies 16기' 카테고리의 다른 글
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(13일차) (0) | 2023.11.08 |
---|---|
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(12일차) (0) | 2023.11.07 |
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(10일차) (0) | 2023.11.03 |
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(9일차) (0) | 2023.11.02 |
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(8일차) (0) | 2023.11.01 |