SlideShare a Scribd company logo
보안 어플리케이션 개발 공정
및 실무적 수행 방법
마이크로포커스 (구 한국HP) 김상현 컨설턴트
CISA/CISSP/AWS SA, SysOps Admin/OCP/OCJP
sanghyoun.kim@microfocus.com
2018/04/21 (토), 마루180
Table of Contents
1. 어플리케이션 보안 현황
2. 소프트웨어 개발 보안의 시작 - 시큐어 코딩
 정적 코드 분석기
 시큐어 코딩 예제, Mindset Deep Dive
 정적 코드 분석 실무 예제
 보안 스코어
 정적 코드 분석과 머신 러닝
3. 안전한 어플리케이션 운영
 안전한 운영 및 지속적인 모니터링 – RASP
4. 마치며
2/120
어플리케이션 보안 현황
 데이터 침해 사고의 84%가 웹 어플리케이션 취약점을 활용 –
가트너, 2014
 어플리케이션 보안 (AppSec) 지출은 경계 보안의 23분의 1
어플리케이션 보안 현황
4/120
어플리케이션 복잡도 증가
 어플리케이션의 규모와 복잡도 상승
 아웃소싱 소프트웨어
 COTS (Commercial Off-the-Shelf; 상용) 소프트웨어
 오픈 소스 컴포넌트
 레거시 소프트웨어 (유지 보수 만료, 소스 코드 망실)
 이 모든 요소들을 보안 위협으로부터 보호하고 규제와 컴플라이언스 충족 필요
5/120
Proactive vs. Reactive
 Proactive
 개발 단계부터 예상 가능한 취약점을 선제적으로 제거
 코딩 규칙을 정의하고 소스 코드 취약 목록을 개발 단계에서부터 제거하기 위한 "시큐어 코딩" 기법이 대표적
 Reactive
 테스트/운영 환경에서 공격을 반응적으로 탐지하고 차단
 고도화/정교화되는 어플리케이션에 대한 공격  단편적인 대응으로는 대응 불가
 소프트웨어 보안 보증 (Software Security Assurance), 보안 소프트웨어 개발 공정 (Secure SDLC)
Proactive Approach Reactive Approach
Secure SDLC
보안 요구 사항,
위험 분석
개발 가이드라인,
코드 리뷰,
정적 코드 분석
동적 분석 방화벽, IDS/IPS, WAF
6/120
 Introduced by Microsoft
 Software development process
 Helps developers build more secure software & address security
compliance requirements
 Reduce development cost
Source:www.microsoft.com/en-us/sdl/
Security Development Lifecycle (SDL)
7/120
어플리케이션 개발 보안의 시작 –
시큐어 코딩
구조/기술적 부채(負債)
 경험 많고 노련한 개발자는 잘못된 설계/코딩에 따른 결함을 바로잡는데 많은
비용과 노력이 필요하다는 것을 잘 알고 있음  Architectural/Technical Debt
 배포 이후에 결함을 수정하는 것은 설계 시 바로잡는 것에 비해 30배의 비용이
소요 - 미국 국립 표준 기술 연구소 (NIST)
 https://www.nist.gov/sites/default/files/documents/director/planning/report02-3.pdf
9/120
 늦게 바로잡을수록 많은 노력과 비용이 누적
구조/기술적 부채(負債)
10/120
 85%의 결함이 개발 단계에서
양산 (하늘색)
 탐지율은 이후 단계에서 상승
(노란색)
 체계화된 개발 방법론 부재
 개발자별 보안 인식 및 수준 차이
 탐지가 어려운 실수나 논리적 오류
 이러한 불일치가 결함 조치
비용의 상승을 불러옴
 탐지율 그래프를 가급적
왼쪽으로 이동시켜야 함  Shift-
Left
 시큐어 코딩!
개발 단계별 결함 발생 및 탐지의 불일치
11/120
시큐어 코딩
방법론
• 개발자 수준에 따른 산출물 차이
• 실수나 논리적 오류 제거
SDL의 시작점
• 소프트웨어 개발 수명 주기 (SDL; Software
Development Lifecycle)의 시작점
Metric
• 소프트웨어 보증(Software Assurance) 지표
(Metric) 가 수집되는 첫 단계
12/120
소프트웨어 도구
평가 방법 개발
도구 및 기법의
효과 측정
방화벽, SCADA, 웹 응용
프로그램, 소스 코드 보
안 분석기, 시공 방법 등
광범위한 영역
시큐어 코딩 해외 동향 – NIST SAMATE
3가지 방
법론
10개의
참여팀*
최대
4.7M LOC
Use Case
SAMATE
(Software
Assurance Metrics
and Tool Evaluation)
- https://samate.nist.gov/Main_Page.html
- *서울대의 Sparrow 팀 참여
13/120
 “소프트웨어 보증 참조 데이터셋”(SARD; Software Assurance Reference Dataset)
 NIST SAMATE 하부 프로젝트
 개발자에게 필요한 다양한 개발 언어별 취약점 패턴 정보, 해결 방법, 테스트 케이스의 소스 코드 다운로드 가능
 https://samate.nist.gov/SARD/testsuite.php
 주의) 일부 테스트 케이스는 프로젝트 참여 업체의 솔루션에 Bias됨
NIST SARD
14/120
시큐어 코딩 국내 동향 – “SW 개발보안” 제도
2012.12
•행정안전부 “SW 개발보안" 의무제 시행
•사업 규모 40억원 이상
2014.01
•사업 규모 20억원 이상으로 확대
2015.01
•감리 대상 전체
2016.12
•「행정기관 및 공공기관 정보시스템 구축ㆍ운영 지침」(2016.12.26) 개정
•“SW 개발보안” 적용범위가 설계단계까지 확대
2017.01
•“소프트웨어 개발 보안 가이드” 개정
15/120
 한국인터넷진흥원(KISA)
 관련 법령 현황
 고시 및 권고
 기술 안내서 가이드 조회 및
다운로드 가능
 http://www.kisa.or.kr/public/laws
/laws3.jsp
 기술 안내서의 경우 주로 자바
기반 기술에 국한
시큐어 코딩 국내 동향 – KISA
16/120
 시큐어 코딩에 대한
이론적인 배경을 설명할
수 있는 시큐어 코딩
솔루션과 정적 코드
분석기의 특징을 잠깐
살펴보고자 합니다!
시큐어 코딩 예제 및 데모를 살펴보기 전에
17/120
시큐어 코딩 솔루션의 구성
Static Analysis – SCA
Source Code
Mgt. System
Static Analysis Via
Build Integration
Dynamic Analysis – Vulnerability
Scanner
Dynamic Testing in
QA or Production
Application Protection –
RASP
Real-time Protection of
Running Application
Vulnerability Management
Normalization
(Scoring, Guidance)
Vulnerability
Database
Remediation
IDE Plug-ins (Eclipse,
Visual Studio, etc.)
Developers
(onshore or offshore)
Correlate Target
Vulnerabilities with
Common Guidance
and Scoring
Defects, Metrics
and KPIs Used to
Measure Risk
Application
Lifecycle
Development, Project
and Management
Stakeholders
Software Security CenterCloud Support
Hackers
& Actual Attacks
Correlation
(Static, Dynamic, Runtime)
Threat Intelligence Rules Management
(구성 예)
18/120
시큐어 코딩 솔루션의 구성 – 정적 코드 분석기
Vulnerable Code
분석
결과 제시
XSS – Cross Site Scripting!
19/120
시큐어 코딩 솔루션의 구성 – 정적 코드 분석기
화이트
박스
테스팅
• 소스 코드에 대해 모든
가시성을 가지고 취약점
을 분석
런타임
모사 (模寫)
메트릭
• 실행 시의(Runtime) 모든
정황(Context)를 개발
시점에(Development-time)에
최대한 모사(模寫)할 수 있어야 함
• 정탐율 (Sensitivity) vs. 오탐율
(Specificity)
다양한
분석 기법
• 데이터 및 논리 흐름
• 구조 및 의미 분석
• 환경 요소 파악
• 버퍼 분석
• 머신 러닝
20/120
시큐어 코딩 솔루션의 구성 – 취약점 관리 시스템
분석 결과
Audit Report
프로젝트 매니저/보안 책임자
조치 작업 할당
21/120
시큐어 코딩 솔루션의 구성 – 취약점 관리 시스템
관리 저장소
• 모든 어플리케이션의
취약점 분석 결과를
체계적으로 관리
역할 분리
• 조직화된 보안 활동과
협업 체계 구축
• 담당자별 역할 분리
• 개발자 - 취약점 수정
• 개발PM - 취약점 추적
및 담당 개발자 할당
• CISO/CIO - 취약점
보고서 조회 및
어플리케이션 수명
주기 관리
DevOps/DevSecOps 가속
• CI/CD 툴(Jenkins),
취약점 관리
시스템(JIRA, BugZilla 등)
과의 연계 기능
• 보안과 결합된 DevOps
문화(DevSecOps)를
가속화하는데 기여
22/120
시큐어 코딩 솔루션의 구성 – 개발자 지원
실시간 분석
중요 취약점에 대한
실시간 정보
23/120
시큐어 코딩 솔루션의 구성 – 개발자 지원
Security
Automation
관점에서
중요
보안에 대한 지식이나
경험이 부족한 초보
개발자도 쉽게 활용할
수 있도록 지원
Eclipse, IntelliJ, Microsoft Visual
Studio 등 다양한 통합 개발
환경에서 정적 코드 분석을
실행할 수 있도록 도와주는
플러그인과 Ant, Maven 등의
빌드 시스템과 연계할 수 있는
기능
Tool Fatigue,
Process Friction
최소화
24/120
정적 코드 분석기
정적 코드 분석 성능 지표
정탐율
(Sensitivity,
Recall)
전체 취약점 중 얼마나
많이 보고되었나?
=
오탐율
(Specificity,
Fall-out)
전체 정상 처리 중
얼마나 많은 수가
취약한 것으로 잘못
보고되었나?
=
정확도
(Precision)
보고된
취약점 중 실제로
취약점은 얼마나 되나?
=
#TP
#TP + #FN
#TP
#TP + #FP
#FP
#FP + #TN
취약점 정상 처리
True Positives (TP, 정탐) False Positives (FP, 오탐)
탐지 보고
False Negatives (FN, 미탐) True Negatives (TN, 정미탐)
27/120
정적 코드 분석 성능 지표
 정확도 (Precision) = #TP / (#TP + #FP)
 보고된 전체 취약점 중 실제 취약점 비율, 높을 수록 좋음
 Sensitivity (Recall율) = #TP / (#TP + #FN)
 실제 전체 취약점 중 보고된 취약점 비율, 높을 수록 좋음
 Specificity (Fall-out) = #FP / (#FP + #TN)
 실제 전체 미 취약점 (정상 처리) 중 양성으로 잘못 보고된 비율, 낮을 수록 좋음
 대부분의 툴이 정확도에서 80% 넘지 못함
 Recall율에 있어서도 거의 모든 툴이 50%를 넘기지 못함
