面试问题
1,任意文件读取,到底读什么文件,有什么危害

权限是www
只能读第一个,读这个没用,密码在/etc/shadow中
其它没有权限
my.cnf mysql密码看不了
但是可以看见日志文件的目录
sql注入时,你有注入点,可以支持堆叠,并且是root权限
就可以打开日志,修改位置
就可以通过修改成php文件
来实现webshell

.env重点


准备阶段
伪协议
一.【file://协议】
PHP.ini:
file:// 协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on
file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响

file:// [文件的绝对路径和文件名]
http://127.0.0.1/cmd.php?file=file://D:/soft/phpStudy/WWW/phpcode.txt
二.【php://协议】
条件:
不需要开启allow_url_fopen,仅php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include。
php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。
php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
PHP.ini:
php://filter在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on

测试现象:
http://127.0.0.1/cmd.php?file=php://filter/read=convert.base64-encode/resource=./cmd.php

php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。

PHP.ini:
allow_url_fopen :off/on
allow_url_include:on

测试现象:
http://127.0.0.1/cmd.php?file=php://input
POST DATA\] \ 也可以POST如下内容生成一句话: \');?\>  #### **三.【zip://, bzip2://, zlib://协议】** **自动解压压缩包 然后把压缩包的文件放在include 进行文件包含** **PHP.ini:** zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用; allow_url_fopen :off/on allow_url_include:off/on zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。 参考自:[PHP: zlib:// - Manual](http://php.net/manual/zh/wrappers.compression.php "PHP: zlib:// - Manual ")  **1.【zip://协议】** **使用方法:** zip://archive.zip#dir/file.txt zip:// \[压缩文件绝对路径\]#\[压缩文件内的子文件名
测试现象:
http://127.0.0.1/cmd.php?file=zip://D:/soft/phpStudy/WWW/file.jpg%23phpcode.txt
先将要执行的PHP代码写好文件名为phpcode.txt,将phpcode.txt进行zip压缩,压缩文件名为file.zip,如果可以上传zip文件便直接上传,若不能便将file.zip重命名为file.jpg后在上传,其他几种压缩格式也可以这样操作。
由于#在get请求中会将后面的参数忽略所以使用get请求时候应进行url编码为%23,且此处经过测试相对路径是不可行,所以只能用绝对路径。

这个压缩后php特征明显,可以

绕过waf
2.【bzip2://协议】
使用方法:
compress.bzip2://file.bz2
测试现象:
http://127.0.0.1/cmd.php?file=compress.bzip2://D:/soft/phpStudy/WWW/file.jpg
or
http://127.0.0.1/cmd.php?file=compress.bzip2://./file.jpg

3.【zlib://协议】
使用方法:
compress.zlib://file.gz
测试现象:
http://127.0.0.1/cmd.php?file=compress.zlib://D:/soft/phpStudy/WWW/file.jpg
or
http://127.0.0.1/cmd.php?file=compress.zlib://./file.jpg

四.【data://协议】
经过测试官方文档上存在一处问题,经过测试PHP版本5.2,5.3,5.5,7.0;data:// 协议是是受限于allow_url_fopen的,官方文档上给出的是NO,所以要使用data://协议需要满足双on条件
PHP.ini:
data://协议必须双在on才能正常使用;
allow_url_fopen :on
allow_url_include:on
参考自:PHP: data:// - Manual, 官方文档上allow_url_fopen应为yes。

测试现象:
http://127.0.0.1/cmd.php?file=data://text/plain,<?php phpinfo()?>
or
http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
也可以:
http://127.0.0.1/cmd.php?file=data:text/plain,<?php phpinfo()?>
or
http://127.0.0.1/cmd.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

五. 常规小结:
PHP封装协议在CTF蛮常见的,是经常会遇到的出题点,如下便是对本篇涉及的封装协议进行的总结,期待小伙伴的交流和补充。

文件包含的函数
php代码不会展现在页面

