PHP系统命令执行函数:
- system:
执行外部程序,并且显示输出,成功则返回命令输出的最后一行, 失败则
返回 false。
- exec函数:
执行一个外部程序,命令执行结果的最后一行内容。
- passthru:
执行外部命令, 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏
览器的时候, 需要用此函数来替代 exec() 或 system() 函数。 常用来执行
诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置 Content-type
为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚
本中直接输出图像到浏览器。
- ``反引号运算符:
PHP将尝试将反引号中的内容作为外壳命令执行,并将其输出信息作为返回值返回
(即可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符的效果
与函数shell_exec()相同。反引号运算符在激活了安全模式或者关闭了
shell_exec()时是无效的。
- shell_exec():
通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
- popen():
使用 command 参数打开进程文件指针。
- proc_open:
执行一个命令,并且打开用来输入/输出的文件指针。
命令执行拼接符:
- |
只执行第二个命令
- ||
第一个命令执行成功则第二个命令不执行,若1失败,则执行2
- &
不管第一个命令是否执行成功都会执行第二个命令
- &&
必须两个命令都成功才执行
- ;
第一个命令执行完成再执行第二个命令(linux系统)
命令执行漏洞简介:
可以直接在web应用中执行系统命令,从而获取敏感信息或者拿下shell权限。
命令执行漏洞原理:
web服务器对用户输入的命令安全监测不足,导致恶意代码被执行。
命令执行漏洞复现-DVWA靶场
- 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' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
并没有过滤什么东西,构造payload:127.0.0.1&cd
- 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
echo "<pre>{$cmd}</pre>";
}
?>
过滤了&&和;,就用&,payload:127.0.0.1&cd
- 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
echo "<pre>{$cmd}</pre>";
}
?>
过滤了基本所有的连接符,但注意看’| ‘里加了一个空格,所以我们可以用’|'管道符来绕过,管道符就是第一个命令的输出为第二个命令的输入,payload:127.0.0.1|cd
- 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();
?>
代码过滤十分严格,所以绕不过。
在我写的CTF中的BugkuWeb:聪明的PHP文章中,有命令执行结合模板注入的实战题型,有兴趣的可以看看
命令执行漏洞防御:
1.对拼接符以及命令执行函数等敏感词严格过滤。
2.使用escapeshe||arg函数来处理命令参数。
方法不止这两种,还有很多。