• 위양성: 1종 오류, 알파 오류, 오탐이라고도 함
• 위음성: 2종 오류, 베타 오류, 미탐이라고도 불림
보고 (Reported) 미보고 (Non-Reported)
실제 취약점
진양성
(True Positive; TP)
위음성
(False Negative; FN)
취약점 아님
위양성
(False Positive; FP)
진음성
(True Negative; TN)
28/120
정적 코드 분석의 효용성
취약점 정상 처리
탐지군
29/120
정적 코드 분석의 효용성
취약점 정상 처리
True Positives (TP, 정탐) False Positives (FP, 오탐)
탐지 보고
False Negatives (FN, 미탐) True Negatives (TN, 정미탐)
Shift Left
Find More
- 모든 취약점이 발견되고 해소되기는 불가능
- 취약점만을, 많이 탐지하도록 – Shift Left, Find More
- 랜덤 추측에서는 탐지보고 타원 영역이 중앙에 위치
- 좋은 정적 코드 분석 솔루션은 타원 영역을 왼쪽으로, 그리고 큰
영역을 커버하면서 움직임
- 정적 코드 분석 솔루션으로 탐지되지 않는 취약점이 여전히
존재할 수 있는데 DAST와 RASP를 통해 재탐지하고 실행시 보호
30/120
정적 코드 분석의 보완
31/120
정적 코드 분석 OWASP 벤치마크 프로젝트
OWASP Benchmark
Project
11개 영역,
총 21,042
테스트 케
이스
오픈 소스
5종 (총 조합
10가지)
상용 솔루션
6종
지표 측정
32/120
정적 코드 분석 OWASP 벤치마크 프로젝트 결과
 Youden Index (정탐율 (TPR) - 오탐율
(FPR))을 스코어(Score)로 사용
 상용 솔루션이 오픈 소스 솔루션에
비해 근소하게 양호한 점수를 기록
(26% vs. 22%)
 상용 솔루션이 수행한 테스트
케이스가 오픈 소스 솔루션에 비해
8배 많음 (21041 vs. 2704)
 오픈 소스 솔루션 상용 솔루션에
비해 결과의 편차가 큼 (표준편차:
오픈소스 0.1418 vs. 상용 0.0650)
 오픈 소스 솔루션의 경우 분석 수행
시간이 짧음 – 적은 테스트 케이스
33/120
정적 코드 분석 OWASP 벤치마크 프로젝트 결과
(Cont’d)
 모든 솔루션들이 정탐율이
높아질수록 오탐율도 함께
올라가는 경향
 오픈 소스 솔루션 중 가장 좋은
점수를 보인 FBwFindSecBugs v1.4.6
의 경우 오탐율도 가장 높은 것으로
나타남 (57.74%)
 탐지된 취약점이 실제로 유효한
취약점인지를 파악하기 위한
추가적인 후속 조치가 필요하며,
솔루션의 사용성을 떨어뜨릴 수
있음
34/120
개발자의 역량에 맡김 vs. 시큐어 코딩 솔루션 도입
자체 처리 솔루션 도입
솔루션 도입에 따른 이득이
자체 투자보다 클 때
오픈 소스가 광범위하게 사용
되고 통제가 어려울 때
대외 서비스 프로젝트,
중요한 내부 자산
규제/컴플라이언스
요건 충족 필요
솔루션 도입에 따른 비용이 취약점 침해
에 따른 비용보다 크다고 판단될 때
오픈 소스 도입이 없거나 통제
가능
내부 전용 Pilot 프로젝트
내부 개발 역량으로 대응 가능
35/120
시큐어 코딩 예제 데모
시큐어 코딩
 잘 알려진 일반적인 취약점부터 시작!
38/120
OWASP - 2017
39/120
 브라우저에서 아래 주소 입력
 http://riches2.mydemo.co.kr:580
82/riches/
 참고) 예제에 인용된 URL(
서버)은 실습을 위해 꾸며
진 것이로서, 사전 예고없
이 접속이 불가능할 수 있
습니다
A1: Injection – SQL Injection
40/120
 Username: ”eddie”, Password:
“eddie” 입력하여 로그인
 로그인이 되면 “Account
Summary” 페이지로 이동
A1: Injection – SQL Injection (계속)
41/120
 표시된 “0422328325” 링크를
클릭하여 계좌 이력을 조회
A1: Injection – SQL Injection (계속)
42/120
A1: Injection – SQL Injection (계속)
 브라우저의 주소창에 [' or '1' =
'1]를 추가하고 엔터
 “개발자가 의도하지 않았던”
다른 계좌의 정보도 조회됨
43/120
 데이터베이스와 연동된 웹
어플리케이션에서 입력된
데이터의 유효성 검증 누락
 공격자가 입력 폼, URL
입력란에 SQL을 삽입
 주로 개발자가 의도하지 않은
형태로 Where Predicate가
변조된 동적 쿼리문 생성
 실행이 성공하면 공격자로
데이터가 유출
A1: Injection – SQL Injection 공격 흐름
44/120
 PreparedStatement 클래스를 활용하여 인입되는
매개변수를 바인드 변수 처리하고 executeQuery(), execute(),
executeUpdate() 메서드 호출
 PreparedStatement 클래스를 활용하기 어렵다면 입력값에
대한 Validation을 수행한 후 사용
 Validation은 SQL 구문 제한, 특수 문자 제한, 길이 제한 등을
복합적으로 활용
A1: Injection – SQL Injection 대응 코딩 기법
45/120
A1: Injection – SQL Injection 대응 코딩 기법
변경 전
변경 후
46/120
A1: Injection – SQL Injection 대응 결과
 공격 무효화
 확인: http://riches3.mydemo.co.kr:58083/riches
47/120
 브라우저에서 아래 주소 입력
 http://riches2.mydemo.co.kr:580
82/riches/
A1: Injection – Command Injection
48/120
A1: Injection – Command Injection (계속)
 Username: ”admin”, Password:
“admin” 입력하여 로그인
 로그인 후 “Admin Messaging”
페이지로 이동
49/120
A1: Injection – Command Injection (계속)
 메시지 본문에 ["; cat
/etc/passwd"] 입력 후 “Send
버튼 클릭”
 시스템의 사용자 목록이
조회됨을 확인
50/120
 적절한 검증 절차를 수행하지
않은 사용자 입력값이
운영체제 명령어의 일부 또는
전부로 구성되어 실행
 부적절한 권한 변경, 시스템
리소스의 통제되지 않은 조회
가능
A1: Injection – Command Injection 공격 흐름
51/120
 인터페이스를 통해 전달되는 매개변수를 그대로 시스템
명령어로 사용하지 않는다
 외부 입력에 따라 통제된 경로로 시스템 명령어를 생성하며,
선택이 필요한 경우 명령어 생성에 필요한 값을 미리
지정해 두고 선택적으로 활용
A1: Injection – Command Injection 대응 코딩 기법
52/120
A1: Injection – Command Injection 대응 코딩 기법
Validation 추가
53/120
A1: Injection – Command Injection 대응 결과
 공격 무효화
 확인:
http://riches3.mydemo.
co.kr:58083/riches
 주의: 체계적인 대응을
위해서는 운영 체제
환경, WEB/WAS 시스템,
프레임웍 현황에 대한
정확한 이해가 필요함
54/120
A7: Cross Site Scripting (XSS)
 전통적인 공격 기법이고 많은
대응이 이루어지고 있지만
여전히 보편적인 어플리케이션
취약점
 제어문, 형태 정의 태그, 실제
내용 등이 평면적이고
순차적으로 담겨 있는 HTML의
특성상 완전히 배제하는 것은
불가음 – 효과가 입증된
정형화된 패턴을 따르는 것을
권장
55/120
A7: Cross Site Scripting (XSS) - Reflected
56/120
A7: Cross Site Scripting (XSS) - Reflected
 공격자는 악의적인 스크립트가
담긴 URL 링크가 담긴
이메일을 사용자(Victim)에게
전달
 사용자는 링크를 클릭하여 웹
사이트에 접속하고
 접속 후에 스크립트가
실행되어 공격을 수행 – 예)
사용자의 정보 (쿠키 등)를
공격자에게 전송
57/120
 브라우저에서 아래 주소 입력
 http://riches2.mydemo.co.kr:580
82/riches/
 주의) 일부 브라우저(예: 크롬,
사파리)에서는 XSS 스크립트
전송을 막는 기능이 있으므로
다른 브라우저 이용 (인터넷
익스플로러, 파이어폭스)
A7: Cross Site Scripting (XSS) - Reflected
58/120
 인증창의 Username에
[<script>alert('1');</script>]를
입력하고 “Go” 버튼 클릭
A7: Cross Site Scripting (XSS) - Reflected
59/120
 스크립트가 실행되는 것을
확인
 공격자는 이 스크립트를 좀 더
악의적인 목적으로 이용 가능
 예) 공격자에게 사용자의 쿠키
정보를 전송
A7: Cross Site Scripting (XSS) - Reflected
60/120
 웹 서버로 전달되는 모든 입력값을
직접 Validation
 검증된 패턴 API를 활용
 OWASP 보안 API
ESAPI.encoder().encodeForHTMLAttrib
ute(input);
 XSS Filter
com.jesephoconnel.html.HTMLInputFilt
er.filter(input);
A7: Cross Site Scripting 대응 코딩 기법
From To
< &lt;
> &gt;
( &#40;
) &#41;
# &#35;
& &#38;
61/120
A7: Cross Site Scripting 대응 코딩 기법
62/120
 입력값 중 스크립팅 요소가
Actionable하지 않은
문자열로 변환되므로써
공격이 무효화됨
A7: Cross Site Scripting 대응 코딩 기법
63/120
 잘 알려진 Cross Site Scripting 공격 기법
2가지 중 하나인 Reflected 방법을
알아보았습니다.
 그러면 다른 하나는 무엇일까요?
힌트 “P”로 시작하는 형용사형을 정확하게
맞춰 주세요.
Quiz – 빨리 맞추신 분께는 상품을 드려요!
64/120
KISA 시큐어 코딩 가이드
 http://www.kisa.or.kr/public/
laws/laws3_View.jsp?cPage=
6&mode=view&p_No=259&b
_No=259&d_No=55&ST=T&S
V=
65/120
시큐어 코딩 Mindset Deep Dive
 신뢰할 수 없는 입력이 잠재적으로 어플리케이션의
동작을 제어하는 취약점을 검출하는 분석기 (혹은 사람)
 Injection 공격
 분석기는 오염 (Taint)의 전반적인 전파 (Propagation)
상황을 파악하여 신뢰할 수 없는 데이터의 흐름을 추적
 Source
 신뢰되지 않는 (즉, 사용자가 통제하는) 입력
 Sink
 잠재적으로 위험한 함수 호출이나 동작
