본문 바로가기
SK shieldus Rookies 16기

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

by Challenge programmers 2023. 11. 2.

오늘 학습 주제

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)

 

[ 문제점 ]

외부에서 입력받은 문자열을 바로 포맷스트링으로 사용

내부 정보가 외부로 노출

 

[ 해결 ]

외부에서 입력 받은 문자열은 반드시 포맷 지정자를 이용해 바인딩 후 사용

 

 

 

 

참고

https://yozm.wishket.com/magazine/detail/1822/

https://velog.io/@anhesu11/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C%EC%9D%98-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EB%AA%A8%ED%98%95

https://itwiki.kr/