【原理】
任意命令执行原因:
当应用需要调用一些外部程序去处理内容的情况下,就会用到一些执行系统命令的函数。如PHP中的system、exec、shell_exec等,当用户可以控制命令执行函数中的参数时,将可以注入恶意系统命令到正常命令中,造成命令执行攻击。
脚本语言(如PHP)优点是简洁、方便,但也伴随着一些问题,如速度慢、无法接触系统底层,如果我们开发的应用(特别是企业级的一些应用)需要一些除去WEB的特殊功能时,就需要调用一些外部程序。
在PHP中可以调用外部程序的常见函数:
system、exec、shell_exec、passthru、popen、proc_popen。
应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,又没有过滤用户的输入的情况下,就会造成命令执行漏洞。
通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。
PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一,国内著名的Web应用程序Discuz!、DedeCMS等都曾经存在过该类型漏洞。
初级命令执行漏洞
打开DVWA靶场,难度设置low级别
选择Command Injection模块,输入127.0.0.1
由上一步可以推测这里执行了ping命令,再尝试&,&&,|,;等命令这里尝试127.0.0.1 | ls;
可见执行了ls命令,看一下源代码(在Command Injection模块最下面,点击View Source查看源码):
<?php
echo php_uname();
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
$html .= "<pre>{$cmd}</pre>";
}
?>
分析源代码发现没有对用户的输入做任何的防护。
中级命令执行漏洞
难度设置为中级
选择Command Injection,输入127.0.0.1得到如图:
由上一步可以推测这里执行了ping命令,再尝试&,&&,|,;等命令这里尝试127.0.0.1 ; ls:
可见可能是对;符号进行了过滤,我们尝试127.0.0.1 & ls:
分析源代码(在Command Injection模块最下面,点击View Source查看源码),可见对&&和;符号进行了替换
<?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>";
}
?>
高级命令执行漏洞
选择high级别
选择Command Injection,输入127.0.0.1得到如图:
由上一步可以推测这里执行了ping命令,再尝试&,&&,|,;等命令这里尝试127.0.0.1 ; ls
可见可能是对;符号进行了过滤,我们尝试127.0.0.1 & ls
继续尝试,都没有效果,但是当我们执行127.0.0.1 |ls的时候如图:
分析源代码(在Command Injection模块最下面,点击View Source查看源码)
<?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>";
}
?>
可见代码里面过滤了很多符号但是仔细看|,后面跟了一个空格,所以|ls就成了漏网之鱼。