包含APACHE日志文件
你必须要知道日志物理路径
WEB服务器一般会将用户的访问记录保存在访问日志中。那么我们可以根据日志记录的内容,精心构造请求,把PHP代码插入到日志文件中,通过文件包含漏洞来执行日志中的PHP代码。 Apache运行后一般默认会生成两个日志文件,Windos下是access.log(访问日志)和error.log(错误日志),Linux下是access_log和error_log,访问日志文件记录了客户端的每次请求和服务器响应的相关信息。如果访问一个不存在的资源时,如XXXX<?php phpinfo(); ?>,则会记录在日志中,但是代码中的敏感字符会被浏览器转码,我们可以通过burpsuit绕过编码,就可以把<?php phpinfo(); ?> 写入apache的日志文件,然后可以通过包含日志文件来执行此代码,但前提是你得知道apache日志文件的存储路径,所以为了安全期间,安装apache时尽量不要使用默认路径。
(但是日志可能太多,会导致)服务器down)
日志分隔
一般大公司都会,按时间分隔,可能凌晨12点
参考文章:
1.包含日志文件getshell 2.一道包含日志文件的CTF题
包含SESSION文件
可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。
利用条件:
-
找到Session内的可控变量
-
Session文件可读写,并且知道存储路径
php的session文件的保存路径可以在phpinfo的session.save_path看到。 session常见存储路径:
-
/var/lib/php/sess_PHPSESSID
-
/var/lib/php/sess_PHPSESSID
-
/tmp/sess_PHPSESSID
-
/tmp/sessions/sess_PHPSESSID
-
session文件格式: sess_[phpsessid] ,而 phpsessid 在发送的请求的 cookie 字段中可以看到。
参考文章:一道SESSION包含的CTF题
包含/PROC/SELF/ENVIRON
proc/self/environ中会保存user-agent头,如果在user-agent中插入php代码,则php代码会被写入到environ中,之后再包含它,即可。
**利用条件:**
-
php以cgi方式运行,这样environ才会保持UA头。
-
environ文件存储位置已知,且environ文件可读。
参考文章:[proc / self / environ Injection
包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用c:\winsdows\temp目录。在临时文件被删除之前,利用竞争即可包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的随机函数有缺陷,而window下只有65535中不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。这个方法可以参考LFI With PHPInfo Assistance
类似利用临时文件的存在,竞争时间去包含的,可以看看这道CTF题:XMAN夏令营-2017-babyweb-writeup
其他包含姿势
-
包含SMTP(日志)
-
包含xss
文件包含漏洞的绕过方法
指定前缀绕过
一、目录遍历
使用 ../../ 来返回上一目录,被称为目录遍历(Path Traversal)。例如 ?file=../../phpinfo/phpinfo.php 测试代码如下:
<?php error_reporting(0); $file = $_GET["file"]; //前缀 include "/var/www/html/".$file;
<span class="token function">highlight_file</span><span class="token punctuation">(</span><span class="token constant">__FILE__</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
现在在/var/log目录下有文件flag.txt,则利用.../可以进行目录遍历,比如我们尝试访问:
include.php?file=../../log/flag.txt
则服务器端实际拼接出来的路径为:/var/www/html/../../log/test.txt,即 /var/log/flag.txt,从而包含成功。
二、编码绕过
服务器端常常会对于../等做一些过滤,可以用一些编码来进行绕过。 1.利用url编码
-
../
-
%2e%2e%2f
-
..%2f
-
%2e%2e/
-
-
..\
-
%2e%2e%5c
-
..%5c
-
%2e%2e\
-
2.二次编码
-
../
- %252e%252e%252f
-
..\
- %252e%252e%255c
3.容器/服务器的编码方式
-
../
-
..%c0%af
-
%c0%ae%c0%ae/
- 注:java中会把"%c0%ae"解析为"\uC0AE",最后转义为ASCCII字符的"."(点) Apache Tomcat Directory Traversal
-
-
..\
- ..%c1%9c
指定后缀绕过
后缀绕过测试代码如下,下述各后缀绕过方法均使用此代码:
<?php error_reporting(0); $file = $_GET["file"]; //后缀 include $file.".txt";
<span class="token function">highlight_file</span><span class="token punctuation">(</span><span class="token constant">__FILE__</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
一、利用URL
在远程文件包含漏洞(RFI)中,可以利用query或fragment来绕过后缀限制。 可参考此文章:URI's fragment
完整url格式:
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
11
query(?)
-
访问参数\] `?file=http://localhost:8081/phpinfo.php?`
Example: (设在根目录下有flag2.txt文件) fragment(#)
-
访问参数\] `?file=http://localhost:8081/phpinfo.php%23`
Example:(设在根目录下有flag2.txt文件)
二、利用协议
利用zip://和phar://,由于整个压缩包都是我们的可控参数,那么只需要知道他们的后缀,便可以自己构建。
zip://
-
访问参数\] `?file=zip://D:\zip.jpg%23phpinfo`
phar://
-
访问参数\] `?file=phar://zip.zip/phpinfo`
Example: (我的环境根目录中有php.zip压缩包,内含phpinfo.txt,其中包含代码<?php phpinfo();?>)) 所以分别构造payload为:
?file=zip://D:\PHPWAMP_IN3\wwwroot\php.zip%23phpinfo
?file=phar://../../php.zip/phpinfo
三、长度截断
利用条件:
- php版本 < php 5.2.8
原理:
-
Windows下目录最大长度为256字节,超出的部分会被丢弃
-
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
利用方法:
-
只需要不断的重复 ./(Windows系统下也可以直接用 . 截断)
?file=./././。。。省略。。。././shell.php 11
则指定的后缀.txt会在达到最大值后会被直接丢弃掉
四、%00截断
利用条件:
-
magic_quotes_gpc = Off
-
php版本 < php 5.3.4
利用方法:
-
直接在文件名的最后加上%00来截断指定的后缀名
?file=shell.php%00
注:现在用到%00阶段的情况已经不多了
文件包含漏洞防御
-
allow_url_include和allow_url_fopen最小权限化
-
设置open_basedir(open_basedir 将php所能打开的文件限制在指定的目录树中)
-
*白名单限制包含文件,或者严格过滤 . / *