Data Flow Analyzer
67/120
Understanding Data Flow
1 import java.sql.*;
2
3 public class SQLInjection {
4 public static void main (String args[]) {
5 Connection conn = null;
6 try {
7 String userName = args [0];
8 String passwd = args [1];
9 String query = "select uname, passwd from users where uname like "+userName+"%";
10 conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
11 Statement stmnt = conn.createStatement ();
12 ResultSet rs = stmnt.executeQuery (query);
13 while ( rs.next() ) {
14 ...
15 }
16 rs.close ();
17 stmnt.close ();
18 conn.close ();
19 }
20 catch (SQLException err) {
21 err.printStackTrace ();
22 }
23 }
24 }
68/120
Understanding Data Flow
import java.sql.*;
public class SQLInjection {
public static void main (String args[]) {
Connection conn = null;
try {
String userName = args [0];
String passwd = args [1];
String query = "select uname, passwd from users where uname like "+userName+"%";
conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
Statement stmnt = conn.createStatement ();
ResultSet rs = stmnt.executeQuery (query);
while ( rs.next() ) {
...
}
rs.close ();
stmnt.close ();
conn.close ();
}
catch (SQLException err) {
err.printStackTrace ();
}
}
}
Source
69/120
Understanding Data Flow
import java.sql.*;
public class SQLInjection {
public static void main (String args[]) {
Connection conn = null;
try {
String userName = args [0];
String passwd = args [1];
String query = "select uname, passwd from users where uname like "+userName+"%";
conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
Statement stmnt = conn.createStatement ();
ResultSet rs = stmnt.executeQuery (query);
while ( rs.next() ) {
...
}
rs.close ();
stmnt.close ();
conn.close ();
}
catch (SQLException err) {
err.printStackTrace ();
}
}
}
args[] is tainted
Source
70/120
Understanding Data Flow
import java.sql.*;
public class SQLInjection {
public static void main (String args[]) {
Connection conn = null;
try {
String userName = args [0];
String passwd = args [1];
String query = "select uname, passwd from users where uname like "+userName+"%";
conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
Statement stmnt = conn.createStatement ();
ResultSet rs = stmnt.executeQuery (query);
while ( rs.next() ) {
...
}
rs.close ();
stmnt.close ();
conn.close ();
}
catch (SQLException err) {
err.printStackTrace ();
}
}
}
Taint propagated to userName
args[] is tainted
Source
71/120
Understanding Data Flow
import java.sql.*;
public class SQLInjection {
public static void main (String args[]) {
Connection conn = null;
try {
String userName = args [0];
String passwd = args [1];
String query = "select uname, passwd from users where uname like "+userName+"%";
conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
Statement stmnt = conn.createStatement ();
ResultSet rs = stmnt.executeQuery (query);
while ( rs.next() ) {
...
}
rs.close ();
stmnt.close ();
conn.close ();
}
catch (SQLException err) {
err.printStackTrace ();
}
}
}
Tainted input
userName used
in assignment
Taint propagated to userName
args[] is tainted
Source
72/120
Understanding Data Flow
import java.sql.*;
public class SQLInjection {
public static void main (String args[]) {
Connection conn = null;
try {
String userName = args [0];
String passwd = args [1];
String query = "select uname, passwd from users where uname like "+userName+"%";
conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
Statement stmnt = conn.createStatement ();
ResultSet rs = stmnt.executeQuery (query);
while ( rs.next() ) {
...
}
rs.close ();
stmnt.close ();
conn.close ();
}
catch (SQLException err) {
err.printStackTrace ();
}
}
}
Sink
Tainted input
userName used
in assignment
Taint propagated to userName
args[] is tainted
Source
73/120
Understanding Data Flow
import java.sql.*;
public class SQLInjection {
public static void main (String args[]) {
Connection conn = null;
try {
String userName = args [0];
String passwd = args [1];
String query = "select uname, passwd from users where uname like "+userName+"%";
conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein");
Statement stmnt = conn.createStatement ();
ResultSet rs = stmnt.executeQuery (query);
while ( rs.next() ) {
...
}
rs.close ();
stmnt.close ();
conn.close ();
}
catch (SQLException err) {
err.printStackTrace ();
}
}
}
Vulnerability
Reported
Sink
Tainted input
userName used
in assignment
Taint propagated to userName
args[] is tainted
Source
74/120
 위험할 수 있는 일련의 동작이나 함수 호출을 검출
 상태 머신(State Machine) 모델을 사용하여 상태의
전이 상태를 판단
 각 상태 머신은 취약점이 악용될 수 있는 “에러 상태”를 가질 수 있음
 분석가는 이러한 상태 머신을 파악할 수 있는
지식이나 룰을 가지고 있어야 함
Control Flow Analyzer
75/120
Understanding Control Flow
1 private void cmdLogin_Click(object sender, System.EventArgs e){
2 Label lblMsg = null;
3 try {
4 string txtUser = Request.Form["txtUsername"];
5 string txtPassword = Request.Form["txtPassword"];
6 string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
7 SqlConnection cnx = new SqlConnection(strCnx);
8 cnx.Open();
9
10 string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
11 txtUser + "' AND Password='" + txtPassword + "'";
12 int intRecs;
13
14 SqlCommand cmd = new SqlCommand(strQry, cnx);
15 intRecs = (int)cmd.ExecuteScalar();
16
17 if (intRecs > 0){
18 FormsAuthentication.RedirectFromLoginPage(txtUser, false);
19 cnx.Close();
20 }
21 else{
22 lblMsg.Text = "Login attempt failed.";
23 }
24 }
25 catch (Exception err){
26 Response.Write(err.StackTrace.ToString());
27 }
28 }
76/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Variable
initialized &
assigned
77/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Connection
closed
Variable
initialized &
assigned
78/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Safe
Sequence
Connection
closed
Variable
initialized &
assigned
79/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Variable
initialized &
assigned
80/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Variable
initialized &
assigned
Control Flow observes all
possible paths
81/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Analyze until cnx is out
of scope
Variable
initialized &
assigned
Control Flow observes all
possible paths
82/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Analyze until cnx is out
of scope
Variable
initialized &
assigned
Control Flow observes all
possible paths
Vulnerability
Reported
83/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Variable
initialized &
assigned
Control Flow observes all
possible paths
84/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Analyze until cnx is out
of scope
Variable
initialized &
assigned
Control Flow observes all
possible paths
85/120
private void cmdLogin_Click(object sender, System.EventArgs e){
Label lblMsg = null;
try {
string txtUser = Request.Form["txtUsername"];
string txtPassword = Request.Form["txtPassword"];
string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser + "' AND Password='" + txtPassword + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int)cmd.ExecuteScalar();
if (intRecs > 0){
FormsAuthentication.RedirectFromLoginPage(txtUser, false);
cnx.Close();
}
else{
lblMsg.Text = "Login attempt failed.";
}
}
catch (Exception err){
Response.Write(err.StackTrace.ToString());
}
}
Understanding Control Flow
Vulnerability
Reported
Analyze until cnx is out
of scope
Variable
initialized &
assigned
Control Flow observes all
possible paths
86/120
자동화된 정적 코드 분석 실무
예제
1. 경영진은 앞서 살펴 보았던 “riches” 웹 어플리케이션이 회사의
Reputation을 심하게 훼손하고 비즈니스의 연속성을 해칠 보안
취약점이 있다고 판단
2. DevSecOps 태스크포스를 구성하여 보안 취약점을 소스 코드
차원에서 진단하여 보안성을 제고할 방안을 찾기 시작
예제 시나리오
88/120
1. 하지만 새로운 기능을 담은 전면적인 Renewal을 앞두고 있는
상황이라 발견된 취약점을 수정, 검증하기에는 현실적으로
시간적인 어려움이 있음
2. “Bi-Directional AppSec in CI/CD Pipeline” 전술을 구사하기로 결정
1) 기존에 운영되던 Jenkins의 Nightly Build 프로세스 (새벽 4시)에 정적 코드 분석 단계를
추가
2) Ops/QA 팀은 분석 결과 취약점 지표가 기준치보다 높으면 Dev 조직에 발견된 취약점의
수정을 지시 – Reverse AppSec
3) Ops 팀은 수정된 코드의 검증 기간을 기다리기에는 Renewal 오픈 기간이 촉박하므로
그대로 Production 환경에 Deploy, 대신 어플리케이션의 취약점을 런타임 수준에서
방어해주는 런타임 자가 방어 (RASP; Runtime Application Self Protection) 기술을 사용할
예정 – Forward AppSec
예제 시나리오
89/120
Bi-Directional AppSec Pipelining in CI/CD
Commit Build Test Stage DeployDev Prod
CI/CD
정적 코드
분석
취약점 수정 Reverse AppSec Forward AppSec
취약점 스캐닝/RASP를 통한 안전한 운영
및 지속적인 모니터링
90/120
참고
 이번 예제에서는 특정 정적 코드 분석 솔루션의 기능을 소개하기
보다는 정적 코드 분석 솔루션의 일반적인 특징과 사용 방법에
중점을 두고 이야기해 보고자 합니다.
 따라서 여기서는 솔루션의 특징적인 부분들, 예를 들어 설치
경로와 사용되는 명령어의 구성 등에 대해서 관심을 두기 보다는
시큐어 코딩 활동을 위해 정적 코드 분석 솔루션이 사용되는
전체적인 흐름에 집중하면 좋을 것입니다.
91/120
Jenkins 프로젝트
기존의 빌드 Job이 Freestyle Project 임을 가정
92/120
Jenkins 프로젝트
빌드 명령어도 기존의 빌드 스크립트와 동일
93/120
Jenkins 프로젝트
빌드 외에 정적 코드 분석을 추가로 실시하도록 설정
정적 코드 분석기에 따라 달라질 수 있음94/120
Jenkins 프로젝트
솔루션에 따라 코드 분석 결과를 중앙 관리 서버로 자동으로
전송하는 기능을 추가 사용95/120
Jenkins 프로젝트 실행 화면
- 정규 취약점 점수 (NVS): 387.2점 – 이후 장표에서 설명
96/120
Jenins 프로젝트 실행 화면 온라인 확인
 클라우드 데모 서버의 온라인
대시 보드
 https://cloud.skytap.com/vms/47c
39c3786da57bf2658ddd6428ae68f
/desktops
 https://goo.gl/kGZXQv
(간단 URL)
 참고) Instructor의 조작 필요
97
Jenins 프로젝트 실행 화면 온라인 확인
 혹은 Jenkins에 직접 로그인하여
확인
 http://jenkins.mydemo.co.kr:8080/
jenkins
98
Jenkins 프로젝트 실행 화면
- 정규 취약점 점수 (NVS): 387.2점 – 이후 장표에서 설명
99/120
AppSec Myth
모든 취약점
발견 시도
모든 취약점이
해소되어야 함
AppSec
Myth
불가능!
비용 효과 X
Metric
“적절한” 보안
수준 설정
충족되면 다음
단계로 이관
100/120
AppSec Metric – 정규 취약점 점수 (NVS)
 Impact & Likelihood
 CFPO: Critical로 분류된 취약점 수
 HFPO: High로 분류된 취약점 수
 MFPO: Medium으로 분류된 취약점 수
 LFPO: Low로 분류된 취약점 수
 Security Quality
 P1: 신뢰성이 떨어지는 코드 개수
 P2: Best Practice를 따르지 않는다고 판단된 코드 개수
 P3: 의심이 가는 코드 개수
 PABOVE: Exploitable (해커에 의해 이용이 가능한) 코드 개수
 ExecutableLOC: 실행 가능 코드 라인 수
NVS: Normalized Vulnerability Score
계산이 비교적 간단하고, 각 우선 순위별 가중치를 필요에 따라 적절히 조절할 수 있으므로 많이 사용되는 취약점 산정 지표
101/120
Bi-Directional AppSec Activity by NVS!
개발팀 조치
(NVS 200 이상)
리뉴얼 배포
(NVS 400 이하)
NVS 기준
102/120
정적 코드 분석과 머신 러닝
Machine
Learning
• Reduce false positive noise
• Streamline cumbersome &
audit process
• Provide results unique to
organization’s preference
• Better utilize the resources
103/120
 Supervised Learning First - More data, better result
 Underlying ML algorithm can be extended to unsupervised
clustering, data views and outlier detection
정적 코드 분석과 머신 러닝
104/120
머신 러닝 Smart View
105/120
Prediction Confidence & Issue Graph
106/120
 담당 개발자에게 할당 시
Machine Learning 예측 지표
전달
 개발자는 이를 참고하여
