dvwa命令注入漏洞代码审计(个人学习笔记)
LOW
源码:
?php
//进行if判断,通过isset函数检查设置的变量是否非空, 查看是否通过post请求接收了Sumbit的参数
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
//获取输入的数据【ip】并赋值给target变量
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
//进行if判断,通过stristr函数搜索'Windows NT'在php_uname( 's' )'s'操作系统名称,并用来判断具体是什么操作系统
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows 如果是windows系统 执行ping命令并拼接target变量的值
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix 如果是linux系统 执行ping命令且只ping4次并拼接target变量的值
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
// 输出命令执行的结果
echo "<pre>{$cmd}</pre>";
}
?>
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>";
}
?>
medium难度主要就是多了一个黑名单,过滤掉了&&和;
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>";
}
?>
与medium难度相比黑名单过滤的特殊字符明显的增多了
medium难度中黑名单的编写以及各种函数的作用
黑名单的编写
//首先定义一个数组,将'key'的'value'替换为空,变量名substitutions 里氏替换原则
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
// 通过str_replace函数将第一个数组array_keys( $substitutions )中的'value'匹配$substitutions数组中的'key',如果匹配成功,则将array_keys数组中的'key'替换为$substitutions的'value',最终将替换的值存储到新的变量里面。
// array_keys将substitutions变量定义的数组中所有的'key'以一个新数组的形式返回出来
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
总结:首先定义一个数组,存储想要过滤的关键字到数组的’key’,使用array_keys函数将定义的数组中所有的’key’取出来,定义为一个新的数组,紧接着使用 str_replace函数将想要过滤的关键字替换为空。
函数的作用
- trim -----去除字符串首尾处的空白字符(或者其他字符)
例如
<?php
$string = " Hello World! ";
echo trim($string);
?>
//会去除 Hello World! 两侧的空格并输出Hello World!
- str_replace ---- 用来在字符串中查找并替换指定的字符或字符串
<?php
$string = "Hello World!";
echo str_replace(" ", "*", $string);
?>
//输出为Hello*World! 将空格替换为*并输出。
- array_keys ---- 返回数组中部分的或所有的键名
例如
<?php
$array = array("apple"=>"red", "banana"=>"yellow", "cherry"=>"red");
print_r(array_keys($array));
?>
//上述代码会输出Array ( [0] => apple [1] => banana [2] => cherry ) 将所有的'key'取出并返回一个新的数组
- stristr ---- 在字符串中查找指定的子串,并返回包含该子串的剩余部分,并且是不区分大小写的
例如
<?php
$string = "Hello abcdefg";
echo stristr($string, "abc");
?>
上述代码会返回abcdefg(包含该子串的子串)
- php_uname-----返回运行PHP的系统的信息,如操作系统名称、主机名等
例如
<?php
echo php_uname('s');
?>
//会输出当前操作系统的名称
impossible
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
//检查用户提交的token是否有效,如果无效,则跳转回index.php页面。$_SESSION是一个特殊的PHP超级全局数组,它用于存储和跟踪用户会话中的数据,可以跨多个页面使用
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
//使用stripslashes函数移除反斜杠,
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
//使用is_numeric函数检查输入是否为数字,将IP地址拆分为四个八位字节,检查每个八位字节是否都是数字,并且总共有四个八位字节。如果满足这些条件,则重新组合IP地址。
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];
//判断当前的操作系统是Windows还是linux。如果是Windows,执行ping命令;如果是linux,执行带有-c选项的ping命令,该选项指定了发送ICMP Echo请求的次数
// 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
//生成随机token,用于防止跨站请求伪造(Cross-site Request Forgery, CSRF)攻击
generateSessionToken();
?>
函数的作用
-
stripslashes() ----- 删除反斜杠返回一个去除转义反斜线后的字符串(’ 转换为 ’ 等等)。双反斜线(\)被转换为单个反斜线(\)。
-
explode() ----- 使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
-
is_numeric ----- 用于检测变量是否为数字或数字字符串。
-
sizeof() ----- count() 的别名 返回数组中元素的数目,用于统计数组或对象中的元素数量