米斯特白帽培训讲义(v2)漏洞篇 文件包含

米斯特白帽培训讲义 漏洞篇 文件包含

讲师:gh0stkey

整理:飞龙

协议:CC BY-NC-SA 4.0

原理

文件包含就是将一个文件包含到自己的文件中执行。它可分为本地包含和远程包含,本地包含即包含本地磁盘上的文件,文件名称是相对路径或绝对路径,远程包含即包含互联网上的文件,文件名称是 URL。

本地包含

比如我们有一个test.txt文件,仅仅调用phpinfo来测试:

<?php phpinfo();?>

然后我们在相同目录下放置一个fileinclude.php,如下:

<?php
$file=@$_GET['file'];
if($file){
    echo "<center>File:".$file."<br/>Result:</center>";
    include $file;
}

第一行代码获取 URL 参数file的内容。2 ~ 4 行首先判断$file是否为空,若不为空,输出其内容,并将其作为文件名称包含。

我们将其部署在localhost下,之后访问http://localhost/fileinclude.php?file=test.txt,会看到phpinfo的输出。

我这里之所以用txt文件,就是想说明这个漏洞是无视扩展名的。跟文件上传漏洞不一样,文件上传漏洞中如果我们上传的文件不是.php就执行不了(当然也有一些绕过手段),但是文件包含漏洞中的扩展名是任意的,这里我们上传了.txt,证实有效,那么这个.jpg也是有效的。

要注意,如果被包含的文件里面没有 PHP 标签,那么就当成 HTML 内容如实显示出来。就比如我们放入之前的top100.txt

远程包含

为了演示远程包含,我们需要将 PHP 配置文件中的allow_url_include设置为on,之后重启 PHP。PHP 配置文件的位置可以在phpinfo的输出中寻找,我们搜索ini即可:

我这里是C:\php-5.5.10\php.ini,你那里可能有些差别。我们打开它,搜索allow_url_include,会看到下面这些行,如果是Off把它改成On

; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
; http://php.net/allow-url-include
allow_url_include = On

我们需要将file参数改为http://localhost/text.txt,可以看到相同结果。

技巧

00 截断

有些程序会给被包含内容加一些后缀,比如如果fileinclude.php是这样。

<?php
$file=@$_GET['file'];
if($file){
    $file .= '.php';
    echo "<center>File:".$file."<br/>Result:</center>";
    include $file;
}

它后面加了个.php,也就是说,如果我们传入file=test则是正常的,传入file=test.txt,或变成test.txt.php,从而包含失败。那么我们应该怎么办呢?

如果 PHP 版本小于 5.3,并且magic_quotes_gpc已取消,我们就可以使用%00来截断。我们传入file=test.txt%00,就可以实现包含。

路径遍历

  • ./(或省略):当前目录
  • ../:上级目录
  • /:根目录(Windows 中为当前盘内的根目录)
  • ~/:用户的主目录

例如,在 Linux 下,我们就可以使用file=/etc/passwd来读取系统密码。

这里是一些常见的日志文件位置:

  • apache+Linux日志默认路径
    • /etc/httpd/logs/access.log
    • /var/log/httpd/access.log
  • apache+win2003日志默认路径
    • D:\xampp\apache\logs\access.log
    • D:\xampp\apache\logs\error.log
  • IIS6.0+win2003默认日志文件
    • C:\WINDOWS\system32\Lognames
  • IIS7.0+win2003 默认日志文件
    • %SystemDrive%\inetpub\logs\Lognames
  • nginx 日志文件
    • <安装目录>/logs
    • 如果安装目录为/usr/local/nginx,则为/usr/local/nginx/logs
  • apache+linux 默认配置文件
    • /etc/httpd/conf/httpd.conf
    • /etc/init.d/httpd
  • IIS6.0+win2003 配置文件
    • C:/Windows/system32/inetsrv/metabase.xml
  • IIS7.0+WIN 配置文件
    • C:\Windows\System32\inetsrv\config\applicationHost.config

PHP 伪协议

允许远程包含的情况下,我们可以使用php://伪协议,比如php://filter/resource=test.txt可以读取相同文件。

我们还可以加一个过滤器让它显示为 BASE64 编码格式,php://filter/read=convert.base64-encode/resource=test.txt。如果我们要获取的文件里面有不可打印的字符,或者我们想要获取代码的内容,可以用这种方式来获取,之后解码即可。

php://input可以读取原始的 HTTP 正文内容。如果我们将file设置为php://input,并且在 HTTP 正文中传入 PHP 代码,例如<?php phpinfo();?>,即可执行代码。

Data URI

Data URI 的格式是data://text/plain;base64,<base64>,同样需要远程包含。我们首先把一句话用 base64 编码,得到PD9waHAgcGhwaW5mbygpOz8+,然后将file设置为data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b(注意URL编码),即可执行代码。

如何挖掘

首先对 URL 进行分析,看看是否和文件相关,比如www.test.com/xxx.php?file=yyy。带有文件相关的敏感名称都可以进行挖掘。

利用

当我们发现了本地包含漏洞时,首先寻找上传点,比如用户头像上传功能。然后我们可以构造一个纯文本文件,内容为<?php phpinfo();?>,并将其命名为xxx.jpg

之后我们就可以把xxx.jpg上传上去,并通过应用得到它的位置,假设是/upload/xxx.jpg,然后我们就可以把file参数的值改为它。以前面的代码为例,URL 是http://localhost/fileinclude.php?file=/upload/xxx.jpg

如果我们把xxx.jpg的内容改为菜刀的一句话,那就可以用菜刀连接。

再说一下远程包含,远程包含的条件比较苛刻,目标网站需要把allow_url_open给打开。所以有本地包含不一定有远程包含,有远程包含一定就有本地包含。但是,远程包含的利用相对简单,只要将代码上传到自己博客,或者任何能通过 URL 访问到的地方就可以了。后续步骤是一样的。

附录

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
手写 Picker 可以通过以下步骤实现: 1. 在 WXML 文件中创建一个 Picker 组件,并设置它的样式和属性,如选择器的宽度、高度、颜色等。 2. 在 JS 文件中定义一个数组,用于存储 Picker 组件中的选项值。 3. 在 JS 文件中实现 Picker 组件的初始化方法,将数组中的选项值渲染到 Picker 组件中。 4. 在 JS 文件中实现 Picker 组件的选择事件,当用户选择某个选项时,获取该选项的值并进行相应的操作(如更新页面数据)。 以下是一个简单的手写 Picker 的示例代码: WXML 文件: ``` <view class="picker"> <picker mode="selector" bindchange="onChange" value="{{selectedIndex}}"> <view class="picker-item">{{options[0]}}</view> <view class="picker-item">{{options[1]}}</view> <view class="picker-item">{{options[2]}}</view> </picker> </view> ``` JS 文件: ``` Page({ data: { options: ['选项1', '选项2', '选项3'], selectedIndex: 0 }, onLoad: function () { this.initPicker(); }, initPicker: function () { var that = this; var options = that.data.options; var selectedIndex = that.data.selectedIndex; that.setData({ options: options, selectedIndex: selectedIndex }); }, onChange: function (event) { var that = this; var selectedIndex = event.detail.value; that.setData({ selectedIndex: selectedIndex }); // 在这里可以进行相应的操作,如更新页面数据等 } }) ``` 在这个示例中,我们创建了一个 Picker 组件,并定义了一个包含三个选项值的数组。在初始化方法中,我们将数组中的选项值渲染到 Picker 组件中。在选择事件中,我们获取用户选择的选项值,并进行相应的操作,例如更新页面数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值