low
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
$html .= "<pre>{$cmd}</pre>";
}
?>
相关知识
php_uname( )
• 'a':此为默认。包含序列 "s n r v m" 里的所有模式。
• 's':操作系统名称。例如: FreeBSD。
• 'n':主机名。例如: localhost.example.com。
• 'r':版本名称,例如: 5.1.2-RELEASE。
• 'v':版本信息。操作系统之间有很大的不同。
• 'm':机器类型。例如:i386。
stristr函数返回 haystack 字符串从 needle 第一次出现的位置开始到结尾的字符串。
print_r(stristr( php_uname( 's' ), 'Windows NT' ))
结果:Windows NT
if( stristr( php_uname( 's' ), 'Windows NT' ) )
括号里虽然返回的是字符串但是返回值也是true 因为()这个里面会把字符串强制转化成int 也是true的
绕过方式:用&同时执行两个命令
medium
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// 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
$html .= "<pre>{$cmd}</pre>";
}
?>
相关知识:array_keys() 返回 input 数组中的数字或者字符串的键名。
strreplace如果 search 和 replace 为数组,那么 strreplace() 将对 subject 做二者的映射替换
这里就是会把&&和;替换成空
array_keys( $substitutions )
结果:
Array
(
[0] => &&
[1] => ;
)
; 命令1 ; 命令2 作用:多个命令顺序执行,命令之间没有任何逻辑联系。
&& 命令1 && 命令2 作用:逻辑与,当命令1正确执行,则命令2才会执行;当命令1执行不正确,则命令2不会执行。
& 命令1 & 命令2 作用:&不管左边执行结果是否正确都执行&右边的数据。
&&的执行图
&的执行图
两种绕过方式
-
127.0.0.1&whoami
-
127.0.0.1&;&whoami //因为str_replace会把;映射成空,就变成127.0.0.1&&net user
high
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$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 );
// 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
$html .= "<pre>{$cmd}</pre>";
}
?>
过滤了更多,但是还是有绕过方式。额外了解波知识
|| 命令1 || 命令2 作用:逻辑或,当命令1执行不正确,则命令2才会执行;当命令1正确执行,则命令2不会执行
| 命令1 | 命令2 作用:表示将Command 1的输出作为Command 2的输入,并且只打印Command 2执行的结果
绕过方式
ping 127.0.0.1|net user //这里过滤的"| "(后面有个空格)
impossible
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// 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];
// 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>";
}
else {
// Ops. Let the user name theres a mistake
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
相关知识:
stripslashes() 返回一个去除转义反斜线后的字符串 explode() 截断函数,此函数返回由字符串组成的数组,每个元素都是 string 的一个子串,它们被字符串 delimiter 作为边界点分割出来。如果设置了 limit 参数并且是正数,则返回的数组包含最多 limit 个元素,而最后那个元素将包含 string 的剩余部分。
$target="127.0.0.1";
$target = stripslashes( $target );
$octet = explode( ".", $target );
var_dump(($octet));
结果:
array(4) {
[0]=>
string(3) "127"
[1]=>
string(1) "0"
[2]=>
string(1) "0"
[3]=>
string(1) "1"
}
这里首先加了Check Anti-CSRF token 机制防止csrf,然后使用stripslashes做第一层过滤。然后使用explode分隔成4部分,依次对各个部分采用is_numeric函数进行判断,保证每部分都是数字,最后合并各个分块结果。只有数字.数字.数字.数字”的输入才能满足被执行,因此不存在命令注入漏洞
参考链接
https://www.freebuf.com/articles/web/116714.html
https://blog.csdn.net/weixin_39723165/article/details/81286839