LOW:
if( isset( $_POST[ 'Submit' ] ) ) {
// 本来的目的是接收ip地址,我们用来进行命令注入
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
//php_uname()返回跟系统有关的系统,如果参数为s则返回操作系统的名称
//stristr()是strstr()忽略大小写的版本
//strstr()的作用:查找字符串的首次出现,即第二个字符串在第一个字符串首次的位置
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
$html .= "{$cmd}
";
}
?>
然后这是非常简单的命令执行漏洞(感觉现实根本不可能有这种东西、、、)
payload:
1、windows下:
127.0.0.1&&net user
可以查看用户,然后可以创建用户,把用户添加到管理员组
2、linux下:
127.0.0.1&&cat /etc/shadow
可以查看隐藏文件
Medium:
1 php
2
3 if( isset( $_POST[ 'Submit' ] ) ) {
4 // Get input
5 $target = $_REQUEST[ 'ip' ];
6
7 // Set blacklist 过滤了危险字符
8 $substitutions = array(
9 '&&' => '',
10 ';' => '',
11 );
12
13 // Remove any of the charactars in the array (blacklist).
14 $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
15
16 // Determine OS and execute the ping command.
17 if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
18 // Windows
19 $cmd = shell_exec( 'ping ' . $target );
20 }
21 else {
22 // *nix
23 $cmd = shell_exec( 'ping -c 4 ' . $target );
24 }
25
26 // Feedback for the end user
27 $html .= "{$cmd}
";
28 }
29
30 ?>
代码的逻辑非常清楚,就是过滤掉了两个&号和分号
函数详解:
1、str_replace()
str_replace(find,replace,string)
find:要被取代的字符串
replace:取代掉find的字符串
string:被搜索的字符串
2、array_keys()
顾名思义,就是返回数组中所有的键值
先上Payload:
1、127.0.0.1&net user
2、127.0.0.1&;&net user
原理:
1、&没有被过滤,但是无论ping 127.0.0.1成功与否,net user 都会执行
而&&如果ping 127.0.0.1失败了,net user 不会执行
2、&:&中的分号被去掉之后,又变成了&&'
High:
$target = trim($_REQUEST[ 'ip' ]);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
只看关键的部分,两端的空白被过滤掉了,很多字符也被过滤掉了
但是!仔细看看,居然没有把'|'过滤掉!因为黑名单中,竖线的后面有空格。
所以payload:
127.0.0.1|net user
而"|"是管道符,将ping 127.0.0.1的输出作为输入给net user,只执行net user的结果
IMPOSSIBLE:
1、加入了反CSRF token检测
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
2、剥离了反斜杠
$target = stripslashes( $target );
3、将输入以ip地址的点分十进制的点来分割成四份,只有分割的结果只是四份且每份都是数字才算合法
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// If all 4 octets are int's put the IP back together.
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
鸣谢:https://www.freebuf.com/articles/web/116714.html