오늘 학습 주제
1. 시큐어 코딩 개요
2. 입력 데이터 검증 및 표현
시큐어 코딩 개요
- 시큐어 코딩(Secure coding) -
소프트웨어 개발 시 안전한 코드를 제작한다는 의미
해킹을 비롯한 사이버 공격의 대상이 될 수 있는 소프트웨어의 보안 약점을
개발 단계에서 사전에 제거하는 일련의 보안 활동
- SW 개발 보안 필요성 -
《 개인 정보 보호 》
소프트웨어는 사용자의 개인 정보를 다루는 경우가 많다
보안 결함이나 취약점이 존재하면 해커가 개인 정보를 탈취하거나 유출할 수 있다
개인 정보 보호를 위한 보안이 필요
《 기업 데이터 보호 》
기업은 고객 정보, 경영 데이터, 기밀 정보 등 많은 중요한 데이터를 소프트웨어를 통해 다룬다
이러한 데이터를 보호하지 않으면 기업은 큰 손실을 입을 수 있음
《 법률 준수 》
: 많은 규제 및 법률이 개인 정보 보호 및 데이터 보안을 강제하고 있음
소프트웨어 개발 보안을 신경쓰지 않으면 법률 위반으로 인한 벌금이나 소송 위험을 초래할 수 있음
《 브랜드 이미지 》
: 보안 침해 사건이 발생하면 기업의 브랜드 이미지가 훼손될 수 있으며,
이는 장기적인 영향을 미칠 수 있음
-소프트웨어 개발 생명주기(SDLC) -
시스템의 요구분석부터 유지보수까지의 전 공정을 체계화한 절차
시스템의 개발부터 유지보수까지 어떤 작업이 이루어지는지를 단계별로 정리
프로젝트의 진행관리를 위해 각 단계별 주요 활동과 산출물로 프로젝트 진행 방향을
명확하게 파악하고 관리를 용이하게 한다
《 SDLC 모델 》
구분 | 폭포수 모델 | 프로토타입 모델 | 나선형 모델 | 개발수정 모델 |
정의 | 순차적으로 소프트웨어를 개발하는 전형적인 개발모델 |
점진적으로 시스템을 개발해 나가는 접근 방식 |
폭포수 모형과 원형모형의 장점을 수용하고 위험분석을 추가한 점증적 개발모델 |
요구사항, 분석/설계 단계 없이 일단 개발에 들어간 후 만족할 때까지 수정작업을 수행하는 방식 |
장점 | 사례가 많고 단계별 정의와 산출물이 명확하다 |
고객과의 소통이 원활하다 |
위험을 관리하는데 큰 유연성을 제공한다 |
- |
단점 | 요구사항의 변경이 어렵다 | 관리가 어렵고 개발 시간과 비용이 증가할 수 있다 |
복잡성이 있어 개발 시간과 비용이 증가할 수 있다 | - |
- 소프트웨어 개발 방법론 -
구조적 방법론 | 객체지향 방법롭 | CBD 방법론 | |
정의 | 정형화된 분석 절차에 따라 사용자 요구사항을 파악하여 문서화하는 체계적인 방법으로 비즈니스 프로세스 자동화를 목표로 하고 있는 프로세스 중심의 개발 방법 |
분석, 설계 및 개발에 있어서 객체지향 기법을 활용하여 시스템을 구축하는 방법 |
재사용이 가능한 컴포넌트의 개발 또는 사용 컴포넌트를 조합하여 애플리케이션 개발 생산성과 품질을 높이고, 시스템 유지보수 비용을 최소화할 수 있는 방법 |
특징 | • 프로세스 위주의 분석과 설계방식 • 하향식 설계 방식 • 소프트웨어의 개발이 목표인 프로세스와 산출물의 구성 • 데이터의 구성에 대한 설계 방안이 부족 • 프로젝트 관리 및 조직, 역할 등 방법론적 다른 요소들의 정의가 없다 |
• 반복적, 그리고 점증적인 개발 방식 • 재사용성의 강조 • 쉽고 표준화된 표기법 존재 • 분산객체 기술의 완벽한 지원 • DBMS의 원활한 연계 등 아직 개선의 여지가 많다 |
• 컴포넌트 기반 개발 • 반복 점진적 개발프로세스 제공 • 표준화된 산출물 작성, 컴포넌트 제작 기법으로 재사용성 향상 |
라이프 사이클 |
폭포수 모델 | 반복적 개발 | 반복적 개발 |
개발 방식 |
TOP-DOWN | BOTTOM-UP | BOTTOM-UP |
단계별 산출물 활용 |
계획 - 도메인 분석, 프로젝트 계획서 |
계획 - 비즈니스 프로세스, 개념 모델, 프로젝트 계획서 |
계획 - 비즈니스 프로세스, 개념 모델, 프로젝트 계획서 |
분석 - DFD(Data Flow Diagram) | 분석 - 유즈케이스 다이어그램, 시퀀스 다이어그램, 클래스 다이어그램 |
분석 - 유즈케이스 다이어그램, 유즈케이스 명세서, 요구사항 추적표 |
|
설계 - Structure Chart, 프로그램 사양서 |
설계-시퀀스 다이어그램, 클래스 다이어그램, 컴포넌트 다이어그램, 배포 다이어그램 |
설계 - 사용자 인터페이스 설계서, 컴포넌트 설계서, ERD 기술서, 데이터베이스 설계서 |
- SW 개발보안 방법론 -
기존의 개발방법론이 적용된 프로젝트에서 안전한 소프트웨어를 만들기 위해
요구되는 보안 활동들은 적용하는 개발방법
- SW 개발보안 모범 사례 -
《 MS-SDL 》
마이크로소프트에서 개발한 TwC를 위한 SW 개발 보안 방법론
SDL이 적용된 소프트웨어는 이전 버전에 비해 50% 이상 취약점이 감소
《 Seven Touchpoints 》
실무적으로 검증된 SW개발 보안 방법론
SW 보안의 모범 사례를 SDLC에 통합
7개의 보안강화 활동을 개발자에게 집중적으로 관리하도록 요구
《 CLASP 》
Comprehensive, Lightweight Application Security Process
SDLC 초기 단계에서 보안강화를 목적으로 하는 정형화된 프로세스
이미 운영중인 시스템에 적용하기 적합
- SW 개발 보안 적용 효과 -
- 파이썬 시큐어 코딩 -
파이썬은 플랫폼에 독립적이며 인터프리터식, 객체지향적, 동적 타입의 언어
다양한 플랫폼을 지원하며 라이브러리(모듈)가 풍부하여
여러 교육기관, 연구기관 및 산업계에서 활용도가 높이지고 있다
웹 개발 이외에도 그래픽, 머신러닝 업계에서 선호하는 언어로 선호도 1위에 오르기도 했다
선호도가 높은만큼 보안 가이드의 중요성도 높다
- 구현단계 보안약점 제거 기준 -
유형 | 주요 내용 |
입력데이터 검증 및 표현 | SQL 삽입, 코드 삽입, 경로 조작 및 자원 삽입 등 16개 항목 |
보안기능 | 적절한 인증 없는 중요 기능 허용, 부적절한 인가 등 16개 항목 |
시간 및 상태 | 경쟁 조건, 종료되지 않는 반복문 또는 재귀함수 2개 항목 |
에러 처리 | 오류 메시지 정보노출, 오류 상황 대응 부재 등 3개 항목 |
코드 오류 | Null Pointer 역참조, 부적절한 자원 해제 등 3개 항목 |
캡슐화 | 잘못된 세션에 의한 데이터 정보 노출 등 4개 항목 |
API 오용 | DNS lookup에 의한 보안 결정 1개 항목 |
입력데이터 검증 및 표현
프로그램 입력 값에 대한 검증 누락 또는 부적절한 검증, 데이터의 잘못된 형식 지정,
일관되지 않은 언어셋 사용 등으로 인해 발생되는 보안약점
SQL Injection, 크로스 사이트 스크립트 등의 공격을 유발
- SQL Injection -
SQL Injection | |
정의 | 입력 폼 및 URL 입력란에 SQL문을 삽입하여 DB로부터 정보를 열람하거나 조작할 수 있는 보안약점 |
공격 목적 및 발생되는 문제 | 정보 유출 및 조작, 원격 코드 실행, 인증 우회 |
공격 원리 | 동적쿼리(Dynamic Query)를 생성하여 개발자가 의도하지 않은 쿼리를 실행 |
예방법 | • 인자화된 쿼리를 통해 입력값을 바인딩 후 사용하여 공격으로부터 안전하게 보호 • ORM 프레임워크(Django의 querySets, SQLAlchemy 등)을 사용 • ORM은 기본적으로 모든 쿼리문에 인자화된 쿼리문을 사용하므로 공격으로부터 안전 • ORM 내에서 원시 SQL을 사용할 경우에도 외부 입력값을 인자화된 쿼리문의 바인딩 변수로 사용하면 안전한 코드를 작성 |
========================================= 안전하지 않은 코드 =========================================
# 외부로부터 입력받은 값을 검증 없이 사용할 경우 안전하지 않다
name = request.POST.get('name', ")
content_id = request.POST.get('content_id', ")
# 사용자의 검증되지 않은 입력값을 사용해 동적 쿼리문 생성
sql_query = "update board set name = " + name + " where content_id = " + content_id + ""
# 외부 입력값이 검증 없이 쿼리로 포함되어 안전하지 않다
curs.execute(sql_query)
=========================================== 안전한 코드 =============================================
# 외부 입력값 조작으로부터 안전한 인자화된 쿼리를 생성한다.
sql_query = 'update board set name=%s where content_id=%s'
# 사용자의 입력값이 인자화된 쿼리에 바인딩 후 실행되므로 안전하다.
curs.execute(sql_query, (name, content_id))
[ 문제점 ]
별도의 검증 없이 쿼리문의 인자 값으로 사용하는 단순 문자열 결합을 통해 쿼리를 생성
[ 해결 ]
입력 받은 외부 입력값을 그대로 사용하지 않고 인자화된 쿼리 생성 후
execute() 메서드의 두 번째 인자 값으로 이 값을 바인딩 해서 쿼리문을 실행
또는 포멧 지정으로 다른 명령문이 입력되지 않도록 한다
ex) Select * from Tablename where id = {}".format(id)
========================================= 안전하지 않은 코드 =========================================
# 입력값을 검증 없이 쿼리문 생성에 사용해 안전하지 않다
query=“select * from member where name=‘” + name + “’”
# 외부 입력값을 검증 없이 사용한 쿼리문을 raw()함수로 실행하면 안전하지 않다
data = Member.objects.raw(query)
=========================================== 안전한 코드 =============================================
# 외부 입력값을 raw() 함수 실행 시 바인딩 변수로 사용하여 쿼리 구조가
# 변경되지 않도록 한다.(list 형은 %s, dictionary 형은 %(key)s를 사용)
query='select * from member where name=%s'
# 인자화된 쿼리문을 사용하여 raw() 함수를 호출해 안전하다
data = Member.objects.raw(query, [name])
[ 문제점 ]
외부로부터 입력받은 외부 입력값을 쿼리문 생성에 문자열 조합으로 사용해 쿼리문을 구성
[ 해결 ]
외부 입력값을 포함하는 쿼리문 생성 자체를 인자화된 쿼리 형식으로 생성하고
raw() 메소드에서 두 번째 인자의 바인딩 변수로 사용
- 코드 삽입 -
코드 삽입 | |
정의 | 공격자가 소프트웨어의 의도된 동작을 변경하도록 임의 코드를 삽입해 소프트웨어가 비정상적으로 동작하도록 하는 보안약점 프로그래밍 언어 자체의 기능에 한해 이뤄진다는 점에서 운영체제 명령어 삽입과 다르다 |
공격 목적 및 발생되는 문제 | 웜 배포, Dos공격, 정보 유출, 시스템 탈취 |
공격 원리 | 입력값 내에 코드가 포함되는 것을 허용할 경우, 공격자는 개발자가 의도하지 않은 코드를 실행해 권한을 탈 취하거나 인증 우회, 시스템 명령어 실행 |
예방법 | • 동적코드를 실행할 수 있는 함수를 사용 X • 필요 시, 실행 가능한 동적 코드를 입력값으로 받지 않도록 외부 입력값에 대해 • 이트리스트 기반 검증을 수행 • 유효한 문자만 포함하도록 동적 코드에 사용되는 사용자 입력값을 필터링 하는 방법도 고려 |
========================================= 안전하지 않은 코드 =========================================
# 외부 입력값을 검증 없이 eval 함수에 전달할 경우 의도하지 않은 코드가
# 실행될 수 있어 위험하다
ret = eval(message)
=========================================== 안전한 코드 =============================================
# 사용자 입력을 영문, 숫자로 제한하며, 만약 입력값 내에 특수문자가 포함되어
# 있을 경우 에러 메시지를 반환 한다
if message.isalnum():
ret = eval(message)
[ 문제점 ]
입력 받은 값을 아무런 검증 없이 eval() 함수의 인자로 사용
공격자는 파이썬 코드를 통해 악성 기능 실행을 위한 라이브러리 로드 및 원격 대화형 쉘 등을 실행 가능
[ 해결 ]
외부 입력값 내에 포함된 (파이썬 코드를 실행할 수 있는) 특수 문자 등을 필터링 하는
사전 검증 코드를 추가하여 코드 삽입 공격 위험을 완화
========================================= 안전하지 않은 코드 =========================================
# 사용자에게 전달받은 함수명을 검증하지 않고 실행
# 입력값으로 “__import__(‘platform’).system()” 등을 입력 시
# 시스템 정보 노출 위험이 있다
exec('{}()'.format(function_name))
=========================================== 안전한 코드 =============================================
# 사용 가능한 함수를 화이트리스트 목록 내의 함수로 제한
if function_name in WHITE_LIST:
exec('{}()'.format(function_name))
[ 문제점 ]
입력값을 검증 없이 exec 함수의 인자로 사용하고 있다
중요 데이터 탈취 및 서버의 권한 탈취, 액세스 거부, 심지어 완전한 호스트 탈취 가능
[ 해결 ]
입력 받은 문자열 내부에서 발견된 라이브러리 이름이 사전에 정의한 화이트리스트에 포함되는지 확인
- 경로 조작 및 자원 삽입 -
경로 조작 및 자원 삽입 | |
정의 | 파일 및 서버 등 시스템 자원에 대한 접근과 식별로 시스템이 보호하는 자원에 임의로 접근할 수 있는 보안 약점 |
공격 목적 및 발생되는 문제 | 디렉토리 추적, 자원 수정과 삭제, 시스템 정보 누출, 시스템 자원 간 충돌로 인한 서비스 장애 |
공격 원리 | subprocess.popen()과 같이 프로세스를 여는 함수, os.pipe()처럼 파이프를 여는 함수, socket 연결 등에서 외부 입력값을 검증 없 이 사용할 경우 경로 조작 및 자원 삽입의 취약점이 발생 |
예방법 | • 입력값을 자원(파일, 소켓의 포트 등)의 식별자로 사용하는 경우 검증을 거치도록 하거나, 사전에 정의된 리스트에 포함 된 식별자만 사용하도록 해야 함 • 외부의 입력이 파일명인 경우에는 필터를 적용해 경로순회(directory traversal) 공격의 위험이 있는 문자( /, \, .. 등)를 제거해야 함 |
========================================= 안전하지 않은 코드 =========================================
# 입력값을 검증 없이 파일 처리에 사용했다
with open(request_file) as f
=========================================== 안전한 코드 =============================================
# 파일 명에서 경로 조작 문자열을 필터링 한다.
filename = filename.replace('.', '')
filename = filename.replace('/', '')
filename = filename.replace('\\', '')
try:
with open(filename + file_ext) as f:
[ 문제점 ]
외부 입력값으로 파일 경로 등을 입력받아 파일 처리
의도치 않은 시스템 정보노출 문제 발생 가능
[ 해결 ]
외부 입력값에서 경로 조작 문자열 ( /, \, .. 등)을 제거한 후 파일의 경로 설정에 사용
========================================= 안전하지 않은 코드 =========================================
def get_info(request):
port = int(request.POST.get('port'))
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# 외부로부터 입력받은 검증되지 않은 포트 번호를 이용하여
# 소켓을 바인딩하여 사용하고 있어 안전하지 않다
s.bind(('127.0.0.1', port))
=========================================== 안전한 코드 =============================================
ALLOW_PORT = [4000, 6000, 9000]
def get_info(request):
port = int(request.POST.get('port'))
# 사용 가능한 포트 번호를 화이트리스트 내의 포트로 제한
if port not in ALLOW_PORT:
return render(request, '/error.html', {'error':'소켓연결 실패'})
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
[ 문제점 ]
외부 입력을 소켓 포트 번호로 그대로 사용
기존 자원과의 충돌로 의도치 않은 에러 발생 가능
[ 해결 ]
허용 가능한 목록을 설정한 후 목록 내에 포함된 포트만 할당
- 크로스사이트 스크립트(XSS) -
크로스사이트 스크립트(XSS) | |
정의 | 웹사이트에 악성 코드를 삽입하는 공격 방법 |
공격 목적 및 발생되는 문제 | 사용자의 세션을 탈취, 악성코드가 있는 페이지로 리다이렉트, 내부 네트워크 포트스캔 |
공격 원리 | 웹 응용프로그램을 속여 브라우저에서 실행될 수 있는 형식의 데이터(코드)를 다른 사용자에게 전달 |
예방법 | • 외부 입력값 또는 출력값에 스크립트가 삽입되지 못하도록 문자열 치환 함수를 사용하여 &<>*‘/() 등을 & < > " ' / ( )로 치환하거나, html라이브러리의 escape()를 사용해 문자열을 변환 • HTML 태그를 허용해야 하는 게시판에서는 허용할 HTML 태그들을 화이트 리스트로 만들어 해당 태그만 지원 • Django, Flask 등을 사용하는 경우 외부 입력값에 악의적인 스크립트가 삽입되지 못하도록 프레임워크 자체에서 XSS 공격에 사용될 수 있는 문자를 HTML 특수문자로 치환하여 응답 페이지를 생성하므로 XSS 공격으로부터 안전 • 프레임워크 자체에서 XSS 공격으로부터 보호해 주는 기능이 있더라도 완전하지 않은 경우도 있고 개발자의 실수로 보호기능이 무효화 되는 경 우가 있으므로 주의를 기울여야 함 |
공격 유형 1 : Reflective XSS (or Non-persistent XSS) | |
정의 | 공격 코드를 사용자의 HTTP 요청에 삽입한 후, 해당 공격 코드를 서버 응답 내용에 그대로 반사 (Reflected)시켜 브라우저에서 실행하는 공격기법 |
공격 목적 및 발생되는 문제 | 피해자가 링크를 방문하면 스크립트가 피해자의 브라우저에서 자동으로 실행 |
공격 원리 | 악의적으로 제작된 링크를 사용자가 클릭하도록 유도 |
공격 유형 2 : Persistent XSS (or Stored XSS) | |
정의 | 사용자 입력(코드)이 서버에 저장되고, 이 데이터가 다른 사용자들에게 전달될 때 발생 |
공격 목적 및 발생되는 문제 | 정보 유출 |
공격 원리 | 프로필 입력 폼에 악성 스크립트를 주입해 다른 사용자가 프로필을 방문하면 브라우저에서 자동으로 코드가 실행 |
공격 유형 3 : DOM XSS (or Client-Side XSS) | |
정의 | JavaScript의 검증 로직을 무효화 하는 것을 목표로 하는 공격 기법 |
공격 목적 및 발생되는 문제 | 정보 유출 |
공격 원리 | HTTP 응답에 페이로드를 포함하는 대신 DOM 또는 문서 개체 모델을 수정해 브라우저와 독립적인 공격을 실행 |
========================================= 안전하지 않은 코드 =========================================
# mark_safe함수는 Django의 XSS escape 정책을 따르지 않는다
object_link = mark_safe(object_link)
=========================================== 안전한 코드 =============================================
# 신뢰할 수 없는 데이터에 대해서는 mark_safe 함수를 사용해선 안 된다
# object_link = mark_safe(object_link)
[ 문제점 ]
mark_safe를 사용하여 XSS 공격에 대한 보호 정책이 무력화
[ 해결 ]
mark_safe 함수를 사용할 경우에는 각별한 주의가 필요하고
신뢰할 수 없는 데이터에 대해서는 mark_safe 함수를 사용하지 않는다
========================================= 안전하지 않은 코드 =========================================
<div class="content">
{% autoescape off %}
<!-- autoescape off로 설정하면 해당 블록내의 데이터는 XSS 공격에
노출될 수 있다 -->
{{ content }}
{% endautoescape %}
</div>
<div class="content2">
<!-- safe 필터 사용으로 XSS 공격에 노출될 수 있다 -->
{{ content | safe }}
</div>
=========================================== 안전한 코드 =============================================
<div class="content">
{% autoescape on %}
<!--autoescape on으로 해당 블록내의 데이터는 XSS 공격에 노출되지 않음. -->
{{ content }}
{% endautoescape %}
</div>
<div class="content2">
<!-- 검증되지 않은 데이터에는 safe 필터를 사용하지 않는다. -->
{{ content }}
</div>
[ 문제점 ]
autoescape 블록 사용 시 설정값을 off로 하고 개별 변수에 대해서 safe 필터를 사용
크로스사이트 스크립트 공격에 노출 가능
[ 해결 ]
신뢰할 수 없는 입력값 또는 동적 데이터에 대해서는 autoescape 옵션 값을 on으로 설정해야 하며
safe 필터를 부득이 하게 사용할 경우에는 추가적인 보안대책이 필요
========================================= 안전하지 않은 코드 =========================================
# 사용자의 입력을 아무런 검증 또는 치환 없이 동적 웹페이지에 사용하고 있어
# XSS 공격이 발생할 수 있다
return render_template('search.html', search_keyword=search_keyword)
=========================================== 안전한 코드 =============================================
# 동적 웹페이지 생성에 사용되는 데이터는
# HTML 엔티티코드로 치환하여 표현해야 한다
escape_keyword = html.escape(search_keyword)
return render_template('search.html', search_keyword=escape_keyword)
[ 문제점 ]
autoescape 블록 사용 시 설정값을 off로 하고 개별 변수에 대해서 safe 필터를 사용
XSS 공격 발생 가능
[ 해결 ]
신뢰할 수 없는 입력값 또는 동적 데이터에 대해서는 autoescape 옵션 값을 on으로 설정해야 하며
safe 필터를 부득이 하게 사용할 경우에는 추가적인 보안대책이 필요
- 운영체제 명령어 삽입 -
운영체제 명령어 삽입 | |
정의 | 운영체제 명령어의 일부 또는 전부로 구성된 입력값으로 인해 의도하지 않은 시스템 명령어가 실행되는 취약점 |
공격 목적 및 발생되는 문제 | 권한 변경, 시스템 동작 및 운영에 문제 발생 |
공격 원리 | 웹에서 시스템 명령어를 실행시킬 수 있는 환경을 제공한 대상에게 실행 |
예방법 | • 입력값에 시스템 명령어를 포함하는 경우 |, ;, &, :, >, <, `, \, ! 과 같이 멀티라인 및 리다이렉트 문 자 등을 필터링 하고 명령 을 수행할 파일명과 옵션을 제한해 인자로만 사용될 수 있도록 해야 함 • 외부 입력에 따라 명령어를 생성하거나 선택이 필요한 경우에는 명령어 생성에 필요한 값들을 미 리 지정해 놓고 사용해야 함 |
========================================= 안전하지 않은 코드 =========================================
def execute_command(request):
app_name_string = request.POST.get('app_name','')
# 입력 파라미터를 제한하지 않아 외부 입력값으로 전달된
# 모든 프로그램이 실행될 수 있음
os.system(app_name_string)
=========================================== 안전한 코드 =============================================
ALLOW_PROGRAM = ['notepad', 'calc']
def execute_command(request):
app_name_string = request.POST.get('app_name','')
# 입력받은 파라미터가 허용된 시스템 명령어 목록에 포함되는지 검사
if app_name_string not in ALLOW_PROGRAM:
[ 문제점 ]
해당 프로그램에서 실행할 프로그램을 제한하지 않고 있기 때문에
외부의 공격자는 원하는 모든 프로그램을 실행
[ 해결 ]
사전에 화이트 리스트 파라미터 배열을 정의한 후 외부의 입력에 따라 적절한 파라미터를 선택하도록 하여
외부의 부적절한 입력이 명령어로 사용되는 것을 금지
========================================= 안전하지 않은 코드 =========================================
# 입력받은 파라미터를 제한하지 않아 전달된 모든 프로그램이 실행될 수 있음
cmd_str = “cmd /c backuplog.bat ” + date
subprocess.run(cmd_str, shell=True)
=========================================== 안전한 코드 =============================================
for word in ['|', ';', '&', ':', '>', '<', '`', '\\', '!']:
date = date.replace(word, “”)
# re.sub 함수를 사용해 특수문자를 제거하는 방법도 있다
# date = re.sub('[|;&:><`\\\!]', '', date)
# shell=True 옵션은 제거 하고 명령과 인자를 배열로 입력
subprocess.run(["cmd", "/c", "backuplog.bat", date])
[ 문제점 ]
입력값으로 받은 파라미터를 별도의 검증 없이 subprocess의 인자 값으로 사용
[ 해결 ]
운영체제 명령어 실행 시에는 외부에서 들어오는 값에 의하여 멀티라인을 지원하는
특수문자(|, ;, &, :, `, \, !)나 파일 리다이렉트 특수문자( >, >> )등을 제거하여 원하지 않는
운영체제 명령어가 실행될 수 없도록 필터링을 수행
- 위험한 형식 파일 업로드 -
위험한 형식 파일 업로드 | |
정의 | 서버 측에서 실행 가능한 스크립트 파일(asp, jsp, php, sh 파일 등)을 업로드 가능하게 하여 공격자가 웹을 통해 시스템을 제어할 수 있는 보안약점 |
공격 목적 및 발생되는 문제 | 시스템 침해 사고 유발, 웹셀 공격 |
공격 원리 | 서버에 실행 가능한 스크립트 파일(asp, jsp, php, sh 파일 등)을 업로드하고, 이 파일을 공격자가 웹을 통해 직접 실행하여 시스템 내부 명령어를 실행하거나 외부와 연결해 시스템을 제어 |
예방법 | • 공격을 방지하기 위해서 특정 파일 유형만 허용하도록 화이트리스트 방식으로 파일 유형을 제한 • 파일의 확장자 및 업로드 된 파일의 Type도 함께 확인 • 파일 크기와 개수를 제한하여 시스템 자원 고갈 등의 서비스 거부 공격이 발생하지 않도록 제한 • 업로드 된 파일을 웹 루트 폴더 외부에 저장해 URL을 통해 파일을 실행할 수 없도록 해야함 • 가능하면 업로드 된 파일의 이름은 공격자가 추측할 수 없는 무작위한 이름으로 변경 후 저장 • 업로드 된 파일을 저장시 최소 권한만 부여하고 실행 여부를 확인하여 실행 권한을 삭제해야 함 |
========================================= 안전하지 않은 코드 =========================================
# 사용자가 업로드하는 파일을 검증 없이 저장하고 있어
# 안전하지 않다
upload_file = request.FILES['upload_file']
fs = FileSystemStorage(location='media/screenshot', base_url='media/screenshot')
# 업로드 하는 파일에 대한 크기, 개수, 확장자 등을 검증하지 않음
=========================================== 안전한 코드 =============================================
# 업로드 하는 파일 개수, 크기, 확장자 제한
FILE_COUNT_LIMIT = 5
# 업로드 하는 파일의 최대 사이즈 제한 예 ) 5MB - 5*1024*1024
FILE_SIZE_LIMIT = 5242880
# 허용하는 확장자는 화이트리스트로 관리한다.
WHITE_LIST_EXT = [
'.jpg',
'.jpeg'
]
def file_upload(request):
# 파일 개수 제한
if len(request.FILES) == 0 or len(request.FILES) > FILE_COUNT_LIMIT:
return render(request, '/error.html', {'error': '파일 개수 초과'})
for filename, upload_file in request.FILES.items():
# 파일 타입 체크
if upload_file.content_type != 'image/jpeg':
return render(request, '/error.html', {'error': '파일 타입 오류'})
# 파일 크기 제한
if upload_file.size > FILE_SIZE_LIMIT:
return render(request, '/error.html', {'error': '파일사이즈 오류'})
# 파일 확장자 검사
file_name, file_ext = os.path.splitext(upload_file.name)
if file_ext.lower() not in WHITE_LIST_EXT:
return render(request, '/error.html', {'error': '파일 타입 오류'})
[ 문제점 ]
업로드 대상 파일 개수, 크기, 확장자 등의 유효성 검사를 하지 않고 파일 시스템에 그대로 저장할 경우
공격자에 의해 악성코드, 쉘코드 등 위험한 형식의 파일이 시스템에 업로드될 수 있음
[ 해결 ]
업로드 하는 파일의 개수, 크기, 파일 확장자 등을 검사해 업로드를 제한
- 신뢰되지 않은 URL 주소로 자동접속 연결 -
신뢰되지 않은 URL 주소로 자동접속 연결 | |
정의 | 검증되지 않은 외부 입력값이 URL링크 생성에 사용되어 악의적인 사이트로 자동 접속될 수 있는 취약점 |
공격 목적 및 발생되는 문제 | 악성코드 설치, 정보 노출 |
공격 원리 | 입력하는 값을 외부 사이트 주소로 사용해 해당 사이트로 자동 접속하는 서버 프로그램을 피싱 (Phishing) 공격하여 정상적인 폼 요청을 변조해 사용자가 위험한 URL로 접속하도록 유도 |
예방법 | • 리다이렉션을 허용하는 모든 URL을 서버 측 화이트리스트로 관리하고 사용자 입력값을 리다이렉션 할 URL이 존재하는지 검증해야 함 • 사용자 입력값이 화이트리스트로 관리가 불가능하고 리다이렉션 URL의 인자 값으로 사용되어야만 하는 경우는 모든 리다이렉션에서 프로토콜 과 host 정보가 들어가지 않는 상대 URL(relative)을 사용 및 검증해야함 • 절대 URL(absoute URL)을 사용할 경우 리다이렉션을 실행하기 전에 사용자 입력 URL이 https://myhompage.com/ 처럼 서비스하고 있는 URL로 시작하는지를 확인해야함 |
========================================= 안전하지 않은 코드 =========================================
# 사용자 입력에 포함된 URL 주소로 리다이렉트 하는 경우
# 피싱 사이트로 접속되는 등 사용자가 피싱 공격에 노출될 수 있다
return redirect(url_string)
=========================================== 안전한 코드 =============================================
ALLOW_URL_LIST = [
'127.0.0.1',
'192.168.0.1',
'192.168.0.100',
'https://login.myservice.com',
'/notice',
]
def redirect_url(request):
url_string = request.POST.get('url', '')
# 이동할 수 있는 URL 범위를 제한하여
# 위험한 사이트의 접근을 차단하고 있다
if url_string not in ALLOW_URL_LIST:
[ 문제점 ]
사용자로부터 입력받은 url 주소를 검증 없이 redirect 함수의 인자로 사용
사용자가 의도하지 않은 사이트로 접근하도록 하거나 피싱(Phishing)공격에 노출
[ 해결 ]
화이트리스트로 사전에 정의된 안전한 웹사이트에 한하여 리다이렉트
- 부적절한 XML 외부 개체 참고 -
부적절한 XML 외부 개체 참고 | |
정의 | 서버에서 XML 외부 엔티티를 처리할 수 있도록 설정된 경우에 발생하는 취약점 |
공격 목적 및 발생되는 문제 | 서버 파일 접근, 불필요한 자원 사용, 인증 우회, 정보 노출 |
공격 원리 | XML파서에 외부 개체를 삽입한 XML을 주입하여 서버에서 외부 개체를 파싱 |
예방법 | • 로컬 정적 DTD를 사용하도록 설정하고, 외부에서 전송된 XML 문서에 포함된 DTD를 완전하게 비활성화해야 함 • 비활성화를 할 수 없는 경우에는 외부 엔티티 및 외부 문서 유형 선언을 각 파서에 맞는 고유한 방식으로 비활성화 해야 함 • 외부 라이브러리를 사용할 경우 기본적으로 외부 엔티티에 대한 구문 분석 기능을 제공하는지 확인 필요 • 제공이 되는 경우 해당 기능을 비활성화 할 수 있는 방법을 확인해 외부 엔티티 구문 분석 기능을 비활성화 해야 함 • XML 파서의 한 종류인 lxml의 경우 외부 엔티티 구문 분석 옵션인 resolve_entities 옵션을 비활성화 해야 함 • 외부 문서 조회 시 네트워크 액세스를 방지하는 no_network 옵션이 활성화(True) 되어 있는지도 확인해야 함 |
========================================= 안전하지 않은 코드 =========================================
# 외부 일반 엔티티를 포함하는 설정을 True로 적용할 경우 취약하다
parser.setFeature(feature_external_ges, True)
=========================================== 안전한 코드 =============================================
parser.setFeature(feature_external_ges, False)
[ 문제점 ]
외부 엔티티를 처리하는 방식의 옵션(feature_external_ges)을 True로 설정
[ 해결 ]
sax 패키지를 사용해 XML을 파싱할 경우, 외부 엔티티를 처리하는 방식의 옵션(feature_external_ges)을 False로 설정
- XML 삽입 -
XML 삽입 | |
정의 | XML 구조를 조작하여 허가되지 않은 데이터를 열람하거나 인증절차를 우회할 수 있는 보안약점 |
공격 목적 및 발생되는 문제 | 서버 파일 접근, 불필요한 자원 사용, 인증 우회, 정보 노출 |
공격 원리 | 입력값이 XQuery 또는 XPath 쿼리문을 생성하는 문자열로 사용되어 공격자가 쿼리문의 구조를 임의로 변경하고 임의의 쿼리를 실행 |
예방법 | • XQuery 또는 XPath 쿼리에 사용되는 외부 입력 데이터에 대하여 특수문자 및 쿼리 예약어를 필터링 하고 인자화된 쿼리문을 지원하는 XQuery 를 사용해야 함 |
========================================= 안전하지 않은 코드 =========================================
# 검증되지 않은 외부 입력값 user_name을 사용한 안전하지 않은
# 질의문이 query 변수에 저장
query = "/collection/users/user[@name='" + user_name + "']/home/text()"
elmts = root.xpath(query)
=========================================== 안전한 코드 =============================================
# 외부 입력값을 paramname으로 인자화 해서 사용
query = '/collection/users/user[@name = $paramname]/home/text()'
elmts = root.xpath(query, paramname=user_name)
[ 문제점 ]
xml.etree.ElementTree 모듈은 제한적인 Xpath 기능을 제공하며,
Xpath 표현식을 인자화해서 사용하는 방법을 제공하지 않는다
[ 해결 ]
파이썬 3.3 이후 보안상의 이유로 금지된 xml.etree.ElementTree 모듈 대신
lxml 라이브러리를 사용하고, 외부 입력값은 인자화해서 사용
- LDAP 삽입 -
LDAP 삽입 | |
정의 | 웹 어플리케이션에서 악의적인 LDAP문을 이용하여 서버에서 실행되도록 하는 취약점 |
공격 목적 및 발생되는 문제 | 권한 변경, 시스템 동작 및 운영에 문제 발생 |
공격 원리 | 입력값을 적절한 처리 없이 LDAP 쿼리문이나 결과의 일부로 사용하는 경우, LDAP 쿼리문이 실행될 때 공격자는 LDAP 쿼리문의 내용을 마음대 로 변경 LDAP 서버는 사내 또는 방화벽 안에 존재하며 악성코드가 포함된 이메일등을 통해 내부에 침투 후 작동 |
예방법 | • 올바른 인코딩(Encoding) 함수를 사용해 모든 변수 이스케이프(Escape) 처리 • 화이트리스트 방식의 입력값 유효성 검사 • 사용자 패스워드와 같은 민감한 정보가 포함된 필드 인덱싱 • LDAP 바인딩 계정에 할당된 권한 최소화 |
========================================= 안전하지 않은 코드 =========================================
# 사용자 입력을 필터링 하지 않는 경우 공격자의 권한 상승으로
# 이어질 수 있다
search_str = '(&(objectclass=%s))' % search_keyword
=========================================== 안전한 코드 =============================================
# 사용자의 입력에 필터링을 적용하여 공격에 사용될 수 있는 문자를
# 이스케이프하고 있다
escpae_keyword = escape_filter_chars(search_keyword)
search_str = '(&(objectclass=%s))' % escpae_keyword
[ 문제점 ]
사용자의 입력을 그대로 LDAP 질의문에 사용
권한 상승 등의 공격에 노출
[ 해결 ]
사용자의 입력 중 LDAP 질의문에 사용될 변수를 이스케이프 하여
질의문 실행 시 공격에 노출되는 것을 예방
- 크로스사이트 요청 위조(CSRF) -
크로스사이트 요청 위조(CSRF) | |
정의 | 특정 웹사이트에 대해 사용자가 인지하지 못한 상황에서 사용자의 의도와는 무관하게 공격자가 의도한 행위 (수정, 삭제, 등록 등)를 요청하게 하는 공격 |
공격 목적 및 발생되는 문제 | 시스템 동작 및 운영에 문제 발생 |
공격 원리 | 사용자가 웹사이트에 로그인한 상태에서 사이트 간 요청 위조 공격 코드가 삽입된 페이지를 열면 이후에는 사용자의 행동과 관계없이 사용자의 웹 브라우저와 공격 대상 웹사이트 간의 상호작용이 이루어져 다양한 공격이 가능 |
예방법 | • 해당 요청이 정상적인 사용자의 정상적인 절차에 의한 요청인지를 구분하기 위해 세션별로 CSRF 토큰을 생성하여 세션에 저장 • 사용자가 작업 페이지를 요청할 때마다 hidden 값으로 클라이언트에게 토큰을 전달 • 해당 클라이언트의 데이터 처리 요청 시 전달되는 CSRF 토큰값을 체크하여 요청의 유효성을 검사 하도록 함 • Django 프레임워크와 Flask 프레임워크는 미들웨어와 프레임워크에서 기본적으로 CSRF Token을 사용해서 CSRF 공격으로부터 보호하는 기능 을 제공함 • 해당 기능을 사용하기 위해 form 태그 내부에 csrf_token을 사용해야 함 |
========================================= 안전하지 않은 코드 =========================================
# MIDDLEWARE 목록에서 CSRF 항목을 삭제 또는 주석처리 하면
# Django 앱에서 CSRF 유효성 검사가 전역적으로 제거된다
# 'django.middleware.csrf.CsrfViewMiddleware',
=========================================== 안전한 코드 =============================================
# MIDDLEWARE 목록에서 CSRF 항목을 활성화 한다
'django.middleware.csrf.CsrfViewMiddleware',
[ 문제점 ]
미들웨어의 CSRF 옵션을 비활성하거나 템플릿에서 csrf_exempt decorator를 사용
CSRF 공격에 노출
[ 해결 ]
미들웨어의 CSRF 기능을 활성화
템플릿 페이지에는 csrf_token을 form 태그 안에 명시 해야 미들웨어에서 정상적으로 CSRF 기능을 사용
========================================= 안전하지 않은 코드 =========================================
# csrf.exempt 데코레이터로 미들웨어에서 보호되는 CSRF 기능을 해제한다
@csrf.exempt
=========================================== 안전한 코드 =============================================
# csrf_exempt 데코레이터를 삭제하거나 주석 처리한다.
# @csrf_exempt
[ 문제점 ]
미들웨어에 CSRF 검증 기능이 활성화 되어 있어도 View에서 CSRF 기능을 해제하는 경우에는
해당 요청에 대해서 CSRF 검증 기능을 사용하지 않게 된다
[ 해결 ]
CSRF 기능을 해제해야 하는 경우는 미들 웨어의 CSRF 기능을 전역적으로 비활성화 하기 보다는
미들웨어의 CSRF 기능은 활성화 하고 필요한 요청에 대해서만
csrf_exempt 데코레이터를 사용하여야 하고 이 경우에 크로스사이트 요청 위조의
위협에 노출될 수 있으므로 주의를 기울여야 한다
이때, 취약점이지만 비즈니스에서 필요로 할 수도 있으며 대체가 불가능 할 수도 있으니
들어간 경위를 잘 확인해서 판단을 내려야 한다
========================================= 안전하지 않은 코드 =========================================
<!--html page-->
<form action="" method="POST">
<!-- form 태그 내부에 csrf_token 미적용-->
=========================================== 안전한 코드 =============================================
<!--html page-->
<form action="" method="POST">
{% csrf_token %} <!--csrf_token 사용->
[ 문제점 ]
미들웨어에서 CSRF 기능을 활성화해도 템플릿 페이지에 CSRF 토큰을 명시하지 않을 경우
CSRF 검증 기능 사용 불가
[ 해결 ]
미들웨어에서 CSRF 기능을 활성화한 후에 템플릿 페이지에서는 csrf_token 값을 명시하여야만
정상적인 CSRF 검증 기능 사용 가능
========================================= 안전하지 않은 코드 =========================================
from flask import Flask
app = Flask(__name__)
=========================================== 안전한 코드 =============================================
# CSRF 설정 추가
csrf = CSRFProtect(app)
app = Flask(__name__)
app.config[‘SECRET_KEY’] = os.environ.get('SECRET_KEY')
csrf.init_app(app)
[ 문제점 ]
CSRF 설정이 되지 않은 상태
[ 해결 ]
Flask 프레임워크를 사용해 웹 애플리케이션을 구축하는 경우,
CSRF를 방지하려면 Flask-WTF extension의 CSRFProtect를 사용
========================================= 안전하지 않은 코드 =========================================
<form action="" method="POST">
<!-- form 태그 내부에 csrf_token 미적용-->
=========================================== 안전한 코드 =============================================
<form action="" method="POST">
<!-- form 태그 내부에 csrf_token 적용-->
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
[ 문제점 ]
템플릿 페이지에도 csrf_token 값을 명시해줘야 정상적인 CSRF 검증이 수행
[ 해결 ]
form 태그 안에 hidden input 값으로 {{ csrf_token }} 값을 명시
- 서버사이드 요청 위조 -
서버사이드 요청 위조 | |
정의 | 검증 절차를 거치지 않은 사용자 입력값을 내부 서버간의 요청에 사용해 악의적인 행위가 발생할 수 있는 보안약점 |
공격 목적 및 발생되는 문제 | 비정상적인 동작을 유도, 신뢰된 네트워크에 있는 데이터를 획득 |
공격 원리 | 외부에 노출된 웹 서버가 취약한 애플리케이션을 포함하는 경우 공격자는 URL 또는 요청문을 위조해 접근통제를 우회 |
예방법 | • 식별 가능한 범위 내에서 사용자의 입력값을 다른 시스템의 서비스 호출에 사용하는 경우, 사용자의 입력값을 화이트리스트 방식으로 필터링함 • 부득이하게 사용자가 지정하는 무작위의 URL을 받아들여야 하는 경우라면 내부 URL을 블랙리스트로 지정 하여 필터링 함 • 같은 내부 네트워크에 있더라도 기기 인증, 접근권한을 확인해 요청이 이루어질 수 있도록 함 |
========================================= 안전하지 않은 코드 =========================================
# 사용자가 입력한 주소를 검증하지 않고 HTTP 요청을 보낸 후
# 응답을 사용자에게 반환
result = requests.get(addr).text
=========================================== 안전한 코드 =============================================
# 허용하는 도메인을 화이트리스트에 정의할 경우 DNS rebinding 공격 등에
# 노출될 위험이 있어 신뢰할 수 있는 자원에 대한 IP를 사용해
# 검증하는 것이 조금 더 안전하다
ALLOW_SERVER_LIST = [
'https://127.0.0.1/latest/',
'https://192.168.0.1/user_data',
'https://192.168.0.100/v1/public',
]
def call_third_party_api(request):
addr = request.POST.get('address', '')
# 사용자가 입력한 URL을 화이트리스트로 검증한 후 그 결과를 반환하여
# 검증되지 않은 주소로 요청을 보내지 않도록 제한한다
if addr not in ALLOW_SERVER_LIST:
return render(request, '/error.html', {‘error’ = '허용되지 않은 서버입니다.'})
[ 문제점 ]
사용자로부터 입력된 URL 주소를 검증 없이 사용
의도하지 않은 다른 서버의 자원에 접근
[ 해결 ]
사전에 정의된 서버 목록을 정의하고 매칭되는 URL만 사용하여
URL 값을 임의로 조작 불가
- HTTP 응답분할 -
HTTP 응답분할 | |
정의 | 분할된 HTTP의 응답에 악의적 코드를 삽입, 실행 할 수 있는 취약점 |
공격 목적 및 발생되는 문제 | XSS 및 캐시훼손(Cache Poisoning) |
공격 원리 | HTTP 요청 내의 파라미터가 HTTP 응답 헤더에 포함되어 사용자에게 다시 전달될 때, 입력값에 CR(Carriage Return)이나 LF(Line Feed)와 같은 개행문자가 존재하면 HTTP 응답이 2개 이상으로 분리될 수 있다. 공격자는 개행문자를 이용해 첫 번째 응답을 종료 시키고, 두 번째 응답에 악의적인 코드를 주입해 공격을 수행한다 |
예방법 | • 요청 파라미터의 값을 HTTP 응답 헤더에 포함시킬 경우 CR(\r), LF(\n)와 같은 개행문자를 제거해야 함 • 외부 입력값이 헤더, 쿠키, 로그 등에 사용될 경우에는 항상 개행 문자를 검증하고 가능하다면 헤더에 사용되는 예약어 등을 화이트리스트로 제한해야 함 |
========================================= 안전하지 않은 코드 =========================================
# 외부 입력값을 검증 또는 필터링 하지 않고
# 응답 헤더의 값으로 포함시켜 회신한다
......
res = HttpResponse()
=========================================== 안전한 코드 =============================================
# 허용하는 도메인을 화이트리스트에 정의할 경우 DNS rebinding 공격 등에
# 응답헤더에 포함될 수 있는 외부 입력값 내의 개행 문자를 제거한다
content_type = content_type.replace('\r', '')
content_type = content_type.replace('\n', '')
......
res = HttpResponse()
[ 문제점 ]
개행문자로 인해 여러 개의 응답으로 분할되어 사용자에게 전달
[ 해결 ]
\r, \n과 같은 문자에 대해 치환 또는 예외처리를 적용해
응답분할이 발생하지 않도록 예방
- 정수형 오버플로우 -
정수형 오버플로우 | |
정의 | 변수의 크기범위를 넘어선 값이 저장되어 프로그램이 예기치 않게 동작하게 되는 취약점 |
공격 목적 및 발생되는 문제 | 반복문 제어, 메모리 할당, 메모리 복사 등을 위한 조건으로 사용자가 제공하는 입력값을 사용하는 과정에서 정수형 오버플로우가 발생하는 경우 보안상 문제를 유발 |
공격 원리 | 정수형 크기가 고정된 상태에서 변수가 저장할 수 있는 범위를 넘어선 값을 저장하려 할 때 실제 저장되는 값이 의도치 않게 아주 작은 수 또는 음수가 되어 프로그램이 예기치 않게 동작 |
예방법 | • 데이터 타입의 표현 방식과 최대 크기를 반드시 확인 • numpy는 기본적으로 64비트 길이의 정수형 변수를 사용하며, 변수가 표현할 수 없는 큰 크기의 숫자는 문자열 형식(object)으로 변환하는 기능을 제공함 하지만, 64비트를 넘어서는 크기의 숫자는 제대로 처리불가 • 변수에 값 할당 전에 반드시 변수의 최소 및 최대값을 확인하고, 범위를 넘어서는 값을 할당하지 않는지 테스트 |
========================================= 안전하지 않은 코드 =========================================
res = np.power(number, pow, dtype=np.int64)
# 64비트를 넘어서는 숫자와 지수가 입력될 경우 오버플로우가 발생해 결과값이 0이 된다
=========================================== 안전한 코드 =============================================
calculated = number ** pow
# 파이썬 기본 자료형으로 큰 수를 계산한 후 이를 검사해 오버플로우 탐지
if calculated > MAX_NUMBER or calculated < MIN_NUMBER:
# 오버플로우 탐지 시 비정상 종료를 나타내는 –1 값 반환
return –1
res = np.power(number, pow, dtype=np.int64)
[ 문제점 ]
계산 가능한 숫자에 대한 검증이 없어 에러는 발생하지 않지만
반환값을 처리하는 함수에서 예기치 않은 오류가 발생
[ 해결 ]
오버플로우가 발생하지 않는 파이썬 기본 자료형에 계산 결과값을 저장한 후
그 값을 검사해 오버플로우 여부를 확인
- 보안기능 결정에 사용되는 부적절한 입력값 -
보안기능 결정에 사용되는 부적절한 입력값 | |
정의 | 응용 프로그램이 외부 입력값에 대한 신뢰를 전제로 보호 메커니즘을 사용하는 경우 공격자가 입력값을 조작하여 보호 메커니즘을 우회하는 취약점 |
공격 목적 및 발생되는 문제 | 보안 우회 |
공격 원리 | 인증이나 인가와 같은 보안 결정이 입력값(쿠키, 환경변수, 히든필드 등)에 기반을 두어 수행되는 경우 공격자는 입력값을 조작해 응용프로그램의 보안을 우회 |
예방법 | • 상태 정보나 민감한 데이터, 사용자 세션 정보와 같은 중요 정보는 서버에 저장하고 보안확인 절차도 서버에서 실행 • 보안설계 관점에서 신뢰할 수 없는 입력값이 응용 프로그램 내부로들어올 수 있는 지점을 검토하고, 민감한 보안 기능 실행에 사용되는 입력값을 식별해 입력값에 대한 의존성을 없애는 구조로 변경 가능한지 분석 |
========================================= 안전하지 않은 코드 =========================================
# 쿠키에서 권한 정보를 가져 온다
role = request.COOKIE['role']
=========================================== 안전한 코드 =============================================
# 세션에서 권한 정보를 가져옴
role = request.session['role'
[ 문제점 ]
쿠키에서 등급을 가져와 관리자 여부를 확인
[ 해결 ]
중요 기능 수행을 위한 데이터는 위변조 가능성이 높은 쿠키보다 세션에 저장
- 포맷 스트링 삽입 -
포맷 스트링 삽입 | |
정의 | 입력된 값을 검증하지 않고 입·출력 함수의 포맷 문자열로 그대로 사용하는 경우 발생할 수 있는 보안약점 |
공격 목적 및 발생되는 문제 | 권한 변경, 시스템 동작 및 운영에 문제 발생 |
공격 원리 | 공격자는 포맷 문자열을 이용해 취약한 프로세스를 공격하거나 메모리 내용을 읽고 사용하거나 권한을 취득해 임의의 코드를 실행 |
예방법 | • 포맷 문자열을 처리하는 함수 사용 시 사용자 입력값을 직접적으로 포맷 문자열로 사용하거나 포맷 문자열 생성에 포함시키지 않아야 함 • 사용자로부터 입력 받은 데이터를 포맷 문자열로 사용하고자 하는 경우에는 서식 지정자를 포함하지 않거나 파이썬의 내장함수 또는 내장변수 등이 포함되지 않도록 해야 함 |
========================================= 안전하지 않은 코드 =========================================
format_string = request.POST.get('msg_format', '')
# 내부의 민감한 정보가 외부로 노출될 수 있다.
# 사용자가 입력한 문자열을 포맷 문자열로 사용하고 있어 안전하지 않다
message = format_string.format(user=user_info)
=========================================== 안전한 코드 =============================================
# 사용자가 입력한 문자열을 포맷 문자열로 사용하지 않아 안전하다
message = 'user name is {}'.format(user_info.name)
[ 문제점 ]
외부에서 입력받은 문자열을 바로 포맷스트링으로 사용
내부 정보가 외부로 노출
[ 해결 ]
외부에서 입력 받은 문자열은 반드시 포맷 지정자를 이용해 바인딩 후 사용
참고
'SK shieldus Rookies 16기' 카테고리의 다른 글
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(11일차) (0) | 2023.11.06 |
---|---|
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(10일차) (0) | 2023.11.03 |
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(8일차) (0) | 2023.11.01 |
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(7일차) (0) | 2023.10.31 |
[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합 보안 과정 교육 정리(6일차) (0) | 2023.10.30 |