利用ModSecurity内置实现第一代 rasp

admin 2022年10月5日15:22:45评论78 views字数 7547阅读25分9秒阅读模式

前言


本文由作者授权发布,如果需要转载,请在后台留言,会将消息转交给作者,未授权请勿转载

书接上文《安全中间件的设计思路和简单践》:https://my.oschina.net/9199771/blog/5417127

当时写完之后感觉意犹未尽,内心觉得很多实现方案其实可以进一步强化。

之后又遇到了中国 X 科院的安全测试工作,仔细研究了下其中的安全标准,其中就要求应用系统内部能抵抗 sqli、xss、恶意上传。

去年开始不间断的研究 ModSecurity 这个出名的 waf,感觉设计的很好(还提交了几个策略都被官方采纳了)

今年又发现了一个 java 集成 ModSecurity 的项目:https://github.com/bytedeco/javacpp-presets/tree/master/modsecurity

这么多事情积攒在一起,所以简单的实现下,集成 ModSecurity 的应用内部防护设计

正文



1)准备 java 环境

目前建议使用 java8+maven 的配置,使用 java11 会有个报错

之后我们要看看当前的最新版本

利用ModSecurity内置实现第一代 rasp

目前只支持到 ModSecurity 3.0.6

<!-- https://mvnrepository.com/artifact/org.bytedeco/modsecurity -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>modsecurity</artifactId>
<version>3.0.6-1.5.7</version>
</dependency>

所以我们编译 ModSecurity 的时候版本要切换到 3.0.6

 

2)编译 ModSecurity

ModSecurity3 目前只能在 linux 下编译使用,所以本文在 linux 上实现。

官方给出了在不同环境下的编译命令(直接复制粘贴就可以了):

https://github.com/SpiderLabs/ModSecurity/wiki/Compilation-recipes-for-v3.x

编译难度几乎为 0,我就不多说了,其中不要忘记 git clone 下代码后先执行 git checkout v3.0.6 把代码切换到 3.0.6 分支,后续版本更新就见机行事

 

3)执行防护

官方的样例代码:https://github.com/bytedeco/javacpp-presets/tree/master/modsecurity/samples

一个是 pom 文件一个 java 源码,我们都要做一下修改。

3.1)其中因为我们采用了 3.0.6 版本,所以先修改一下 pom 文件的 <version>

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.bytedeco.modsecurity</groupId>
<artifactId>samples</artifactId>
<version>1.5.8-SNAPSHOT</version>
<properties>
<exec.mainClass>ModSecuritySimpleIntervention</exec.mainClass>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>modsecurity-platform</artifactId>
<version>3.0.6-1.5.7</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>.</sourceDirectory>
</build>
</project>

3.2)java 源码中我们主要关注的是检测方式

ModSecurity 只是一个引擎,它的防护规则来自于:  https://github.com/coreruleset/coreruleset

利用ModSecurity内置实现第一代 rasp

我们先使用 sqli 和 xss 防护策略。顺便说一句他们更新的挺勤快的,测试用例同步的也很好

@detectXSS 和 @detectSQLi  这两句是使用内置的 libinjection 语义引擎进行 sql 和 xss 探测的语句

所以我们可以把 java 代码做如下修改:

import java.util.Optional;
import org.bytedeco.javacpp.*;
import org.bytedeco.modsecurity.*;

public class ModSecuritySimpleIntervention {
private static final String BASIC_RULE =
"SecRuleEngine Onn" +
"SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@detectSQLi" "id:942100, phase:2, block, capture, t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls, msg:'SQL Injection Attack Detected via libinjection', logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}', tag:'application-multi', tag:'language-multi', tag:'platform-multi', tag:'attack-sqli', tag:'paranoia-level/1', tag:'OWASP_CRS', tag:'capec/1000/152/248/66', tag:'PCI/6.5.2', ver:'OWASP_CRS/4.0.0-rc1', severity:'CRITICAL', multiMatch, setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}', setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'""
+ "n" +
"SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@detectXSS" "id:941100, phase:2, block, t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls, msg:'XSS Attack Detected via libinjection', logdata:'Matched Data: XSS data found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}', tag:'application-multi', tag:'language-multi', tag:'platform-multi', tag:'attack-xss', tag:'paranoia-level/1', tag:'OWASP_CRS', tag:'capec/1000/152/242', ctl:auditLogParts=+E, ver:'OWASP_CRS/4.0.0-rc1', severity:'CRITICAL', setvar:'tx.xss_score=+%{tx.critical_anomaly_score}', setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"";

public static void main(String[]args){
ModSecurity modSecurity = new ModSecurity();

RulesSet rulesSet = new RulesSet();
rulesSet.load(BASIC_RULE);

Transaction transaction = new Transaction(modSecurity, rulesSet, null);
transaction.processConnection("127.0.0.1", 4455, "", 80);
transaction.processURI("https://modsecurity.org/attack?uid=<script>alert(1)</script>&id=-1' and 1=1 union/* foo */select load_file('/etc/passwd')--", "GET", "1.0");
transaction.addResponseHeader("HTTP/1.1", "200 OK");
transaction.processResponseHeaders(200, "HTTP/1.1");
transaction.processRequestBody();
transaction.processRequestHeaders();

ModSecurityIntervention modSecurityIntervention = new ModSecurityIntervention();
boolean isIntervention = transaction.intervention(modSecurityIntervention);

if (isIntervention){
System.out.println("!!!!!!There is intervention !!!!!!!!!");
logRuleMessages(transaction.m_rulesMessages());
}
}

private static void logRuleMessages(RuleMessageList messageList){
if (messageList != null && !messageList.isNull() && !messageList.empty()) {
long size = messageList.size();
System.out.println("MessageRuleSize " + size);
RuleMessageList.Iterator iterator = messageList.begin();
for (int i = 0; i < size; i++) {
logRuleMessage(iterator.get());
iterator.increment();
}
}
}

private static void logRuleMessage(RuleMessage ruleMessage){
System.out.println("RuleMessage id = "+ ruleMessage.m_ruleId()+ " message = " + Optional.ofNullable(ruleMessage.m_message()).map(BytePointer::getString).orElse("NO_MESSAGE"));
}
}

