作者: 我是小三
博客: http://www.cnblogs.com/2014asm/
由于时间和水平有限,本文会存在诸多不足,希望得到您的及时反馈与指正,多谢!
0x00:web安全防御技术介绍
1.一个Web应用开发到上线的过程大致须要经过如下步骤:需求分析、架构设计、系统设计、功能设计、编码实现、测试评估、上线部署、业务运营等关键步骤,其中功能设计、编码测试、发布部署、系统运营这几个环节中都会存在安全风险,但是针对各环节出现的安全风险目前还没有一个比较全面的防御产品。目前主流的Web应用安全防护产品方案较多的是 WAF(Web Application Firewall)和RASP(Runtime Application Self-Protection),WAF是门卫模型,通常部署在Web应用系统的外部边界,所有正常或恶意流量都需要通过特征规则和模式识别,通过特定的规则和模式识别出恶意请求,并且把它们拒之门外,拒绝向高风险的Web请求提供服务。
WAF虽然可以有效个过滤出绝大多数恶意请求,但是不知道应用运行时的上下文,必然会造成一定程度的误报。并且WAF严重依赖于特征库,各种花式绕过,导致特征编写很难以不变应万变。
举个栗子:
WAF就像门卫保安,每当有人走进时,他只会拦下来问:“你是何人?”并且把这个人的基本样貌和手里的册子(特征库)核对。如果不是黑名单里的坏人,就直接放行。
虽然特征库在不停升级,但是从坏人的角度来看,这样的门卫并非无懈可击。如果我是小偷,我可以装扮成维修工人或者保洁人员。对于水平一般的WAF来说,很可能“穿上马甲你就不认识我了”。而智能程度高一些的 WAF,可以利用技术识别出一些“变装”伎俩,但这时对方同样可以用“整容”甚至“换人”的方法,加大成本再次骗过门卫的眼睛。
如果想精准地阻止坏人,WAF必须以非常高的频率升级特征库,但是永远追在敌人后面跑且高居不下的误报率。
2.RASP的不同就在于运行在应用之中,就像贴身保镖一样与应用融为一体,可以获取到应用运行时的上下文行为,根据运行时上下文或者敏感行为操作,对攻击进行精准的识别或拦截。于此同时,由于RASP运行在应用之中,只要检测点选取合理,获取到的payload已经是解码过的真实payload,可以减少由于WAF规则的不完善导致的漏报。
还是举个栗子:
RASP就像贴身保镖,当装扮成维修工人或者保洁人员的小偷进入办公室之后,却猛地用锤子砸向保险柜上面的锁或者不断拆电脑里的硬盘,那么毋庸多言,保镖就可以将其一左勾拳KO便是。
所以门卫没有拦下伪装者,就是因为他不掌握这个人接下来的行为信息。而贴身保镖,却是有充足信息做出判断的。
3.WAF存在的问题:”有广度没深度”。
一般情况下黑客攻击流程主要包含两个步骤:扫描、实际攻击。
黑客借助自动化工具进行的扫描行为可能是实际进攻行为的万倍或亿倍之多。这是一种典型的“广种薄收”的策略,绝大多数扫描仅仅停留在扫描。如果你的系统没有攻击价值,或没有黑客掌握的漏洞信息,黑客根本就不会对你采取下一步攻击动作。
如果黑客只是进行了简单扫描文件操作,这很可能就是自动化程序进行的扫描,产生威胁的可能性非常小。但是由于WAF不掌握应用内部的信息,它没办法判断扫描的危害性有多大,因此保险起见只能报警。
0x01:什么是RASP? RASP能做什么?
1.在2012年的时候,Gartner引入了“Runtime application self-protection”一词,简称为RASP。它是一种新型应用安全保护技术,它将保护程序像疫苗一样注入到应用程序中,应用程序融为一体,它拦截从应用程序到系统的所有调用,能实时检测和阻断安全攻击,使应用程序具备自我保护能力,当应用程序遭受到实际攻击伤害,就可以自动对其进行防御。
2.监控点位于应用程序的输入输出位置:
输入点包括用户请求、文件输入等;输出点包括包括数据库、网络、文件系统等。
3.RASP能做什么?
图1
如图1所示,RASP可以防御OWASP漏洞与第三方框架漏洞及应用性能监控等。
0x02:RASP防御实现与攻防测试(JAVA)
1.Java版的RASP技术使用javaagent机制来实现。在服务器启动时,可动态的修改Java字节码,对敏感操作的函数进行挂钩,比如:
数据库操作、文件读取、写入操作、命令执行等等。当服务器发生攻击,就会触发这些Hook点,此时RASP agent就可以获取到函数的参数,比如要读取的文件名、要执行的命令等等。
2.RASP启动流程
a.启动时首先会进入 javaagent 的 premain 函数,该函数会在 main 函数之前预先执行。
b.初始化字节码转换模块给load class 操作进行插桩操作,当类加载的时候会先进入 agent 进行处理hook指定函数。
3.架构大致如图2所示,具体技术细节后续分析。
图2
启运后hook架构流程图 3、4所示 :
图3
图4
a.因为启动时候进行了插桩操作,当有类被 ClassLoader 加载时候,所以会把该类的字节码先交给自定义的 Transformer 处理
b. 自定义 Transformer 会判断该类是否为需要 hook 的类,如果是会将该类交给ASM字节码处理框架进行处理。
c. ASM框架会将类的字节码依照事件驱动模型逐步解析每个方法,当触发了我们需要hook的方法,我们会在方法的开头或者结尾插入进入检测函数的字节码
d. 把hook好的字节码返回给transformer从而载入虚拟机。
上面提到关于jvm方面的知识可以参考我博客的这两篇文章
https://www.cnblogs.com/2014asm/p/7999049.html
https://www.cnblogs.com/2014asm/p/8633660.html
4.一个简单的RASP实现与攻击测试
上面我们已经大致了解了整体框架流程,知道了要实现Java的RASP所要具备的能力和技术,在Java中有Javassist、与ASM可以实现对Java字节码的修改;有了修改.class字节码文件的技能,还需要能够在Java运行期间注入我们的防护程序,通过上面的流程框架我们知道Java运行时是发生在JVM中,jdk1.5以后引入了javaAgent技术,javaAgent是运行方法之前的拦截器关键方法,只要在JVM中加入启动参数-javaagent配置Java代理可以在运行时注入我们的防护程序。
我们须要开发两个工程,一个是被保护的web程序(webdemo),另一个是RASP保护程序(RASPDEMO)
a.先简单实现一个有sql 注入漏洞的javaweb应用程序,Servlet部分关键代码如图5、6所示:
图5
图6
创建数据库,将工程代码安装布置好。
b.测试sql注入
访问url: http://localhost:8080/DemoServlet/DemoServlet?userId=1正常返回。再次访问
“http://localhost:8080/DemoServlet/DemoServlet?userId=1 and 1=1/2逻辑判断测试是否能注入,存在注入。
执行sqlmap:
python sqlmap.py -u "http://localhost:8080/DemoServlet/DemoServlet?userId=1" --batch –dbs
python sqlmap.py -u "http://localhost:8080/DemoServlet/DemoServlet?userId=1" --batch -D magedu -T userinfo "user, password" --dump
sqlmap顺利的找到了漏洞,sqlmap可以通过漏洞拿到数据库的信息,图7、8所示:
图7
图8
上面过程主要是利用注入点在原始的sql语句综合的中间或后面"插入"、"拼接"上攻击性的sql payload,从而达到提取非法数据等目的。如图9所示的 paylad。
图9
c.接下来我们将实现一个用于保护上面javaweb的RASP保护程序,上面说过只要在JVM的-javaagent参数中配置我们的保护程序,就能够轻松实现Java的RASP,Java代理程序入口类需要有名为premain的静态方法,下面是RASP保护程序的入口类,图10所示:
图10
ClassTransformer类实现了Java的代理程序机制提供的ClassFileTransformer接口,能够在运行时(Runtime)对类的字节码进行替换与修改;ClassTransformer也很简单,只有一个实现方法:transform,此方法中可以获取得到ClassLoader、className、classfileBuffer等,分别为类加载器、类名、字节码,此时我们可以在transform方法中进行关键函数hook,实现我们的防护程序,图11、12所示。
图11
图12
可以看到我们在transform方法中关键类进行拦截,并通过ASM修改字节码注入我们的保护逻辑,图13代码是VisitorAdapter类中的onMethodEnter方法实现了通过ASM框架实现上面sql执行函数的hook。当每次有执行sql语句时都会进入filter拦截器。
图13
在SQL Filter拦截器中,基于SQL语义分析判断是否存在SQL注入攻击,图14 SQL Filter拦截器:
图14
举个栗子:
务器接收到如下sql语句
select * from userinfo where id=3 and len(@@version)>0 and '1'='1'
当执行时被SQL Filter拦截器监控到并传入语法分析引擎进行分析,这条语句被认为是非法的注入攻击,因为攻击者在子句中利用逻辑表达式进行非法的探测注入,该语句就不会被执行。
d.将我们的保护程序(RASPDEMO)布置在javaweb程序中,再进行一次攻击测试。
当输入攻击测试sql语句时就会被拦截器监控到,图15所示日志信息。
图15
使用sqlmap 测试还是会被拦截器监控到,图16、17所示。
图16
图17
最终我们成功的防止了SQL的注入,当然也可以在此基础上防止其它漏洞攻击。
e.最后再来一个RASP拦截器检测流程,图18 所示 。
图18
单说明下请求处理的流程
1.服务器收到一个请求,从而进入了服务器的请求hook点。
2.进入SQL Hook点,我们挂钩了execute、executeUpdate、executeQuery 等方法,从该方法进入检测。
3.最后返回处理结果。
0x03:RASP产品分析
1.目前国内外基于RASP的产品已经有5个以上,今天我们主要来分析下百度的OpenRasp, 从源码可以看到启动时首先会进入 javaagent的premain函数,该函数会在main函数之前预先执行,接着就是初始化js与hook函数了,图19、20所示:
图19
图20
OpenRASP初始化流程图21所示:
图 21
初始完成后就开始走类字节码修改流程(instrument方式),图22、23所示 :
图22
图23
2.OpenRASP攻击检测流程
在进入到被hook类的函数时,调用事先注入的检测函数,最终调用pluginCheck函数。
a.pluginCheck(CheckParameter.Type type, Object params);
(type为检查的挂载点类型,params为函数原始调用参数)
b.遍历执行该挂载点类型的所有JavaScript检测函数;
c.如果检测函数没有返回block,继续执行;
d.主要分为java检测方式与js插件检测方式,如图24、25所示
图24
图25
OpenRASP框架大致流程就分析到这,它支持大部分攻击类型的检查,可新增JS插件和HooK类进行二次开发。
0x04:总结
1.目前RASP还处于发展中阶段,没有像WAF等常见的安全产品一样有非常明确的功能边界(scope),此文仅为技术学习,更多RASP防御技术与新用法还可以发挥想象,比如日志监控、管理会话、安全过滤、请求管理等。
2.个人觉得rasp有点像杀毒软件,实现功能上区别不是太大。 主要还是规则、监控、拦截。这种方式的弊端,也是无法检测未知攻击。由于rasp与业务系统须要深度合作,会和业务逻辑紧密结合,可能稳定性问题是须要重点考虑的了,其实不论实现产品的技术是什么样的,可能大家实现的方式不一样,使用的名称不一样,不过最终的目的就是为了保护应用程序安全,防止攻击者入侵,只要能给最终用户赋能就是好的技术和产品。
3.最后感谢看完本文,如果觉得这篇文章有用可能帮助到你的朋友也欢迎转载,欢迎扫码关注公众号: