打开页面,看见三个可点击链接:
hello.pl:
forms.pl,输入Name和Age后会直接输出在页面上,感觉没什么突破点:
file.pl,先上传一个test.txt文件,内容是123,发现文件内容直接输出在页面了,猜想后台源码可能用了parm()函数:
param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的接收 变量中。 如果我们传入一个ARGV的文件,那么Perl会将传入的参数作为文件名读出来。 对正常的上传文件进行修改,可以达到读取任意文件的目的。
用burpsuite抓包,上传一个ARGV文件,构造payload:
-----------------------------2863305740649526554427396279 Content-Disposition: form-data; name="file"; Content-Type: application/octet-stream ARGV
根据三个链接的url里可以知道,每个网页都是在/cgi-bin目录下,所以根据做题经验,可以猜测file.pl是否在/var/www/cgi-bin/目录下,测试成功并且得到后台关键代码,并且印证了之前对param()函数使用的猜测:
然后通过管道的方式,执行任意命令,然后将其输出结果用管道传输到读入流中,这样就可以保证获取到flag文件的位置了。这里用到了${IFS}来作命令分割,原理是会将结果变成bash -c "ls/"的等价形式。
“|”是管道命令操作符,简称管道符。利用Linux所提供的管道符“|”将两个命令隔 开,管道符左边命令的输出就会作为管道符右边命令的输入。连续使用管道意味着第 一个命令的输出会作为 第二个命令的输入,第二个命令的输出又会作为第三个命令 的输入,依此类推。
构造读取payload:
/cgi-bin/file.pl?/bin/bash%20-c%20ls${IFS}/|
找到flag的位置,那我们就直接读取就可以了:
还有另外一种简单易懂的方法,附上链接:Natas32
URL加入命令ls -l . |查看Webroot目录下的文件,构造payload:
/cgi-bin/file.pl?ls%20-l%20.%20|
发现file.pl,但没有flag文件,继续寻找:
ls%20-l%20/%20|
找到flag文件,直接读取就可以了
总结:
perl文件遇到上传可配合ARGV文件使用造成任意文件读取或者任意命令执行(管道符)



