Level 07 —— Perl脚本可执行任意文件漏洞

详情:

flag07 用户正在编写他们的第一个 Perl 程序,该程序允许他们 ping 主机,以检查是否可以从 Web 服务器访问它们。要执行此级别的操作,请以 level07 帐户和密码登录。此级别的文件位于 /home/flag07。

源代码如下:

#!/usr/bin/perl

use CGI qw{param};

print "Content-type: text/html\n\n";

sub ping {
$host = $_[0];

print("<html><head><title>Ping results</title></head><body><pre>");

@output = `ping -c 3 $host 2>&1`;
foreach $line (@output) { print "$line"; }

print("</pre></body></html>");

}

# check if Host set. if not, display normal page, etc

ping(param("Host"));

Solution:

在/home/flag07这个目录中,有一个index.cgi和thttpd.conf,既然是一个cgi程序,我们需要客户端访问,根据thttpd.conf配置文件中的内容,得知端口号是7007。

index.cgi 是一个 CGI(Common Gateway Interface)脚本文件,通常用于 Web 服务器中,用来处理动态网页请求。


🧩 详细解释:

✅ 什么是 .cgi

  • .cgi 是一种常见的脚本文件扩展名,表示这个文件是通过 CGI 机制运行的。
  • CGI 是 Web 服务器和外部程序(脚本)之间的一个接口协议。
  • 它允许 Web 服务器调用程序(比如 Python、Perl、Bash 脚本)来生成动态内容返回给浏览器。

这关考验的是分析这个index.cgi,我们先看下它的源码:

#!/usr/bin/perl

use CGI qw{param};

print "Content-type: text/html\n\n";

sub ping {
$host = $_[0];

print("<html><head><title>Ping results</title></head><body><pre>");

@output = `ping -c 3 $host 2>&1`;
foreach $line (@output) { print "$line"; }

print("</pre></body></html>");

}

# check if Host set. if not, display normal page, etc

ping(param("Host"));

🧠 逐行详解


#!/usr/bin/perl

  • 指定该脚本使用 Perl 解释器执行。

use CGI qw{param};

  • 引入 Perl 的 CGI 模块,用于处理 Web 表单参数。

  • param("Host") 会获取用户通过 GET 或 POST 传入的 Host 参数值。


print "Content-type: text/html\n\n";

  • CGI 的标准输出格式,表示返回的是 HTML 网页内容。

  • 必须写在输出 HTML 内容前,否则浏览器会报错。


sub ping { ... }

  • 定义一个名为 ping 的子程序,用于执行 ping 操作。

其中:

$host = $_[0];
  • 接收传入的第一个参数,赋值给 $host

@output = `ping -c 3 $host 2>&1`;

  • 执行系统命令:ping -c 3 $host,即 ping 指定主机 3 次。

  • 用反引号执行命令并捕获输出(标准输出和错误合并到一起)。

  • 2>&1 是将标准错误重定向到标准输出。


foreach $line (@output) { print "$line"; }

  • 遍历 ping 命令的每一行输出,逐行打印到网页中。

ping(param("Host"));

  • 调用 ping() 函数,并传入 Host 参数的值。

  • 比如访问:

    http://target.com/index.cgi?Host=8.8.8.8

    就会执行:

    ping -c 3 8.8.8.8

总结一下,就是这段代码的功能是调用外部的ping命令去ping指定的ip地址,ip地址通过参数$host=$_[0]获得。然后加了-c参数——指定了发送数据包的数量为3。最后,程序会把ping的结果返回到客户端的浏览器中。

我们先配置好虚拟机的地址,保障实体机的系统可以正常访问,确保能互相ping通(我这里使用的都是桥接模式)。在Kali中访问http://192.168.3.151:7007/index.cgi可以访问如下:(192.168.3.151是Nebula的地址)

image-20250605165525529

然后提交URL:http://192.168.3.151:7007/index.cgi?Host=127.0.0.1可以得到:

image-20250605173943563

这段Perl脚本的漏洞出现在以下代码上:

@output = `ping -c 3 $host 2>&1`;

这句出现了可执行任意文件漏洞。在Perl中,“`”符号之间的内容是调用的外部命令。

然后在Kali浏览器中输入http://192.168.3.151:7007/index.cgi?Host=127.0.0.1;getflag即可得到回显结果

image-20250605173833294

进入脚本后执行的是ping -c 3 127.0.0.1 ;getflag 2>&1这其实执行的是两条指令ping -c 3 127.0.0.1getflag。在我实验的过程中,我发现如果执行太多次HTTP请求访问会导致访问链接被拒绝。