实验目的
- 审计dvwa高难度命令执行漏洞的代码,编写实例说明如下函数的用法
- trim
- str_replace
- array_keys
- stristr
- php_uname
实验环境
- DVWA靶场
代码审计
DVWA代码查看
<?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>";
}
?>
trim
- 在PHP中,
trim()
函数用于移除字符串的首尾空白字符(或其他字符)。 - 函数的语法如下:
string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )
- 其中:
$str
是要处理的字符串$character_mask
是可选参数,用于指定要删除的字符。默认情况下,它会删除空格、制表符、换行符、回车符、空字符和垂直制表符。
- 面是一个简单的例子,说明了
trim()
函数的作用:
<?php
$str = " Hello, World! ";
echo $str."<br />";
$trimmed_str = trim($str);
echo "Original String: '$str'<br />";
echo "Trimmed String: '$trimmed_str'<br />";
echo strlen($str)."<br />";
echo strlen($trimmed_str)."<br />";
?>
- 输出将是:
Hello, World!
Original String: ' Hello, World! '
Trimmed String: 'Hello, World!'
21
13
- 在这个例子中,
trim()
函数移除了字符串$str
首尾的空格,得到了一个没有首尾空格的新字符串$trimmed_str
。但是因为在页面中没有表现出来,通过计算字符串的长度更容易理解。
str_replace
str_replace()
函数用于在字符串中替换指定的子字符串。它的语法如下:
str_replace(search, replace, subject, count);
其中:
- search:需要被替换的子字符串或字符串数组。
- replace:用于替换的字符串或字符串数组。
- subject:要进行替换操作的字符串或字符串数组。
- count:可选参数,用于存储替换的次数。
下面是一个简单的例子,说明了 str_replace() 函数的作用:
<?php
$original_string = "Hello, World!";
$replacement_string = str_replace("World", "PHP", $original_string);
echo "Original String: '$original_string'<br/>";
echo "After Replacement: '$replacement_string'<br />";
?>
输出将是:
Original String: 'Hello, World!'
After Replacement: 'Hello, PHP!'
- 在这个例子中,
str_replace()
函数将字符串$original_string
中的 “World” 替换为 “PHP”,得到了新的字符串$replacement_string
。 - 这个函数对于在字符串中进行简单的文本替换非常有用,比如修改配置文件、替换模板中的变量等。如果要替换多个不同的子字符串,可以将 search 和 replace 参数传递为数组。
array_keys
- array_keys() 函数在 PHP 中用于返回数组中的所有键名。这个函数的语法如下:
- array array_keys ( array $array, mixed $search_value = null, bool $strict = false )
其中: $array
是要获取键名的数组。$search_value
是可选参数,用于指定要搜索的值。如果提供了这个参数,array_keys 将只返回包含指定值的键名。$strict
是可选参数,如果设置为 true,则搜索时会使用严格的比较(即类型和值都要匹配)。
下面是一个简单的例子,说明了 array_keys() 函数的作用:
<?php
$colors = array("red", "green", "blue", "yellow");
$keys = array_keys($colors);
echo "Original Array: ";
print_r($colors);
echo "Keys: ";
print_r($keys);
?>;
输出将是:
Original Array: Array
(
[0] => red
[1] => green
[2] => blue
[3] => yellow
)
Keys: Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
)
- 在这个例子中,
array_keys()
函数返回了数组$colors
中所有的键名。这对于需要获取数组中的键名并进行进一步处理的情况非常有用,例如在遍历关联数组时需要知道键名。
stristr
stristr()
函数在 PHP 中用于执行对字符串的不区分大小写的查找。它会查找字符串中第一次出现的指定子字符串,并返回该子字符串及其余部分。这个函数的语法如下:
string stristr ( string $haystack , mixed $needle [, bool $before_needle = false ] )
- 其中:
$haystack
是要在其中查找的字符串。$needle
是要查找的子字符串。这个参数可以是一个字符串或者是一个数组,如果是数组,stristr()
将对数组中的每个元素执行查找,并返回第一个匹配的元素及其余部分。- - -$before_needle
是可选参数,如果设置为 true,则返回匹配子字符串之前的部分,而不是匹配子字符串及其后的部分。
- 下面是一个简单的例子,说明了 stristr() 函数的作用:
<?php
$string = "Hello, World!";
// 查找不区分大小写的子字符串 "WORLD"
$found = stristr($string, "WORLD");
// 输出结果
echo "Original String: '$string'<br />";
echo "Found String: '$found'<br />";
?>
- 输出将是:
Original String: 'Hello, World!'
Found String: 'World!'
- 在这个例子中,
stristr()
函数查找字符串$string
中的子字符串 “WORLD”(不区分大小写),并返回找到的子字符串及其余部分。
php_uname
- php_uname() 函数用于获取服务器的操作系统信息。这个函数返回一个字符串,包含了有关服务器操作系统的信息。其语法如下:
string php_uname ([ string $mode = "a" ] )
- $mode 是可选参数,用于指定要返回的信息的类型。可以是以下值之一:
- “a”: 返回包含所有信息的字符串(默认值)。
- “s”: 返回操作系统的名称。
- “n”: 返回主机名。
- -“r”: 返回操作系统的版本。
- “v”: 返回操作系统的版本和发行级别。
- “m”: 返回系统的类型(例如,x86_64)。
- 下面是一个简单的例子,说明了
php_uname()
函数的作用:
<?php
// 获取全部信息
$all_info = php_uname();
echo "All Info: $all_info\n";
// 获取操作系统的名称
$os_name = php_uname('s');
echo "OS Name: $os_name\n";
// 获取主机名
$hostname = php_uname('n');
echo "Hostname: $hostname\n";
?>
- 输出可能类似于:
All Info: Linux myserver 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64
OS Name: Linux
Hostname: myserver
- 在这个例子中,首先使用默认模式获取了包含所有信息的字符串,然后分别获取了操作系统的名称和主机名。这对于在程序中动态获取服务器信息,例如在调试或记录日志时,非常有用。
整体代码阅读
<?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>";
}
?>
- 这段代码首先判断是否点击了
Submit
按钮,点击了则代表true,然后对输入的ip参数去掉首位空格以及换行符之类的,定义了$substitutions
数组是黑名单过滤了不想通过的字符,使用str_reolace
函数进行替换,达到黑名单过滤的目的,下面一段if
判断语句是判断操作系统,然后根据不同操作系统输出ping的结果。