攻防世界Web题wp解析(难度6)

文章讲述了如何利用Perl中的param()函数和ARGV特殊变量绕过限制,实现上传文件时读取服务器上任意文件的漏洞。通过修改上传请求,删除filename参数并替换为ARGV,得以执行远程命令并获取flag。
摘要由CSDN通过智能技术生成
  1. got-id-200

打开环境

 

进入场景后有3个链接,点进去都是.pl文件,.pl文件都是用perl编写的网页文件

尝试后发现,Files链接可以上传文件并把文件内容打印出来

 

想后台应该用了param()函数。

param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的接收变量中。如果我们传入一个ARGV的文件,那么Perl会将传入的参数作为文件名读出来。对正常的上传文件进行修改,可以达到读取任意文件的目的。

这里附上网上大佬们猜测的后台代码:

use strict;

use warnings;

use CGI;

my $cgi= CGI->new;

if ( $cgi->upload( 'file' ) ) {

    my $file= $cgi->param( 'file' );

     while ( <$file> ) { print "$_"; }

}

我们利用bp抓包

然后增加一个ARGV内容

ARGV内容如下:

-----------------------------203714850424912882901994417149

Content-Disposition: form-data; name="file";

Content-Type:image/jpeg

ARGV

这里注意修改一些东西        

 

  1. 盲猜,flag在根目录下

 

2.正常流程做法

直接先读取file.pl文件,盲猜在/var/www/cgi-bin/file.pl试试

 

发现确实使用了param()函数,然后我们利用bash来进行读取当前目录下的文件。

Payload:?/bin/bash%20-c%20ls${IFS}/|

 

发现flag 我们读取flag就行

Payload:?cat%20/flag%20|

 

总结:

param()

param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的接收变量中。如果我们传入一个ARGV的文件,那么Perl会将传入的参数作为文件名读出来。对正常的上传文件进行修改,可以达到读取任意文件的目的:

漏洞分析

这里大佬告诉我们要利用@ARGV这个全局变量

首先要了解Perl中的ARGV全局特殊文件句柄

ARGV:遍历数组变量@ARGV中所有文件名的特殊文件句柄

@ARGV:是个全局数组特殊变量,传给脚本的命令行参数列表

Perl 会将 perl 命令行参数列表放入到数组 @ARGV 中,而默认情况下,这些命令行参数是 Perl 的数据输入源,也就是 说Perl 会以依次将他们当作文件进行读取。这里可以参考C语言的argv{}数组,但不同的是,

Perl语言的@ARGV中的第一个变量就是参数,而不是文件名。

Param() 函数会返回一个列表,但只有第一个文件会被放到变量中。

增加新的上传项,并删除filename,重大漏洞来了:

删除filename后, $file的值(也就是文件名)变为了上传的内容,而输出的文件内容为空

通俗理解就是,新加入的文件内容替换了filename参数,传给了$file变量,<file>句柄中打开文件内容为空

那如果我们利用@ARGV,将$file替换为@ARGV,其句柄就是,就是命令行的参数呀,如果给的参数是文件名,就可以输出第一个文件名的所有内容。

这里我们利用以上信息构造,加入新的文件列表,删除filename,文件内容写入ARGV

那么后端执行,就会把$file的值换为ARGV,也就成了上述test.pl的内容,会把从命令行里读取到的参数,当作文件路径找到并输出。

那么如何传入命令行参数呢?其实直接在url给出参数就相当于命令行传参

那么,通过ARGV和url的参数就可以达到读取服务器上任意文件的目的

构造远程执行代码

这里空格需要用url编码转义,否则不符合http头部格式,不能随便加空格的

Linux中,/bin/bash 是bash解释器,这句话当作文件名时,首先会去寻找/bin/bash并且输出,那就是执行了解释器的功能

bash -c 的语法是,后面跟的第一个参数会当作命令来被bash解析,第二,第三个参数被认为是bash的参数,而不是第一个参数(命令)的参数

举个例子:

bash -c ls /

会执行ls命令,列出当前目录,/会被当做bash的参数,没有意义,会找不到

如果我们想要列出根目录需要 “ls /”时,需要加入$IFS

IFS是linux的特殊变量,默认值是space空格, $是取变量值,$IFS就代表空格

就可以执行“ls /“的命令了

若只有 /bin/bash%20-c%20ls$IFS/ 命令会发现没有返回信息

因为,/etc/passwd本身就是文件,后端代码找到并输出返回在html标签中

而/bin/bash 一旦被访问输出,就是bash运行环境,整个语句的输出结果在shell的缓冲区里,也就是后台服务器才能看到,并不会输出到html标签中。在linux里我们只需要管道操作就可以指定结果的存放位置了。

注:经测试,${IFS}和/bin/bash联用时,不代表空格

Tips:Perl open()函数会默认打开一个管道!

这里利用Perl open()函数打开的管道,进行劫持,通过“|“操作符,把内容引入open()函数已经打开的管道中,就可以输出到html标签中啦!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W3nd4L0v3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值