前后端结合的 WAF
前言
之前介绍了一些前后端结合的中间人攻击方案。由于 Web 程序的特殊性,前端脚本的参与能大幅弥补后端的不足,从而达到传统难以实现的效果。
攻防本为一体,既然能用于攻击,类似的思路同样也可用于防御。如果将前端技术结合到传统的 WAF 中,又能有如何的改进?
假人的威胁
简单易用,是 Web 服务最大的优势。然而,这也是个致命的弱点。
这种格式简单、标准一致的特征,使得攻击者能利用现有的安全工具,进行大规模、通用化的探测和入侵。甚至无需了解其中的原理。
试想一下,如果某个网站使用私有的二进制协议,那么即使存在漏洞,也得先考虑通信问题。若是寄托于现成的安全工具,那就更举步维艰了。然而现实中是不存在的。通用性和低成本,始终是首要因素。
要模仿这种简单的协议易如反掌。于是,各种需要重复劳动的地方,都能见到假人的身影。对于需要反复测试的安全领域,更是必不可缺。
传统 WAF
传统 WAF 大多关注于信息监控,记录拦截各种异常的输入输出。对于用户的真假鉴别,并非是其重点。
然而现实中,大多异常的请求,都不是正常用户发起的。有谁会那么闲,把各种帐号一次又一次输入测试撞库?或者反反复复的在浏览器里尝试内网探测?没有工具的协助,安全检测将是无比的折磨。
遗憾的是,WAF 很难从表面上识别用户的真假,只能对其一视同仁。通过之后更详细的规则进行综合分析,才能做出判定。因此,这样的决策似乎有些『有理无据』。
有理。例如正常用户每秒只有几个请求,但攻击者开了漏洞扫描工具,短时间内产生了上百请求,这显然不符合常理。
无据。虽然判定一个用户并不难,但要拿出确凿的证据,却不容易。
这种模糊的规则难免会有一些的误差。若是内网里有人对网站进行入侵探测,很可能导致正常用户也被屏蔽;或者攻击者放慢扫描速度,兴许又能躲过监视。
当然,一套好的规则和模型能让拦截更精准,不过这需要大量的分析和积累。对于 Web 这类特殊群体,我们能否另辟蹊径,寻找一种既简单又靠谱的方案?
在之前讲解的流量劫持系列中也曾提到,后端分析是十分被动的。好在它掌控着流量大权,而 Web 这种特殊流量,同时具备可执行能力。因此可化守为攻,开辟一条全新的作战方案。
所以,我们得借助前端技术,来实现最终目标 —— 做一个有理有据的规则系统。
但一个令人信服的证据不会无中生有,必须人为约定和创造,并在适当的时候将其带上,做到真正的『理据服』。
现有解决方案
在开始构思的我们的『前后端 WAF』之前,有必要提一下现有的解决方案。
每当遇到这种禁止改包重放的场合,安全工程师们总能不假思索的给出解决方案。例如让页面产生个唯一的随机数和时间戳,加密后让后端去验证。
如果仅仅是为了解决个例,这样倒也无可厚非。然而现实中,这样的需求并不少见。如果要让每个业务都去现实这样的方案,将会极大增加前后端开发维护成本。
所以,把一些具体的方案抛给开发者,是很不合理的。对于开发者来说,理应投入全部精力在产品业务的开发上;与其不相关的事,都应交给适配层,让开发者无需了解任何细节,自动帮其实现。
于是,我们需要一个前后端相辅相成的切面系统,在其中透明解决这些琐碎的问题。这样才可大规模部署,以及后期统一更新和维护。
前后端结合 WAF
提到切面,Web『中间件』自然是我们的切入点。和过去的『中间人』劫持类似,我们在页面中注入一段脚本,以开启前端功能。
派出了位于前线的哨兵,就能提供更详细的情报,这在过去是难以实现的。如今前端技术日新月异,利用这些优势,我们开始构思一个全新的系统。
前面提到,如果能在发起请求时,提供一个证据来证明自己不是外人,那样后端就会好办的多 —— 不懂规矩的假人,自然会立即暴露破绽。
因此我们给页面 IO 做一层切面:在请求发出前一刻,带上一个蕴含各种私密信息的暗号,供后端验证。
借助之前《SSLStrip 的未来 —— HTTPS 前端劫持》中使用的技术,稍作修改即可实现前端层面的请求拦截。
如今我们目的更简单,只是携带一个额外参数而已,因此对于同站的请求,甚至无需修改目标 URL,将参数储存在 cookie 即可自动带入请求。
于是,开发者无需任何修改,就能获得更安全的防御。
秘钥策略
在秘钥中,我们可储存各种环境的上下文,例如:
只能用一次的随机数,防止请求重放。
表单数据的校验值,防止中途被改包。
当前时间戳,让后端更精准的掌握发包间隔。
浏览器 BOM 特征,校验是否和 UserAgent 描述的浏览器相符合。
......
最终通过私有算法,将其编码成一个暗号秘钥。
当然,这个秘钥并不要求每次都严格验证。事实上首次访问,就是没有秘钥的;或者在钩子之外的网络请求,例如图片等资源文件,无法保证每次都有唯一的秘钥。
在 Web 富应用时代,『AJAX』和『JSONP』承载了绝大多数的接口请求,因此我们需严格防御。而普通的静态资源风险则小得多,可以更宽松一些。
后期对抗
不过,类似的系统曾经也有过尝试,但都是备受争议的。原因很简单,秘钥是在前端生成的,其中的秘密查看页面源码即可获得。一旦算法被解开,假人也能冒充真实用户,整个系统就失去了意义。
这也是为什么把『前端中间件』标注成黑色背景 —— 我们需要将前端脚本高度混淆,让攻击者难以在短期内破解其中的算法。
于是,我们可以把网络上的对抗,转换成逆向技术的比拼了。让攻击者需要具备更多的技能,从而提高入侵门槛。
黑盒对抗
即使无法破解,攻击者也能想尽办法,将其当做黑盒来使用。我们举几个能预测的情况,进行攻防模拟。
No.1
攻击者可完全无视加密细节,直接把假人的请求转到页面进行代理,因此看起来就像是正常业务发起的。
对于这样的情况,很难有绝对的防御措施。但可以用简单的策略:限制请求频率,从而降低攻击速度。
我们设定一个相对宽松的请求数阈值,如果一定时间里达到上限了,就让前端钩子 Pending 住请求,稍做休息再发出。并且堆积的越多,就让它推延更久。
如果正常用户短时间里操作太快,导致请求超标,那么惩罚几秒也情有可原(点的太快本来就会卡);但请求数持续居高不下的,那就很可疑了,是不是该好好休息下呢?
我们把请求数记录到全局存储里,在多个页面间共享,防止多开慢刷;并且页面关了仍然保留,下次回来继续惩罚,避免反复刷新页面清零。
No.2
即便如此,攻击者仍能想出一些规避方法。例如开上几个不同的浏览器、甚至虚拟机,作为完全隔离的环境,单独慢慢刷。
对付这样的假人,就得用一个靠谱的识别手段:用户行为分析。
正常的用户浏览页面,总是伴随着鼠标滚轮、移动、点击、触屏等事件。而且网络请求的发起,大多通过这些事件的驱动。若页面一动不动,却在不断的发请求,那很有可能就是开挂的。
甚至还可以考虑把采集到的行为数据,通过秘钥提交到后端进行分析,建立更详细的行为模型。
No.3
当然秘密总是会被发现的。行为采集这个门槛也难不倒攻击者,如今能模拟用户行为的机器人也不在少数,它们能逼真的模仿出各种事件,而我们也只能初略的分析。
不过能把攻击者的门槛提高到这一步,我们的目的也达到了 —— 我们并非要 100% 阻止假人,而是通过对抗减少假人。
End
在黑盒对抗下,由于攻击者 不了解实情,只能见招『猜』招,很是被动。我们可以不时更新下脚本,调整策略,或者添加一些巧妙的思路,不断折磨攻击者。
对于攻击者,显然不甘长久在黑盒中对抗,会想方设法破解脚本。
逆向对抗
好在相比传统语言,JavaScript 流行起来的时间还很短,成熟的逆向工具少之又少。而且运行于浏览器,又会牵扯到各种 DOM 与 BOM,因此还得了解不少的前端知识。
做一个好的混淆器,需要不少理论知识。不过不必搞的那样先进 —— 我们只需比攻击者想的更远就可以了。
在实际对抗中,无需太过纠结『技术』层面,更多的是需要『计谋』。有些东西其实原理很简单,但就是想不到。这里就不详细讨论混淆技术了,分享几个非技术层面对抗的案例。
脱壳迷惑
真正的脚本混淆器,应该是打乱原先的代码结构,并且加入各种多余语句,以增加调试复杂度。
不过目前有相当多的混淆器,只是加个壳而已 —— 把原先的代码进行加密,运行时解密再 eval 执行。要解开这种『混淆』毫不费力,把 eval 替换成 alert 就能原形毕露,相信大家都尝试过。
当然,我们也可以利用人们一些天真的想法,进行真假迷惑。
我们显然不会『加壳』原始代码,但可以准备一套伪代码,假装先解密再 eval。这套假代码看上去和真的一样,但里面的功能并不会触发,仅仅用以迷惑而已,把攻击者引到错误的方向上,从而浪费其时间。
而真正的代码,则夹杂在解密的区域,在脱壳之前已经开始运行了。
在解密伪代码的时候,还可以往其中插入大量无用的内容。例如眼花缭乱的特殊符号、成千上万的续行符,阻碍正常阅读。
尽管这不能解决根本问题,但能消耗攻击者的精力,这就是非技术对抗。
蜜罐钓鱼
既然想逆向,那总得先大致看一下脚本。在眼花缭乱的代码里,一段可读文本,就像是万木丛中一点红。利用它吸引攻击者的眼球,从而上钩。
例如,我们在代码开头的某个字符串里,写一段『... compressed by xxxtool』。攻击者看到这段文字,必然会好奇 xxxtool 是什么工具,于是就去网上搜索。
我们预先制作一个简单的网页,提供在线 JavaScript 的加密和解密。名字就叫 xxxtool,一个非常特殊的名字。我们从不推广这个页面,正常情况下根本不会有人来访问。
当攻击者搜到这个网站,自然会进来看看。发现还提供在线解密,以为找到了解药,立即将代码粘进来试试。
落入了我们的蜜罐,就免不了被我们忽悠了。如果是一般的脚本,就显示普通工具的结果;一旦发现是在解密自己的代码,赶紧拿出预先准备的那套伪代码,让攻击者误以为成功解开了。
同时,只要攻击者一进入我们的网页,就立即上报给云端,能及时了解有谁在研究我们的脚本。甚至还可以记录下访客的 IP,通知给 WAF 封杀一段时间。
当然,也未必要那么复杂。我们可以在一个永远到不了的条件分支里,请求一个特殊页面;如果某天发现这个页面有访问量了,显然是有好奇的人在尝试破解。
End
类似的对抗思路还有很多,以后有时间再分享。只有『技术』与『计谋』结合,才能在对抗中更胜一筹。
回到正题,对于这个系统来说,即使被破解也不会有太大的损失。只要换一套秘钥算法和混淆方案,又可以继续我们的防御。自动化的部署,能让我们的更新维护更简单,为持久对抗提供强有力的保障。
后记
我们把传统的网络攻防,转换成逆向技术的对抗,让系统涉及更多的领域。对于攻击者来说,就需要掌握更多的技能点,从而提高入侵的门槛。
退一步,即使攻击者能轻易破解我们的系统,那也无法立即应用于现有的安全工具,必须改造才能使用,同样能大幅增加攻击成本。
前后端结合的 WAF的更多相关文章
- 对抗假人 —— 前后端结合的 WAF
前言 之前介绍了一些前后端结合的中间人攻击方案.由于 Web 程序的特殊性,前端脚本的参与能大幅弥补后端的不足,从而达到传统难以实现的效果. 攻防本为一体,既然能用于攻击,类似的思路同样也可用于防御. ...
- Maven多模块,Dubbo分布式服务框架,SpringMVC,前后端分离项目,基础搭建,搭建过程出现的问题
现互联网公司后端架构常用到Spring+SpringMVC+MyBatis,通过Maven来构建.通过学习,我已经掌握了基本的搭建过程,写下基础文章为而后的深入学习奠定基础. 首先说一下这篇文章的主要 ...
- 快速web开发中的前后端框架选型最佳实践
这个最佳实践是我目前人在做的一个站点,主要功能: oauth登录 发布文章(我称为"片段"),片段可以自定义一些和内容有关的指标,如“文中人物:12”.支持自定义排版.插图.建立相 ...
- JSON(及其在ajax前后端交互的过程)小识
一. json介绍 json是一种轻量级的数据交换格式,规则很简单: 并列的数据之间用逗号(,)分隔: 映射用冒号(:)表示: 并列数据的集合(数组)用方括号([])表示: 映射的集合(对象)用大括号 ...
- com.panie 项目开发随笔_前后端框架考虑(2016.12.8)
(一) 近日和一同学联系,说了我想要做一个网站的打算.她很感兴趣.于是我们协商了下,便觉得一起合作.她写前端,我写后台.因为我对于前端样式设计并不怎么熟悉. (二) 我们决定先做一个 个人博客. 网上 ...
- SpringMVC前后端数据交互总结
控制器 作为控制器,大体的作用是作为V端的数据接收并且交给M层去处理,然后负责管理V的跳转.SpringMVC的作用不外乎就是如此,主要分为:接收表单或者请求的值,定义过滤器,跳转页面:其实就是ser ...
- 前后端分离中,Gulp实现头尾等公共页面的复用
前言 通常我们所做的一些页面,我们可以从设计图里面看出有一些地方是相同的.例如:头部,底部,侧边栏等等.如果前后端分离时,制作静态页面的同学,对于这些重复的部分只能够通过复制粘贴到新的页面来,如果页面 ...
- nodeJS(express4.x)+vue(vue-cli)构建前后端分离详细教程(带跨域)
好想再回到大学宿舍,当时床虽小,房随小,但是心确是满的 ----致 西安工程大学a-114舍友们 转载请注明出处:水车:http://www.cnblogs.com/xuange306/p/6185 ...
- 浅谈WEB前后端分离
重审业务逻辑 用过MVC的童鞋都知道业务逻辑(Bussiness Logic),但是大多对这概念又是模棱两可,业务逻辑从来都是这样难以理解,谈论前后端分离之前这个概念非常有必要探讨一下! 在简单的CR ...
随机推荐
- WPF 如何显示gif
最近碰到了要显示表情的需求,而表情刚好是gif的图片. 于是用了Image试了下,发现不行,只会显示第一帧,然后上网查了下资料,大致有这么几种方法,都可以实现. 第一种: 使用Winfrom里面的pi ...
- windows中将网络共享文件夹映射为网络硬盘
目的是: 实现局域网,不同电脑之间共享文件. 例如: 计划将A电脑 的文件夹C:\MM ,共享给局域网电脑 B. 局域网所有电脑都可访问: 1. 在A电脑中 共享文件夹..选择‘启用网络发现’ ‘ ...
- linux系统 (实验二)实验楼的课程笔记
who am i 打印用户名和终端 终端的启动时间 whoami 打印用户名 who 命令其它常用参数 参数 说明 -a 打印能打印的全部 -d 打印死掉的进程 -m 同am i,mom li ...
- 基于docker的php调用基于docker的mysql数据库的方法
1:建立基于docker的mysql,参考 Mac上将brew安装的MySql改用Docker执行 2:建立基于docker�php image 在当前目录,建立Dockerfile,内容如下 FRO ...
- Liferay JSP Tag Libraries介绍
Liferay自带了很多标签库,这极大地提高了开发Liferay项目的效率. 下面让我们一起来探索吧. 什么是标签库? 什么是JSP标签? 什么是JSTL? 标签库由下面这几部分组成: Tag Lib ...
- 【Leetcode 堆、快速选择、Top-K问题 BFPRT】有序矩阵中第K小的元素(378)
题目 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素. 请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1, 5, 9], [ ...
- 为什么学习React Native三点原因
React Native不到两岁,兼容Android平台刚刚1年.我学习React Native其实也就不到1年,不算长,也不算短. Paul Graham在文章中写过:大多数人真正注意到你的时候,不 ...
- oracle中时间格式的转换
1:取得当前日期是本月的第几周 select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; TO_CHAR(SYSDATE,'YY') se ...
- 将nginx搜集到的日志通过flume转到hive
背景介绍: Nginx为app打点数据,打点日志每小时滚动一次.目录结构如下 文件中的数据如下( cat -A 2019072414r.log 后的结果,-A为显示隐形的符号,下方^A为指定的分隔符. ...
- 笔记:字体大小的几种不同的格式px,em,rem
px px像素(Pixel),相对长度单位,像素px是相对于显示器屏幕分辨率而言的.(引自CSS2.0手册) 譬如,Windows的用户所使用的分辨率一般是96像素/英寸. 而MAC的用户所使用的分辨 ...