因为Perl File Upload 这里上传文件会原样输出,所以大佬猜测源码是这样的:
1 | use strict; |
这里$cgi
接受上传的 file,然后复制给$file
,再把这个文件内容逐行读出并显示在页面上。
<$file>
被 Perl 解释成 <ARGV>
,<ARGV>
是特殊的,这是漏洞的来源。
如果我们这里上传的不是文件,而是一个 叫 "ARGV"
的纯文本字符串,那么$file
就是 ARGV,<$file>
就是<ARGV>
。
Perl 中<ARGV>
可以类比于 Python 里的sys.argv
,也就是说当你在命令行里输入perl demo.pl /etc/passwd
的时候/etc/passwd
就会填补在<ARGV>
。
虽然我们题目里没有命令行,但是 Perl
里的CGI
模块很聪明,如果你访问的是:upload.pl?file=/etc/passwd
,那么 CGI 模块会自动把这个参数放进 @ARGV
里。
这正好被 <ARGV>
使用,所以你传进去的参数 /etc/passwd
就会被当作文件名打开。
?
这里我看网上 wp 说的是,param
是可以接受多个值的,只有第一个文件会被放入到下面的file变量中。所以我们抓包上传请求,在我们上传的文件前面添加一个 ARGV,在命令行添加系统命令就可以实现命令执行。
这里如果把下面的文件删掉,读不出来。也就是说我们无法只上传一个内容是字符串ARGV
的file
来读取。
有可能是上传的第二个文件是文件,保证是服务器会当成文件来读,我们单独上传 ARGV
时识别的是字符串。