적절한 보완 조치 수행
Assign to Developer with Machine Learning Feedback
107/120
안전한 어플리케이션 운영
배포된 어플리케이션의 취약점은?
Commit Build Test Stage DeployDev Prod
CI/CD
정적 코드
분석
취약점 수정 Reverse AppSec Forward AppSec
?
109/120
배포된 어플리케이션의 취약점은?
Commit Build Test Stage DeployDev Prod
CI/CD
정적 코드
분석
취약점 수정 Reverse AppSec Forward AppSec
취약점 스캐닝/RASP를 통한 안전한
운영 및 지속적인 모니터링
110/120
자기 방어 응용 프로그램
2014년 APM 솔루션 시장 규모: $2.72B
2019년에 $4.98B예상 (CAGR 12.86%)
• 런타임 어플리케이션 자기 방어 (Runtime
Application Self-Protection; RASP)
• RASP는 응용 프로그램의 런타임 환경과
결합되어 응용 프로그램 자체의 실행을
통제하고, 실시간으로 공격을 탐지 및 방어하는
보안 기술
• 2017년 10대 기술 트렌드 – 가트너
• 런타임 환경의 성숙과 함께 찾아온 일종의
프레임워크 협업 모델
• 런타임 제작사: 확장 가능한 런타임 설계
• 프레임워크 구현 벤더: 런타임의 확장성을 구현
• APM 시장은 이미 성장을 넘어 성숙 단계로…
111/120
자기 방어 응용 프로그램 - RASP
어플리케이션 서버 RASP 서버
에이전트/보안 규칙
방어/모니터링 이벤트
어플리케이션
자기 방어 에이전트
프로그램 포인트
실시간
공격
런타임
1. 런타임 시작 시 자기 방어 에이전트를 로드합니다.
A. 보안 서버로부터 보안 규칙을 받아 적용할 수도 있습니다.
2. 자기 방어 에이전트는 취약하거나 중요한 실행 지점에 보호 로직을
“편성” 합니다.
 프로그램 포인트 및 인스트루먼테이션 (Instrumentation)
1
2
1.A
3
3. 공격자가 해당 프로그램 포인트에 대해 공격을 감행합니다.
4. 자기 방어 에이전트는 어플리케이션을 대신하여 공격을 저지한
후 보안 서버로 이를 보고합니다.
4
Transparent to Application!
Minimum Impact to Performance!
112/120
RASP로 얻는 이점은?
• Resilient Security
 실행 시의 보안 위협에 탄력적으로 대응
• Visibility & Intelligence
 어플리케이션에 대한 가시성을 확보하고 보안
위협을 지능적으로 처리
• Transparency
 어플리케이션의 수정 없이 필수적인 보안성을 확보
 No Code Changes Needed!
• Lightweight & Automation
 런타임에서 동작하는 가벼운 구조
 어플리케이션의 수명 주기와 완전히 일치 –
자동화를 도와주고 DevOps 문화를 가속화
• Adaptability & Extensibility
 프로그램 포인트와 에이전트 확장
 예) 데이터베이스 호출 프로그램 포인트를
확장함으로써 DB 암호화를 응용프로그램 수정없이
구현 가능
RASP
Resilient
Security
Visibility &
Intelligence
Transparency
Lightweight
&
Automation
Adaptability
&
Extensibility
113/120
 http://riches1.mydemo.co.kr:58081/riches/
 Protection message configurable
RASP 데모 – SQL Injection 공격 방어
114/120
 https://appdefender.microfocus.skytapdns.com:8443/
RASP 데모 – 공격 실시간 모니터링
115/120
마치며
보안을 위한 여정 – AppSec Journey Cycle
SCA 활동으로 많은 취약점이
발견되고 조치됨 – Shift Left,
Find More!
동적 분석을 통해 Scan
Surface를 넓히고 SCA로
탐지하지 못한 취약점을
재탐지
여전히 남아 있을 수 있는
제로데이 취약점 등을 RASP
기술로 자체 방어
다수의 취약점이 존재하고,
안전한 코드들도 운에
의존하는 상태
117/120
마치며...
 어플리케이션을 개발하고 검증하여 안전하게 운영하는 활동은
한 순간에 완성을 선언할 수 없는 끝없는 과정의 연속이다.
 오늘날의 소프트웨어 개발 흐름에서 유행 (Viral) 하고 있는 단어
하나를 꼽으라면 단연 “DevOps”와 “CI/CD”일 것입니다.
 앞에서 우리는 시큐어 코딩 예제와 정적 코드 분석기가 CI/CD
툴인 Jenkins와 연동되는 실무 예제도 함께 살펴보았다.
 그리고 시간적 제약으로 불가피하게 전개될 수 밖에 없었던
어플리케이션을 빠르게 강화하고 모니터링할 수 있는 RASP에
대해서도 살펴보았습니다.
 이런 흐름이 단절없이 피드백되어 개선될 때 시큐어 코딩으로
시작하는 여러분의 AppSec 활동이 보다 안전해질 것입니다!
118/120
DevSecOps Cycle
119/120
감사합니다!

More Related Content

Similar to [Main Session] 보안을 고려한 애플리케이션 개발 공정 및 실무적 수행 방법 소개

위험기반테스트접근 테스트계획 사례
위험기반테스트접근 테스트계획 사례위험기반테스트접근 테스트계획 사례
위험기반테스트접근 테스트계획 사례
SangIn Choung
 
Cybereason v2.10
Cybereason v2.10Cybereason v2.10
Cybereason v2.10
Harry Sohn
 
투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2
투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2
투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2
tobeware
 
보안 위협과 악성코드 분석 기법
보안 위협과 악성코드 분석 기법보안 위협과 악성코드 분석 기법
보안 위협과 악성코드 분석 기법
Youngjun Chang
 
[고려대학교-SANE Lab] 170317풀타임세미나 이상민
[고려대학교-SANE Lab]  170317풀타임세미나 이상민[고려대학교-SANE Lab]  170317풀타임세미나 이상민
[고려대학교-SANE Lab] 170317풀타임세미나 이상민
Sane Lab
 
테스트자동화와 TDD
테스트자동화와 TDD테스트자동화와 TDD
테스트자동화와 TDD
Sunghyouk Bae
 
AttackIQ - BAS(Breach and Attack Simulation) Service
AttackIQ - BAS(Breach and Attack Simulation) Service AttackIQ - BAS(Breach and Attack Simulation) Service
AttackIQ - BAS(Breach and Attack Simulation) Service
Softwide Security
 
모바일 앱(App) 개발 테스트 솔루션 v20160415
모바일 앱(App) 개발 테스트 솔루션 v20160415모바일 앱(App) 개발 테스트 솔루션 v20160415
모바일 앱(App) 개발 테스트 솔루션 v20160415
SeungBeom Ha
 
Effective application of software safety techniques for automotive embedded c...
Effective application of software safety techniques for automotive embedded c...Effective application of software safety techniques for automotive embedded c...
Effective application of software safety techniques for automotive embedded c...
Hongseok Lee
 
가장 심각한 웹 애플리케이션 보안 위험 10가지-2013
가장 심각한 웹 애플리케이션 보안 위험 10가지-2013가장 심각한 웹 애플리케이션 보안 위험 10가지-2013
가장 심각한 웹 애플리케이션 보안 위험 10가지-2013
봉조 김
 