其中规则部分的三句话我增加了注释:

private static final String BASIC_RULE =
//启动引擎
"SecRuleEngine Onn" +
//使用@detectSQLi检测sqli
"SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@detectSQLi" "id:942100, phase:2, block, capture, t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls, msg:'SQL Injection Attack Detected via libinjection', logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}', tag:'application-multi', tag:'language-multi', tag:'platform-multi', tag:'attack-sqli', tag:'paranoia-level/1', tag:'OWASP_CRS', tag:'capec/1000/152/248/66', tag:'PCI/6.5.2', ver:'OWASP_CRS/4.0.0-rc1', severity:'CRITICAL', multiMatch, setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}', setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'""
//注意要增加一个换行
+ "n" +
//使用@detectXSS检测xss攻击
"SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@detectXSS" "id:941100, phase:2, block, t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls, msg:'XSS Attack Detected via libinjection', logdata:'Matched Data: XSS data found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}', tag:'application-multi', tag:'language-multi', tag:'platform-multi', tag:'attack-xss', tag:'paranoia-level/1', tag:'OWASP_CRS', tag:'capec/1000/152/242', ctl:auditLogParts=+E, ver:'OWASP_CRS/4.0.0-rc1', severity:'CRITICAL', setvar:'tx.xss_score=+%{tx.critical_anomaly_score}', setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"";

并构造了一个 sqli 和 xss:

transaction.processURI("https://modsecurity.org/attack?uid=<script>alert(1)</script>&id=-1' and 1=1 union/* foo */select load_file('/etc/passwd')--", "GET", "1.0");

使用 mvn compile exec:java 执行

利用ModSecurity内置实现第一代 rasp

成功探测到了 sqli 和 xss。

 

4)后续拓展

其实做到这里思路就很清晰了,我们内置 waf 的主要工作就是将 ModSecurity 的策略进行拆解内置到应用中。

不过后续的工作定制化程度就非常高了,都需要和架构师达成技术一致才能开展,这里捋一下定制化思路:

4.1)过滤原则

所有的 request(输入)和 response(输出)都需要进行过滤

利用ModSecurity内置实现第一代 rasp

4.2)输入过滤

用户输入的入参包括字符串、xml、json、multipart 中的数据都要走一遍正则 + 语义的判断

4.2)输出过滤

系统输出的内容,最重要的就是接口都要进行敏感信息判断,一旦包含就应当禁止输出,如下图:

利用ModSecurity内置实现第一代 rasp利用ModSecurity内置实现第一代 rasp

4.3)策略定制

依据系统实际情况进行策略增减,尤其是 multipart 上传文件的文件内容应进行全局白名单校验

4.4)策略裁剪

对输入输出内容还能使用 AntiSamy 这个库进行 xss 过滤,AntiSamy 的过滤定制化简单并可以使用白名单(包括标签和标签属性)对输入和输出过滤,比较满足现代的防 xss 的设计

4.5)黑白名单

对某些需要输入 sql 或者后台需要定制复杂 html 模板的功能,则需要可配置白名单。

对某些策略可以被绕过的情况,暂时无法得到强壮策略时,应可以配置紧急黑名单。

 

5)总结:

第一代 rasp 就是使用上面的思路,尤其是 sql 注入问题,由应用内置防护可以避免 url 转义、编码等实现差异所导致的 waf 和应用获取的入参不一致问题。

第二代 rasp 使用函数 hook,保证恶意行为在底层拦截,增加了对未知漏洞的抵御能力

第三代 rasp 将操作系统的函数调用和应用的函数调用进行关联,加强了未知漏洞的分析能力。

 

杀毒软件的演进过程:静态文件特征码 -》内存特征码 -》主动防御 -》云沙箱

应用防护的演进过程:静态流量特征码 -》语义引擎 -》上下文行为分析 -》内存马云查杀

都从静态特征码 -》动态行为特征 -》主动防御和 rasp 的上下文都是针对 api 函数调用关系进行分析 -》云查杀

历史真是出奇的相似:-)


转载自:(已获得原作者授权)

https://my.oschina.net/9199771/blog/5582107


原文始发于微信公众号(Th0r安全):利用ModSecurity内置实现第一代 rasp

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月5日15:22:45
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   利用ModSecurity内置实现第一代 rasphttp://cn-sec.com/archives/1332979.html

发表评论

匿名网友 填写信息