代码审计php文件包含,php代码审计之文件包含

文件包含

文件包含分为本地文件包含(Local File Inclusion,简LFI)和远程文件包含(Remote File Inclusion,简RFI)。

在php中常见的文件包含函数有:

当php包含一个文件时不会在意文件的类型,都会把文件当做php文件来解析。(file_get_contents()除外)。

本地文件包含

测试代码:

存在本地文件包含漏洞。

%00截断

条件:

playload:

这时就是本地任意文件包含。

可以读取服务器敏感信息。

路径长度截断和点号截断

测试代码:

Linux 需要文件名长于 4096,Windows 需要长于 256。

在windows下测试是240个点和240个斜杠加点都能截断。

在linux上只有2038个/.才能截断。(至少2038个)

php版本5.3之后被修复。

远程文件包含

远程文件包含需要设置

测试代码:

41873ded5029a92a9016061a50cba47d.png

问号截断

测试代码:

php伪协议

file:// — 访问本地文件系统

file:///文件绝对路径和文件名

php://

php:// — 访问各个输入/输出流(I/O streams)

条件:

php://input

php://input 是个可以访问请求的原始数据的只读流,enctype=”multipart/form-data” 的时候 php://input 是无效的。POST请求的情况下,php://input可以获取到post的数据。

php://output

php://output 是一个只写的数据流, 允许你以 print 和 echo一样的方式 写入到输出缓冲区。

php://filter

该协议语法为:php://filter:/=参数功能resource=数据来源(必须)

read=读取

write=写入

常用功能:读取源码:

测试代码:

2780620a563b0c5f8b51242ebfa2b83b.png写入webshell

测试代码:

这里需要理解一下php base64解码的原理:

base64编码中只包含64个可打印字符,而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码.

一般步骤:

起初$content中一共有十四个字符。

我们传入的字符要与其进行拼接。

这里我们可以利用php://filter/write=convert.base64-decode 来首先对其解码。在解码的过程中,字符、空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“c”一共8个字符。这样,”phpexita”被正常解码,而后面我们传入的webshell的base64内容也被正常解码。而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>没有了。成功写入可执行的webshell。

d466245f3b0ecb70d9fb94e3c7512f08.png

方法二:

<?php exit; ?>实际上是一个XML标签,既然是XML标签,我们就可以利用strip_tags函数去除它,而php://filter刚好是支持这个方法。

测试代码:

da73a7b2502296fd0faad973402adbea.png

我们最终的目的是写入一个webshell,而写入的webshell也是php代码,如果使用strip_tags同样会被去除。

php://filter允许使用多个过滤器,我们可以先将webshell用base64编码。在调用完成strip_tags后再进行base64-decode。“死亡exit”在第一步被去除,而webshell在第二步被还原。

playload:

POST传入:

txt=PD9waHAgcGhwaW5mbygpOyA/Pg==&filename=php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php

396b2fc93a6190057408ce8c38a718be.png

这个方法的条件就是不开启短标签。

其他格式:

zlib://

无版本要求

测试代码:

phar://

phar:// — PHP 归档

phar:// 数据流包装器自 PHP 5.3.0 起开始有效

条件:

压缩包必须是zip协议压缩的文件

测试代码同上

data://

data:// — 数据(RFC 2397)

条件:

测试代码同上

本地文件包含之姿势

日志文件

apache日志

测试系统:

centos:

日志路径:/var/log/httpd/access_log或/etc/httpd/logs/access_log

测试系统:

ubuntu16.04

PHP 5.6.40+ Apache/2.4.18

日志路径:/var/log/apache2/access.log

日志中的一条信息:

信息:访问者ip

请求的时间

请求方式以及url

状态码:200

发送给客户端的总字节数

客户端浏览器的信息

我们知道文件包含时,不管文件是什么类型都当作php来解析。

所以我们可以把webshell藏在请求中,然后就写入日志文件。我们再包含日志文件,就可以获得webshell。

我们试试shell藏在url中:

访问:

查看日志:

发现 :shell被url编码了。

尝试包含日志文件:

8e346f6f9df64d1aa58dfc9c93991c54.png

发现解析失败。

这时我们可以尝试把shell藏在User-Agent里:

fa60515fa897155babedfb73f4837327.png

查看日志:

发现这时成功写入shell。

我们再次包含日志文件就getshell了。

436c27ab2f62687c59aa4a7df2ab440b.png

ssh 日志

利用条件

需要知道ssh-log的位置,且可读。默认情况下为 /var/log/auth.log

我们可以用ssh连接来向ssh日志中写入webshell:

查看日志文件:

167b62e5306c3a44ed34cd6c9bea94b7.png

成功写入shell。包含它就getshell了。

b7f25a19ed27fa67a35ef1b1637ee92c.png

session 文件

利用条件:session文件路径已知,且其中内容部分可控

php的session文件的保存路径可以在phpinfo的session.save_path看到

ef5a2b8ec4cb5de79ade97271ed56346.png

session 存储位置:

/var/lib/php/session

测试代码:

session的文件名是“sess_”+当前PHPSESSID

8f8dad143335f68d2b671c5624defb73.png

故session文件路径为/var/lib/php/session/sess_2n3gliufi6ibj1b5ddovr6eub4

所以此时包含:

绕过姿势

在指定前缀名后,我们可以通过../来跳转目录。

编码绕过

服务器端常常会对于../等做一些过滤,可以用一些编码来进行绕过

问号绕过,#号绕过,%00截断,路径截断(./),长度截断(.)和协议。

常见敏感信息文件路径

windows

linux:

防御措施在很多场景中都需要去包含web目录之外的文件,如果php配置了open_basedir,则会包含失败

做好文件的权限管理

对危险字符进行过滤等等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值