[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기
[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기
[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기
Ji-Woong Choi
 
클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018
클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018 클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018
클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018 Amazon Web Services Korea
 
2014 pc방화벽 시온
2014 pc방화벽 시온2014 pc방화벽 시온
2014 pc방화벽 시온
시온시큐리티
 
Istqb 1-소프트웨어테스팅기초
Istqb 1-소프트웨어테스팅기초Istqb 1-소프트웨어테스팅기초
Istqb 1-소프트웨어테스팅기초
Jongwon Lee
 
Cybereason in Korea, SMEC
Cybereason in Korea, SMECCybereason in Korea, SMEC
Cybereason in Korea, SMEC
SMEC Co.,Ltd.
 
Project turtle ship
Project turtle shipProject turtle ship
Project turtle ship
hanbeom Park
 
테스트수행사례 W통합보안솔루션
테스트수행사례 W통합보안솔루션테스트수행사례 W통합보안솔루션
테스트수행사례 W통합보안솔루션
SangIn Choung
 
Observability customer presentation samuel-2021-03-30
Observability customer presentation samuel-2021-03-30Observability customer presentation samuel-2021-03-30
Observability customer presentation samuel-2021-03-30
SAMUEL SJ Cheon
 
모아소프트(MOASOFT) 회사소개서 (20200922) version
모아소프트(MOASOFT) 회사소개서 (20200922) version모아소프트(MOASOFT) 회사소개서 (20200922) version
모아소프트(MOASOFT) 회사소개서 (20200922) version
모아소프트 MOASOFT
 
보안 위협 형태와 악성코드 분석 기법
보안 위협 형태와 악성코드 분석 기법보안 위협 형태와 악성코드 분석 기법
보안 위협 형태와 악성코드 분석 기법
Youngjun Chang
 

Similar to [Main Session] 보안을 고려한 애플리케이션 개발 공정 및 실무적 수행 방법 소개 (20)

위험기반테스트접근 테스트계획 사례
위험기반테스트접근 테스트계획 사례위험기반테스트접근 테스트계획 사례
위험기반테스트접근 테스트계획 사례
 
Cybereason v2.10
Cybereason v2.10Cybereason v2.10
Cybereason v2.10
 
투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2
투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2
투비웨어 AgitarOne Junit 단위테스트자동화 솔루션소개_201608_v1.2
 
보안 위협과 악성코드 분석 기법
보안 위협과 악성코드 분석 기법보안 위협과 악성코드 분석 기법
보안 위협과 악성코드 분석 기법
 
[고려대학교-SANE Lab] 170317풀타임세미나 이상민
[고려대학교-SANE Lab]  170317풀타임세미나 이상민[고려대학교-SANE Lab]  170317풀타임세미나 이상민
[고려대학교-SANE Lab] 170317풀타임세미나 이상민
 
테스트자동화와 TDD
테스트자동화와 TDD테스트자동화와 TDD
테스트자동화와 TDD
 
AttackIQ - BAS(Breach and Attack Simulation) Service
AttackIQ - BAS(Breach and Attack Simulation) Service AttackIQ - BAS(Breach and Attack Simulation) Service
AttackIQ - BAS(Breach and Attack Simulation) Service
 
모바일 앱(App) 개발 테스트 솔루션 v20160415
모바일 앱(App) 개발 테스트 솔루션 v20160415모바일 앱(App) 개발 테스트 솔루션 v20160415
모바일 앱(App) 개발 테스트 솔루션 v20160415
 
Effective application of software safety techniques for automotive embedded c...
Effective application of software safety techniques for automotive embedded c...Effective application of software safety techniques for automotive embedded c...
Effective application of software safety techniques for automotive embedded c...
 
가장 심각한 웹 애플리케이션 보안 위험 10가지-2013
가장 심각한 웹 애플리케이션 보안 위험 10가지-2013가장 심각한 웹 애플리케이션 보안 위험 10가지-2013
가장 심각한 웹 애플리케이션 보안 위험 10가지-2013
 
[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기
[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기
[오픈소스컨설팅] 오픈소스 기반 솔루션 방향성 잡기
 
클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018
클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018 클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018
클라우드 환경에서 비즈니스 애플리케이션의 성능 통합 모니터링 방안::류길현::AWS Summit Seoul 2018
 
2014 pc방화벽 시온
2014 pc방화벽 시온2014 pc방화벽 시온
2014 pc방화벽 시온
 
Istqb 1-소프트웨어테스팅기초
Istqb 1-소프트웨어테스팅기초Istqb 1-소프트웨어테스팅기초
Istqb 1-소프트웨어테스팅기초
 
Cybereason in Korea, SMEC
Cybereason in Korea, SMECCybereason in Korea, SMEC
Cybereason in Korea, SMEC
 
Project turtle ship
Project turtle shipProject turtle ship
Project turtle ship
 
테스트수행사례 W통합보안솔루션
테스트수행사례 W통합보안솔루션테스트수행사례 W통합보안솔루션
테스트수행사례 W통합보안솔루션
 
Observability customer presentation samuel-2021-03-30
Observability customer presentation samuel-2021-03-30Observability customer presentation samuel-2021-03-30
Observability customer presentation samuel-2021-03-30
 
모아소프트(MOASOFT) 회사소개서 (20200922) version
모아소프트(MOASOFT) 회사소개서 (20200922) version모아소프트(MOASOFT) 회사소개서 (20200922) version
모아소프트(MOASOFT) 회사소개서 (20200922) version
 
보안 위협 형태와 악성코드 분석 기법
보안 위협 형태와 악성코드 분석 기법보안 위협 형태와 악성코드 분석 기법
보안 위협 형태와 악성코드 분석 기법
 

More from Oracle Korea

Oracle Blockchain Platform_Wonjo Yoo
Oracle Blockchain Platform_Wonjo YooOracle Blockchain Platform_Wonjo Yoo
Oracle Blockchain Platform_Wonjo Yoo
Oracle Korea
 
Oracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTOOracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTO
Oracle Korea
 
Oracle cloud data interface
Oracle cloud data interfaceOracle cloud data interface
Oracle cloud data interface
Oracle Korea
 
On premise db &amp; cloud database
On premise db &amp; cloud databaseOn premise db &amp; cloud database
On premise db &amp; cloud database
Oracle Korea
 
Spring boot microservice metrics monitoring
Spring boot   microservice metrics monitoringSpring boot   microservice metrics monitoring
Spring boot microservice metrics monitoring
Oracle Korea
 
Opentracing jaeger
Opentracing jaegerOpentracing jaeger
Opentracing jaeger
Oracle Korea
 
Which Questions We Should Have
Which Questions We Should HaveWhich Questions We Should Have
Which Questions We Should Have
Oracle Korea
 
Oracle NoSQL
Oracle NoSQLOracle NoSQL
Oracle NoSQL
Oracle Korea
 
Enterprise Postgres
Enterprise PostgresEnterprise Postgres
Enterprise Postgres
Oracle Korea
 
MySQL Document Store를 활용한 NoSQL 개발
MySQL Document Store를 활용한 NoSQL 개발MySQL Document Store를 활용한 NoSQL 개발
MySQL Document Store를 활용한 NoSQL 개발
Oracle Korea
 
API Design Principles Essential 
API Design Principles Essential API Design Principles Essential 
API Design Principles Essential 
Oracle Korea
 
SpringBoot and Spring Cloud Service for MSA
SpringBoot and Spring Cloud Service for MSASpringBoot and Spring Cloud Service for MSA
SpringBoot and Spring Cloud Service for MSA
Oracle Korea
 
CI/CD 기반의 Microservice 개발
 CI/CD 기반의 Microservice 개발 CI/CD 기반의 Microservice 개발
CI/CD 기반의 Microservice 개발
Oracle Korea
 
kubernetes from beginner to advanced
kubernetes  from beginner to advancedkubernetes  from beginner to advanced
kubernetes from beginner to advanced
Oracle Korea
 
OpenJDK & Graalvm
OpenJDK & GraalvmOpenJDK & Graalvm
OpenJDK & Graalvm
Oracle Korea
 
Cloud Native 자바 플랫폼: Graalvm Overview
Cloud Native 자바 플랫폼: Graalvm OverviewCloud Native 자바 플랫폼: Graalvm Overview
Cloud Native 자바 플랫폼: Graalvm Overview
Oracle Korea
 
Eclipse MicroProfile 과 Microservice Java framework – Helidon
Eclipse MicroProfile 과 Microservice Java framework – HelidonEclipse MicroProfile 과 Microservice Java framework – Helidon
Eclipse MicroProfile 과 Microservice Java framework – Helidon
Oracle Korea
 
times ten in-memory database for extreme performance
times ten in-memory database for extreme performancetimes ten in-memory database for extreme performance
times ten in-memory database for extreme performance
Oracle Korea
 
[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자
Oracle Korea
 
[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service
[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service
[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service
Oracle Korea
 

More from Oracle Korea (20)

Oracle Blockchain Platform_Wonjo Yoo
Oracle Blockchain Platform_Wonjo YooOracle Blockchain Platform_Wonjo Yoo
Oracle Blockchain Platform_Wonjo Yoo
 
Oracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTOOracle Blockchain_JaeHo Park_CTO
Oracle Blockchain_JaeHo Park_CTO
 
Oracle cloud data interface
Oracle cloud data interfaceOracle cloud data interface
Oracle cloud data interface
 
On premise db &amp; cloud database
On premise db &amp; cloud databaseOn premise db &amp; cloud database
On premise db &amp; cloud database
 
Spring boot microservice metrics monitoring
Spring boot   microservice metrics monitoringSpring boot   microservice metrics monitoring
Spring boot microservice metrics monitoring
 
Opentracing jaeger
Opentracing jaegerOpentracing jaeger
Opentracing jaeger
 
Which Questions We Should Have
Which Questions We Should HaveWhich Questions We Should Have
Which Questions We Should Have
 
Oracle NoSQL
Oracle NoSQLOracle NoSQL
Oracle NoSQL
 
Enterprise Postgres
Enterprise PostgresEnterprise Postgres
Enterprise Postgres
 
MySQL Document Store를 활용한 NoSQL 개발
MySQL Document Store를 활용한 NoSQL 개발MySQL Document Store를 활용한 NoSQL 개발
MySQL Document Store를 활용한 NoSQL 개발
 
API Design Principles Essential 
API Design Principles Essential API Design Principles Essential 
API Design Principles Essential 
 
SpringBoot and Spring Cloud Service for MSA
SpringBoot and Spring Cloud Service for MSASpringBoot and Spring Cloud Service for MSA
SpringBoot and Spring Cloud Service for MSA
 
CI/CD 기반의 Microservice 개발
 CI/CD 기반의 Microservice 개발 CI/CD 기반의 Microservice 개발
CI/CD 기반의 Microservice 개발
 
kubernetes from beginner to advanced
kubernetes  from beginner to advancedkubernetes  from beginner to advanced
kubernetes from beginner to advanced
 
OpenJDK & Graalvm
OpenJDK & GraalvmOpenJDK & Graalvm
OpenJDK & Graalvm
 
Cloud Native 자바 플랫폼: Graalvm Overview
Cloud Native 자바 플랫폼: Graalvm OverviewCloud Native 자바 플랫폼: Graalvm Overview
Cloud Native 자바 플랫폼: Graalvm Overview
 
Eclipse MicroProfile 과 Microservice Java framework – Helidon
Eclipse MicroProfile 과 Microservice Java framework – HelidonEclipse MicroProfile 과 Microservice Java framework – Helidon
Eclipse MicroProfile 과 Microservice Java framework – Helidon
 
times ten in-memory database for extreme performance
times ten in-memory database for extreme performancetimes ten in-memory database for extreme performance
times ten in-memory database for extreme performance
 
[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자[Main Session] 카프카, 데이터 플랫폼의 최강자
[Main Session] 카프카, 데이터 플랫폼의 최강자
 
[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service
[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service
[Demo session] 관리형 Kafka 서비스 - Oracle Event Hub Service
 

[Main Session] 보안을 고려한 애플리케이션 개발 공정 및 실무적 수행 방법 소개

  • 1. 보안 어플리케이션 개발 공정 및 실무적 수행 방법 마이크로포커스 (구 한국HP) 김상현 컨설턴트 CISA/CISSP/AWS SA, SysOps Admin/OCP/OCJP sanghyoun.kim@microfocus.com 2018/04/21 (토), 마루180
  • 2. Table of Contents 1. 어플리케이션 보안 현황 2. 소프트웨어 개발 보안의 시작 - 시큐어 코딩  정적 코드 분석기  시큐어 코딩 예제, Mindset Deep Dive  정적 코드 분석 실무 예제  보안 스코어  정적 코드 분석과 머신 러닝 3. 안전한 어플리케이션 운영  안전한 운영 및 지속적인 모니터링 – RASP 4. 마치며 2/120
  • 4.  데이터 침해 사고의 84%가 웹 어플리케이션 취약점을 활용 – 가트너, 2014  어플리케이션 보안 (AppSec) 지출은 경계 보안의 23분의 1 어플리케이션 보안 현황 4/120
  • 5. 어플리케이션 복잡도 증가  어플리케이션의 규모와 복잡도 상승  아웃소싱 소프트웨어  COTS (Commercial Off-the-Shelf; 상용) 소프트웨어  오픈 소스 컴포넌트  레거시 소프트웨어 (유지 보수 만료, 소스 코드 망실)  이 모든 요소들을 보안 위협으로부터 보호하고 규제와 컴플라이언스 충족 필요 5/120
  • 6. Proactive vs. Reactive  Proactive  개발 단계부터 예상 가능한 취약점을 선제적으로 제거  코딩 규칙을 정의하고 소스 코드 취약 목록을 개발 단계에서부터 제거하기 위한 "시큐어 코딩" 기법이 대표적  Reactive  테스트/운영 환경에서 공격을 반응적으로 탐지하고 차단  고도화/정교화되는 어플리케이션에 대한 공격  단편적인 대응으로는 대응 불가  소프트웨어 보안 보증 (Software Security Assurance), 보안 소프트웨어 개발 공정 (Secure SDLC) Proactive Approach Reactive Approach Secure SDLC 보안 요구 사항, 위험 분석 개발 가이드라인, 코드 리뷰, 정적 코드 분석 동적 분석 방화벽, IDS/IPS, WAF 6/120
  • 7.  Introduced by Microsoft  Software development process  Helps developers build more secure software & address security compliance requirements  Reduce development cost Source:www.microsoft.com/en-us/sdl/ Security Development Lifecycle (SDL) 7/120
  • 8. 어플리케이션 개발 보안의 시작 – 시큐어 코딩
  • 9. 구조/기술적 부채(負債)  경험 많고 노련한 개발자는 잘못된 설계/코딩에 따른 결함을 바로잡는데 많은 비용과 노력이 필요하다는 것을 잘 알고 있음  Architectural/Technical Debt  배포 이후에 결함을 수정하는 것은 설계 시 바로잡는 것에 비해 30배의 비용이 소요 - 미국 국립 표준 기술 연구소 (NIST)  https://www.nist.gov/sites/default/files/documents/director/planning/report02-3.pdf 9/120
  • 10.  늦게 바로잡을수록 많은 노력과 비용이 누적 구조/기술적 부채(負債) 10/120
  • 11.  85%의 결함이 개발 단계에서 양산 (하늘색)  탐지율은 이후 단계에서 상승 (노란색)  체계화된 개발 방법론 부재  개발자별 보안 인식 및 수준 차이  탐지가 어려운 실수나 논리적 오류  이러한 불일치가 결함 조치 비용의 상승을 불러옴  탐지율 그래프를 가급적 왼쪽으로 이동시켜야 함  Shift- Left  시큐어 코딩! 개발 단계별 결함 발생 및 탐지의 불일치 11/120
  • 12. 시큐어 코딩 방법론 • 개발자 수준에 따른 산출물 차이 • 실수나 논리적 오류 제거 SDL의 시작점 • 소프트웨어 개발 수명 주기 (SDL; Software Development Lifecycle)의 시작점 Metric • 소프트웨어 보증(Software Assurance) 지표 (Metric) 가 수집되는 첫 단계 12/120
  • 13. 소프트웨어 도구 평가 방법 개발 도구 및 기법의 효과 측정 방화벽, SCADA, 웹 응용 프로그램, 소스 코드 보 안 분석기, 시공 방법 등 광범위한 영역 시큐어 코딩 해외 동향 – NIST SAMATE 3가지 방 법론 10개의 참여팀* 최대 4.7M LOC Use Case SAMATE (Software Assurance Metrics and Tool Evaluation) - https://samate.nist.gov/Main_Page.html - *서울대의 Sparrow 팀 참여 13/120
  • 14.  “소프트웨어 보증 참조 데이터셋”(SARD; Software Assurance Reference Dataset)  NIST SAMATE 하부 프로젝트  개발자에게 필요한 다양한 개발 언어별 취약점 패턴 정보, 해결 방법, 테스트 케이스의 소스 코드 다운로드 가능  https://samate.nist.gov/SARD/testsuite.php  주의) 일부 테스트 케이스는 프로젝트 참여 업체의 솔루션에 Bias됨 NIST SARD 14/120
  • 15. 시큐어 코딩 국내 동향 – “SW 개발보안” 제도 2012.12 •행정안전부 “SW 개발보안" 의무제 시행 •사업 규모 40억원 이상 2014.01 •사업 규모 20억원 이상으로 확대 2015.01 •감리 대상 전체 2016.12 •「행정기관 및 공공기관 정보시스템 구축ㆍ운영 지침」(2016.12.26) 개정 •“SW 개발보안” 적용범위가 설계단계까지 확대 2017.01 •“소프트웨어 개발 보안 가이드” 개정 15/120
  • 16.  한국인터넷진흥원(KISA)  관련 법령 현황  고시 및 권고  기술 안내서 가이드 조회 및 다운로드 가능  http://www.kisa.or.kr/public/laws /laws3.jsp  기술 안내서의 경우 주로 자바 기반 기술에 국한 시큐어 코딩 국내 동향 – KISA 16/120
  • 17.  시큐어 코딩에 대한 이론적인 배경을 설명할 수 있는 시큐어 코딩 솔루션과 정적 코드 분석기의 특징을 잠깐 살펴보고자 합니다! 시큐어 코딩 예제 및 데모를 살펴보기 전에 17/120
  • 18. 시큐어 코딩 솔루션의 구성 Static Analysis – SCA Source Code Mgt. System Static Analysis Via Build Integration Dynamic Analysis – Vulnerability Scanner Dynamic Testing in QA or Production Application Protection – RASP Real-time Protection of Running Application Vulnerability Management Normalization (Scoring, Guidance) Vulnerability Database Remediation IDE Plug-ins (Eclipse, Visual Studio, etc.) Developers (onshore or offshore) Correlate Target Vulnerabilities with Common Guidance and Scoring Defects, Metrics and KPIs Used to Measure Risk Application Lifecycle Development, Project and Management Stakeholders Software Security CenterCloud Support Hackers & Actual Attacks Correlation (Static, Dynamic, Runtime) Threat Intelligence Rules Management (구성 예) 18/120
  • 19. 시큐어 코딩 솔루션의 구성 – 정적 코드 분석기 Vulnerable Code 분석 결과 제시 XSS – Cross Site Scripting! 19/120
  • 20. 시큐어 코딩 솔루션의 구성 – 정적 코드 분석기 화이트 박스 테스팅 • 소스 코드에 대해 모든 가시성을 가지고 취약점 을 분석 런타임 모사 (模寫) 메트릭 • 실행 시의(Runtime) 모든 정황(Context)를 개발 시점에(Development-time)에 최대한 모사(模寫)할 수 있어야 함 • 정탐율 (Sensitivity) vs. 오탐율 (Specificity) 다양한 분석 기법 • 데이터 및 논리 흐름 • 구조 및 의미 분석 • 환경 요소 파악 • 버퍼 분석 • 머신 러닝 20/120
  • 21. 시큐어 코딩 솔루션의 구성 – 취약점 관리 시스템 분석 결과 Audit Report 프로젝트 매니저/보안 책임자 조치 작업 할당 21/120
  • 22. 시큐어 코딩 솔루션의 구성 – 취약점 관리 시스템 관리 저장소 • 모든 어플리케이션의 취약점 분석 결과를 체계적으로 관리 역할 분리 • 조직화된 보안 활동과 협업 체계 구축 • 담당자별 역할 분리 • 개발자 - 취약점 수정 • 개발PM - 취약점 추적 및 담당 개발자 할당 • CISO/CIO - 취약점 보고서 조회 및 어플리케이션 수명 주기 관리 DevOps/DevSecOps 가속 • CI/CD 툴(Jenkins), 취약점 관리 시스템(JIRA, BugZilla 등) 과의 연계 기능 • 보안과 결합된 DevOps 문화(DevSecOps)를 가속화하는데 기여 22/120
  • 23. 시큐어 코딩 솔루션의 구성 – 개발자 지원 실시간 분석 중요 취약점에 대한 실시간 정보 23/120
  • 24. 시큐어 코딩 솔루션의 구성 – 개발자 지원 Security Automation 관점에서 중요 보안에 대한 지식이나 경험이 부족한 초보 개발자도 쉽게 활용할 수 있도록 지원 Eclipse, IntelliJ, Microsoft Visual Studio 등 다양한 통합 개발 환경에서 정적 코드 분석을 실행할 수 있도록 도와주는 플러그인과 Ant, Maven 등의 빌드 시스템과 연계할 수 있는 기능 Tool Fatigue, Process Friction 최소화 24/120
  • 26. 정적 코드 분석 성능 지표 정탐율 (Sensitivity, Recall) 전체 취약점 중 얼마나 많이 보고되었나? = 오탐율 (Specificity, Fall-out) 전체 정상 처리 중 얼마나 많은 수가 취약한 것으로 잘못 보고되었나? = 정확도 (Precision) 보고된 취약점 중 실제로 취약점은 얼마나 되나? = #TP #TP + #FN #TP #TP + #FP #FP #FP + #TN 취약점 정상 처리 True Positives (TP, 정탐) False Positives (FP, 오탐) 탐지 보고 False Negatives (FN, 미탐) True Negatives (TN, 정미탐) 27/120
  • 27. 정적 코드 분석 성능 지표  정확도 (Precision) = #TP / (#TP + #FP)  보고된 전체 취약점 중 실제 취약점 비율, 높을 수록 좋음  Sensitivity (Recall율) = #TP / (#TP + #FN)  실제 전체 취약점 중 보고된 취약점 비율, 높을 수록 좋음  Specificity (Fall-out) = #FP / (#FP + #TN)  실제 전체 미 취약점 (정상 처리) 중 양성으로 잘못 보고된 비율, 낮을 수록 좋음  대부분의 툴이 정확도에서 80% 넘지 못함  Recall율에 있어서도 거의 모든 툴이 50%를 넘기지 못함 • 위양성: 1종 오류, 알파 오류, 오탐이라고도 함 • 위음성: 2종 오류, 베타 오류, 미탐이라고도 불림 보고 (Reported) 미보고 (Non-Reported) 실제 취약점 진양성 (True Positive; TP) 위음성 (False Negative; FN) 취약점 아님 위양성 (False Positive; FP) 진음성 (True Negative; TN) 28/120
  • 28. 정적 코드 분석의 효용성 취약점 정상 처리 탐지군 29/120
  • 29. 정적 코드 분석의 효용성 취약점 정상 처리 True Positives (TP, 정탐) False Positives (FP, 오탐) 탐지 보고 False Negatives (FN, 미탐) True Negatives (TN, 정미탐) Shift Left Find More - 모든 취약점이 발견되고 해소되기는 불가능 - 취약점만을, 많이 탐지하도록 – Shift Left, Find More - 랜덤 추측에서는 탐지보고 타원 영역이 중앙에 위치 - 좋은 정적 코드 분석 솔루션은 타원 영역을 왼쪽으로, 그리고 큰 영역을 커버하면서 움직임 - 정적 코드 분석 솔루션으로 탐지되지 않는 취약점이 여전히 존재할 수 있는데 DAST와 RASP를 통해 재탐지하고 실행시 보호 30/120
  • 30. 정적 코드 분석의 보완 31/120
  • 31. 정적 코드 분석 OWASP 벤치마크 프로젝트 OWASP Benchmark Project 11개 영역, 총 21,042 테스트 케 이스 오픈 소스 5종 (총 조합 10가지) 상용 솔루션 6종 지표 측정 32/120
  • 32. 정적 코드 분석 OWASP 벤치마크 프로젝트 결과  Youden Index (정탐율 (TPR) - 오탐율 (FPR))을 스코어(Score)로 사용  상용 솔루션이 오픈 소스 솔루션에 비해 근소하게 양호한 점수를 기록 (26% vs. 22%)  상용 솔루션이 수행한 테스트 케이스가 오픈 소스 솔루션에 비해 8배 많음 (21041 vs. 2704)  오픈 소스 솔루션 상용 솔루션에 비해 결과의 편차가 큼 (표준편차: 오픈소스 0.1418 vs. 상용 0.0650)  오픈 소스 솔루션의 경우 분석 수행 시간이 짧음 – 적은 테스트 케이스 33/120
  • 33. 정적 코드 분석 OWASP 벤치마크 프로젝트 결과 (Cont’d)  모든 솔루션들이 정탐율이 높아질수록 오탐율도 함께 올라가는 경향  오픈 소스 솔루션 중 가장 좋은 점수를 보인 FBwFindSecBugs v1.4.6 의 경우 오탐율도 가장 높은 것으로 나타남 (57.74%)  탐지된 취약점이 실제로 유효한 취약점인지를 파악하기 위한 추가적인 후속 조치가 필요하며, 솔루션의 사용성을 떨어뜨릴 수 있음 34/120
  • 34. 개발자의 역량에 맡김 vs. 시큐어 코딩 솔루션 도입 자체 처리 솔루션 도입 솔루션 도입에 따른 이득이 자체 투자보다 클 때 오픈 소스가 광범위하게 사용 되고 통제가 어려울 때 대외 서비스 프로젝트, 중요한 내부 자산 규제/컴플라이언스 요건 충족 필요 솔루션 도입에 따른 비용이 취약점 침해 에 따른 비용보다 크다고 판단될 때 오픈 소스 도입이 없거나 통제 가능 내부 전용 Pilot 프로젝트 내부 개발 역량으로 대응 가능 35/120
  • 36. 시큐어 코딩  잘 알려진 일반적인 취약점부터 시작! 38/120
  • 38.  브라우저에서 아래 주소 입력  http://riches2.mydemo.co.kr:580 82/riches/  참고) 예제에 인용된 URL( 서버)은 실습을 위해 꾸며 진 것이로서, 사전 예고없 이 접속이 불가능할 수 있 습니다 A1: Injection – SQL Injection 40/120
  • 39.  Username: ”eddie”, Password: “eddie” 입력하여 로그인  로그인이 되면 “Account Summary” 페이지로 이동 A1: Injection – SQL Injection (계속) 41/120
  • 40.  표시된 “0422328325” 링크를 클릭하여 계좌 이력을 조회 A1: Injection – SQL Injection (계속) 42/120
  • 41. A1: Injection – SQL Injection (계속)  브라우저의 주소창에 [' or '1' = '1]를 추가하고 엔터  “개발자가 의도하지 않았던” 다른 계좌의 정보도 조회됨 43/120
  • 42.  데이터베이스와 연동된 웹 어플리케이션에서 입력된 데이터의 유효성 검증 누락  공격자가 입력 폼, URL 입력란에 SQL을 삽입  주로 개발자가 의도하지 않은 형태로 Where Predicate가 변조된 동적 쿼리문 생성  실행이 성공하면 공격자로 데이터가 유출 A1: Injection – SQL Injection 공격 흐름 44/120
  • 43.  PreparedStatement 클래스를 활용하여 인입되는 매개변수를 바인드 변수 처리하고 executeQuery(), execute(), executeUpdate() 메서드 호출  PreparedStatement 클래스를 활용하기 어렵다면 입력값에 대한 Validation을 수행한 후 사용  Validation은 SQL 구문 제한, 특수 문자 제한, 길이 제한 등을 복합적으로 활용 A1: Injection – SQL Injection 대응 코딩 기법 45/120
  • 44. A1: Injection – SQL Injection 대응 코딩 기법 변경 전 변경 후 46/120
  • 45. A1: Injection – SQL Injection 대응 결과  공격 무효화  확인: http://riches3.mydemo.co.kr:58083/riches 47/120
  • 46.  브라우저에서 아래 주소 입력  http://riches2.mydemo.co.kr:580 82/riches/ A1: Injection – Command Injection 48/120
  • 47. A1: Injection – Command Injection (계속)  Username: ”admin”, Password: “admin” 입력하여 로그인  로그인 후 “Admin Messaging” 페이지로 이동 49/120
  • 48. A1: Injection – Command Injection (계속)  메시지 본문에 ["; cat /etc/passwd"] 입력 후 “Send 버튼 클릭”  시스템의 사용자 목록이 조회됨을 확인 50/120
  • 49.  적절한 검증 절차를 수행하지 않은 사용자 입력값이 운영체제 명령어의 일부 또는 전부로 구성되어 실행  부적절한 권한 변경, 시스템 리소스의 통제되지 않은 조회 가능 A1: Injection – Command Injection 공격 흐름 51/120
  • 50.  인터페이스를 통해 전달되는 매개변수를 그대로 시스템 명령어로 사용하지 않는다  외부 입력에 따라 통제된 경로로 시스템 명령어를 생성하며, 선택이 필요한 경우 명령어 생성에 필요한 값을 미리 지정해 두고 선택적으로 활용 A1: Injection – Command Injection 대응 코딩 기법 52/120
  • 51. A1: Injection – Command Injection 대응 코딩 기법 Validation 추가 53/120
  • 52. A1: Injection – Command Injection 대응 결과  공격 무효화  확인: http://riches3.mydemo. co.kr:58083/riches  주의: 체계적인 대응을 위해서는 운영 체제 환경, WEB/WAS 시스템, 프레임웍 현황에 대한 정확한 이해가 필요함 54/120
  • 53. A7: Cross Site Scripting (XSS)  전통적인 공격 기법이고 많은 대응이 이루어지고 있지만 여전히 보편적인 어플리케이션 취약점  제어문, 형태 정의 태그, 실제 내용 등이 평면적이고 순차적으로 담겨 있는 HTML의 특성상 완전히 배제하는 것은 불가음 – 효과가 입증된 정형화된 패턴을 따르는 것을 권장 55/120
  • 54. A7: Cross Site Scripting (XSS) - Reflected 56/120
  • 55. A7: Cross Site Scripting (XSS) - Reflected  공격자는 악의적인 스크립트가 담긴 URL 링크가 담긴 이메일을 사용자(Victim)에게 전달  사용자는 링크를 클릭하여 웹 사이트에 접속하고  접속 후에 스크립트가 실행되어 공격을 수행 – 예) 사용자의 정보 (쿠키 등)를 공격자에게 전송 57/120
  • 56.  브라우저에서 아래 주소 입력  http://riches2.mydemo.co.kr:580 82/riches/  주의) 일부 브라우저(예: 크롬, 사파리)에서는 XSS 스크립트 전송을 막는 기능이 있으므로 다른 브라우저 이용 (인터넷 익스플로러, 파이어폭스) A7: Cross Site Scripting (XSS) - Reflected 58/120
  • 57.  인증창의 Username에 [<script>alert('1');</script>]를 입력하고 “Go” 버튼 클릭 A7: Cross Site Scripting (XSS) - Reflected 59/120
  • 58.  스크립트가 실행되는 것을 확인  공격자는 이 스크립트를 좀 더 악의적인 목적으로 이용 가능  예) 공격자에게 사용자의 쿠키 정보를 전송 A7: Cross Site Scripting (XSS) - Reflected 60/120
  • 59.  웹 서버로 전달되는 모든 입력값을 직접 Validation  검증된 패턴 API를 활용  OWASP 보안 API ESAPI.encoder().encodeForHTMLAttrib ute(input);  XSS Filter com.jesephoconnel.html.HTMLInputFilt er.filter(input); A7: Cross Site Scripting 대응 코딩 기법 From To < &lt; > &gt; ( &#40; ) &#41; # &#35; & &#38; 61/120
  • 60. A7: Cross Site Scripting 대응 코딩 기법 62/120
  • 61.  입력값 중 스크립팅 요소가 Actionable하지 않은 문자열로 변환되므로써 공격이 무효화됨 A7: Cross Site Scripting 대응 코딩 기법 63/120
  • 62.  잘 알려진 Cross Site Scripting 공격 기법 2가지 중 하나인 Reflected 방법을 알아보았습니다.  그러면 다른 하나는 무엇일까요? 힌트 “P”로 시작하는 형용사형을 정확하게 맞춰 주세요. Quiz – 빨리 맞추신 분께는 상품을 드려요! 64/120
  • 63. KISA 시큐어 코딩 가이드  http://www.kisa.or.kr/public/ laws/laws3_View.jsp?cPage= 6&mode=view&p_No=259&b _No=259&d_No=55&ST=T&S V= 65/120
  • 65.  신뢰할 수 없는 입력이 잠재적으로 어플리케이션의 동작을 제어하는 취약점을 검출하는 분석기 (혹은 사람)  Injection 공격  분석기는 오염 (Taint)의 전반적인 전파 (Propagation) 상황을 파악하여 신뢰할 수 없는 데이터의 흐름을 추적  Source  신뢰되지 않는 (즉, 사용자가 통제하는) 입력  Sink  잠재적으로 위험한 함수 호출이나 동작 Data Flow Analyzer 67/120
  • 66. Understanding Data Flow 1 import java.sql.*; 2 3 public class SQLInjection { 4 public static void main (String args[]) { 5 Connection conn = null; 6 try { 7 String userName = args [0]; 8 String passwd = args [1]; 9 String query = "select uname, passwd from users where uname like "+userName+"%"; 10 conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); 11 Statement stmnt = conn.createStatement (); 12 ResultSet rs = stmnt.executeQuery (query); 13 while ( rs.next() ) { 14 ... 15 } 16 rs.close (); 17 stmnt.close (); 18 conn.close (); 19 } 20 catch (SQLException err) { 21 err.printStackTrace (); 22 } 23 } 24 } 68/120
  • 67. Understanding Data Flow import java.sql.*; public class SQLInjection { public static void main (String args[]) { Connection conn = null; try { String userName = args [0]; String passwd = args [1]; String query = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statement stmnt = conn.createStatement (); ResultSet rs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLException err) { err.printStackTrace (); } } } Source 69/120
  • 68. Understanding Data Flow import java.sql.*; public class SQLInjection { public static void main (String args[]) { Connection conn = null; try { String userName = args [0]; String passwd = args [1]; String query = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statement stmnt = conn.createStatement (); ResultSet rs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLException err) { err.printStackTrace (); } } } args[] is tainted Source 70/120
  • 69. Understanding Data Flow import java.sql.*; public class SQLInjection { public static void main (String args[]) { Connection conn = null; try { String userName = args [0]; String passwd = args [1]; String query = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statement stmnt = conn.createStatement (); ResultSet rs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLException err) { err.printStackTrace (); } } } Taint propagated to userName args[] is tainted Source 71/120
  • 70. Understanding Data Flow import java.sql.*; public class SQLInjection { public static void main (String args[]) { Connection conn = null; try { String userName = args [0]; String passwd = args [1]; String query = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statement stmnt = conn.createStatement (); ResultSet rs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLException err) { err.printStackTrace (); } } } Tainted input userName used in assignment Taint propagated to userName args[] is tainted Source 72/120
  • 71. Understanding Data Flow import java.sql.*; public class SQLInjection { public static void main (String args[]) { Connection conn = null; try { String userName = args [0]; String passwd = args [1]; String query = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statement stmnt = conn.createStatement (); ResultSet rs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLException err) { err.printStackTrace (); } } } Sink Tainted input userName used in assignment Taint propagated to userName args[] is tainted Source 73/120
  • 72. Understanding Data Flow import java.sql.*; public class SQLInjection { public static void main (String args[]) { Connection conn = null; try { String userName = args [0]; String passwd = args [1]; String query = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statement stmnt = conn.createStatement (); ResultSet rs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLException err) { err.printStackTrace (); } } } Vulnerability Reported Sink Tainted input userName used in assignment Taint propagated to userName args[] is tainted Source 74/120
  • 73.  위험할 수 있는 일련의 동작이나 함수 호출을 검출  상태 머신(State Machine) 모델을 사용하여 상태의 전이 상태를 판단  각 상태 머신은 취약점이 악용될 수 있는 “에러 상태”를 가질 수 있음  분석가는 이러한 상태 머신을 파악할 수 있는 지식이나 룰을 가지고 있어야 함 Control Flow Analyzer 75/120
  • 74. Understanding Control Flow 1 private void cmdLogin_Click(object sender, System.EventArgs e){ 2 Label lblMsg = null; 3 try { 4 string txtUser = Request.Form["txtUsername"]; 5 string txtPassword = Request.Form["txtPassword"]; 6 string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; 7 SqlConnection cnx = new SqlConnection(strCnx); 8 cnx.Open(); 9 10 string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + 11 txtUser + "' AND Password='" + txtPassword + "'"; 12 int intRecs; 13 14 SqlCommand cmd = new SqlCommand(strQry, cnx); 15 intRecs = (int)cmd.ExecuteScalar(); 16 17 if (intRecs > 0){ 18 FormsAuthentication.RedirectFromLoginPage(txtUser, false); 19 cnx.Close(); 20 } 21 else{ 22 lblMsg.Text = "Login attempt failed."; 23 } 24 } 25 catch (Exception err){ 26 Response.Write(err.StackTrace.ToString()); 27 } 28 } 76/120
  • 75. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Variable initialized & assigned 77/120
  • 76. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Connection closed Variable initialized & assigned 78/120
  • 77. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Safe Sequence Connection closed Variable initialized & assigned 79/120
  • 78. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Variable initialized & assigned 80/120
  • 79. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Variable initialized & assigned Control Flow observes all possible paths 81/120
  • 80. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Analyze until cnx is out of scope Variable initialized & assigned Control Flow observes all possible paths 82/120
  • 81. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Analyze until cnx is out of scope Variable initialized & assigned Control Flow observes all possible paths Vulnerability Reported 83/120
  • 82. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Variable initialized & assigned Control Flow observes all possible paths 84/120
  • 83. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Analyze until cnx is out of scope Variable initialized & assigned Control Flow observes all possible paths 85/120
  • 84. private void cmdLogin_Click(object sender, System.EventArgs e){ Label lblMsg = null; try { string txtUser = Request.Form["txtUsername"]; string txtPassword = Request.Form["txtPassword"]; string strCnx = "server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry = "SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0){ FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else{ lblMsg.Text = "Login attempt failed."; } } catch (Exception err){ Response.Write(err.StackTrace.ToString()); } } Understanding Control Flow Vulnerability Reported Analyze until cnx is out of scope Variable initialized & assigned Control Flow observes all possible paths 86/120
  • 85. 자동화된 정적 코드 분석 실무 예제
  • 86. 1. 경영진은 앞서 살펴 보았던 “riches” 웹 어플리케이션이 회사의 Reputation을 심하게 훼손하고 비즈니스의 연속성을 해칠 보안 취약점이 있다고 판단 2. DevSecOps 태스크포스를 구성하여 보안 취약점을 소스 코드 차원에서 진단하여 보안성을 제고할 방안을 찾기 시작 예제 시나리오 88/120
  • 87. 1. 하지만 새로운 기능을 담은 전면적인 Renewal을 앞두고 있는 상황이라 발견된 취약점을 수정, 검증하기에는 현실적으로 시간적인 어려움이 있음 2. “Bi-Directional AppSec in CI/CD Pipeline” 전술을 구사하기로 결정 1) 기존에 운영되던 Jenkins의 Nightly Build 프로세스 (새벽 4시)에 정적 코드 분석 단계를 추가 2) Ops/QA 팀은 분석 결과 취약점 지표가 기준치보다 높으면 Dev 조직에 발견된 취약점의 수정을 지시 – Reverse AppSec 3) Ops 팀은 수정된 코드의 검증 기간을 기다리기에는 Renewal 오픈 기간이 촉박하므로 그대로 Production 환경에 Deploy, 대신 어플리케이션의 취약점을 런타임 수준에서 방어해주는 런타임 자가 방어 (RASP; Runtime Application Self Protection) 기술을 사용할 예정 – Forward AppSec 예제 시나리오 89/120
  • 88. Bi-Directional AppSec Pipelining in CI/CD Commit Build Test Stage DeployDev Prod CI/CD 정적 코드 분석 취약점 수정 Reverse AppSec Forward AppSec 취약점 스캐닝/RASP를 통한 안전한 운영 및 지속적인 모니터링 90/120
  • 89. 참고  이번 예제에서는 특정 정적 코드 분석 솔루션의 기능을 소개하기 보다는 정적 코드 분석 솔루션의 일반적인 특징과 사용 방법에 중점을 두고 이야기해 보고자 합니다.  따라서 여기서는 솔루션의 특징적인 부분들, 예를 들어 설치 경로와 사용되는 명령어의 구성 등에 대해서 관심을 두기 보다는 시큐어 코딩 활동을 위해 정적 코드 분석 솔루션이 사용되는 전체적인 흐름에 집중하면 좋을 것입니다. 91/120
  • 90. Jenkins 프로젝트 기존의 빌드 Job이 Freestyle Project 임을 가정 92/120
  • 91. Jenkins 프로젝트 빌드 명령어도 기존의 빌드 스크립트와 동일 93/120
  • 92. Jenkins 프로젝트 빌드 외에 정적 코드 분석을 추가로 실시하도록 설정 정적 코드 분석기에 따라 달라질 수 있음94/120
  • 93. Jenkins 프로젝트 솔루션에 따라 코드 분석 결과를 중앙 관리 서버로 자동으로 전송하는 기능을 추가 사용95/120
  • 94. Jenkins 프로젝트 실행 화면 - 정규 취약점 점수 (NVS): 387.2점 – 이후 장표에서 설명 96/120
  • 95. Jenins 프로젝트 실행 화면 온라인 확인  클라우드 데모 서버의 온라인 대시 보드  https://cloud.skytap.com/vms/47c 39c3786da57bf2658ddd6428ae68f /desktops  https://goo.gl/kGZXQv (간단 URL)  참고) Instructor의 조작 필요 97
  • 96. Jenins 프로젝트 실행 화면 온라인 확인  혹은 Jenkins에 직접 로그인하여 확인  http://jenkins.mydemo.co.kr:8080/ jenkins 98
  • 97. Jenkins 프로젝트 실행 화면 - 정규 취약점 점수 (NVS): 387.2점 – 이후 장표에서 설명 99/120
  • 98. AppSec Myth 모든 취약점 발견 시도 모든 취약점이 해소되어야 함 AppSec Myth 불가능! 비용 효과 X Metric “적절한” 보안 수준 설정 충족되면 다음 단계로 이관 100/120
  • 99. AppSec Metric – 정규 취약점 점수 (NVS)  Impact & Likelihood  CFPO: Critical로 분류된 취약점 수  HFPO: High로 분류된 취약점 수  MFPO: Medium으로 분류된 취약점 수  LFPO: Low로 분류된 취약점 수  Security Quality  P1: 신뢰성이 떨어지는 코드 개수  P2: Best Practice를 따르지 않는다고 판단된 코드 개수  P3: 의심이 가는 코드 개수  PABOVE: Exploitable (해커에 의해 이용이 가능한) 코드 개수  ExecutableLOC: 실행 가능 코드 라인 수 NVS: Normalized Vulnerability Score 계산이 비교적 간단하고, 각 우선 순위별 가중치를 필요에 따라 적절히 조절할 수 있으므로 많이 사용되는 취약점 산정 지표 101/120
  • 100. Bi-Directional AppSec Activity by NVS! 개발팀 조치 (NVS 200 이상) 리뉴얼 배포 (NVS 400 이하) NVS 기준 102/120
  • 101. 정적 코드 분석과 머신 러닝 Machine Learning • Reduce false positive noise • Streamline cumbersome & audit process • Provide results unique to organization’s preference • Better utilize the resources 103/120
  • 102.  Supervised Learning First - More data, better result  Underlying ML algorithm can be extended to unsupervised clustering, data views and outlier detection 정적 코드 분석과 머신 러닝 104/120
  • 103. 머신 러닝 Smart View 105/120
  • 104. Prediction Confidence & Issue Graph 106/120
  • 105.  담당 개발자에게 할당 시 Machine Learning 예측 지표 전달  개발자는 이를 참고하여 적절한 보완 조치 수행 Assign to Developer with Machine Learning Feedback 107/120
  • 107. 배포된 어플리케이션의 취약점은? Commit Build Test Stage DeployDev Prod CI/CD 정적 코드 분석 취약점 수정 Reverse AppSec Forward AppSec ? 109/120
  • 108. 배포된 어플리케이션의 취약점은? Commit Build Test Stage DeployDev Prod CI/CD 정적 코드 분석 취약점 수정 Reverse AppSec Forward AppSec 취약점 스캐닝/RASP를 통한 안전한 운영 및 지속적인 모니터링 110/120
  • 109. 자기 방어 응용 프로그램 2014년 APM 솔루션 시장 규모: $2.72B 2019년에 $4.98B예상 (CAGR 12.86%) • 런타임 어플리케이션 자기 방어 (Runtime Application Self-Protection; RASP) • RASP는 응용 프로그램의 런타임 환경과 결합되어 응용 프로그램 자체의 실행을 통제하고, 실시간으로 공격을 탐지 및 방어하는 보안 기술 • 2017년 10대 기술 트렌드 – 가트너 • 런타임 환경의 성숙과 함께 찾아온 일종의 프레임워크 협업 모델 • 런타임 제작사: 확장 가능한 런타임 설계 • 프레임워크 구현 벤더: 런타임의 확장성을 구현 • APM 시장은 이미 성장을 넘어 성숙 단계로… 111/120
  • 110. 자기 방어 응용 프로그램 - RASP 어플리케이션 서버 RASP 서버 에이전트/보안 규칙 방어/모니터링 이벤트 어플리케이션 자기 방어 에이전트 프로그램 포인트 실시간 공격 런타임 1. 런타임 시작 시 자기 방어 에이전트를 로드합니다. A. 보안 서버로부터 보안 규칙을 받아 적용할 수도 있습니다. 2. 자기 방어 에이전트는 취약하거나 중요한 실행 지점에 보호 로직을 “편성” 합니다.  프로그램 포인트 및 인스트루먼테이션 (Instrumentation) 1 2 1.A 3 3. 공격자가 해당 프로그램 포인트에 대해 공격을 감행합니다. 4. 자기 방어 에이전트는 어플리케이션을 대신하여 공격을 저지한 후 보안 서버로 이를 보고합니다. 4 Transparent to Application! Minimum Impact to Performance! 112/120
  • 111. RASP로 얻는 이점은? • Resilient Security  실행 시의 보안 위협에 탄력적으로 대응 • Visibility & Intelligence  어플리케이션에 대한 가시성을 확보하고 보안 위협을 지능적으로 처리 • Transparency  어플리케이션의 수정 없이 필수적인 보안성을 확보  No Code Changes Needed! • Lightweight & Automation  런타임에서 동작하는 가벼운 구조  어플리케이션의 수명 주기와 완전히 일치 – 자동화를 도와주고 DevOps 문화를 가속화 • Adaptability & Extensibility  프로그램 포인트와 에이전트 확장  예) 데이터베이스 호출 프로그램 포인트를 확장함으로써 DB 암호화를 응용프로그램 수정없이 구현 가능 RASP Resilient Security Visibility & Intelligence Transparency Lightweight & Automation Adaptability & Extensibility 113/120
  • 112.  http://riches1.mydemo.co.kr:58081/riches/  Protection message configurable RASP 데모 – SQL Injection 공격 방어 114/120
  • 113.  https://appdefender.microfocus.skytapdns.com:8443/ RASP 데모 – 공격 실시간 모니터링 115/120
  • 115. 보안을 위한 여정 – AppSec Journey Cycle SCA 활동으로 많은 취약점이 발견되고 조치됨 – Shift Left, Find More! 동적 분석을 통해 Scan Surface를 넓히고 SCA로 탐지하지 못한 취약점을 재탐지 여전히 남아 있을 수 있는 제로데이 취약점 등을 RASP 기술로 자체 방어 다수의 취약점이 존재하고, 안전한 코드들도 운에 의존하는 상태 117/120
  • 116. 마치며...  어플리케이션을 개발하고 검증하여 안전하게 운영하는 활동은 한 순간에 완성을 선언할 수 없는 끝없는 과정의 연속이다.  오늘날의 소프트웨어 개발 흐름에서 유행 (Viral) 하고 있는 단어 하나를 꼽으라면 단연 “DevOps”와 “CI/CD”일 것입니다.  앞에서 우리는 시큐어 코딩 예제와 정적 코드 분석기가 CI/CD 툴인 Jenkins와 연동되는 실무 예제도 함께 살펴보았다.  그리고 시간적 제약으로 불가피하게 전개될 수 밖에 없었던 어플리케이션을 빠르게 강화하고 모니터링할 수 있는 RASP에 대해서도 살펴보았습니다.  이런 흐름이 단절없이 피드백되어 개선될 때 시큐어 코딩으로 시작하는 여러분의 AppSec 활동이 보다 안전해질 것입니다! 118/120