0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ecology相关的挖掘思路

哆啦安全 来源:哆啦安全 2023-09-14 16:49 次阅读

前段时间 ecology 密集发布了一系列补丁,修复几个笔者之前储备的 0day,本文就来介绍其中一个列比较有意思的,以及分享一下相关的挖掘思路。


背景

最近几个月笔者都在研究 Java Web 方向,一方面是工作职责的调整,另一方面也想挑战一下新的领域。对于漏洞挖掘而言,选择一个具体目标是非常重要的,经过一段时间供应链和生态的学习以及同事建议,兼顾漏洞挖掘难度和实战效果选择了 ecology OA作为第一个漏洞挖掘的目标。

代码审计

虽然本文介绍的是 Fuzzing,但之前也说过很多次,自动化漏洞挖掘只能作为一种辅助手段,是基于自身对代码结构的理解基础上的提效方式。

在真正开始挖漏洞之前,笔者花了好几周的时间去熟悉目标的代码,并且对一些不清晰的动态调用去进行运行时分析,最终才能在 20G 代码之中梳理出大致的鉴权和路由流程。

通过分析 JavaEE 应用注册的路由,注意到其中一个映射:

ServletMapping[url-pattern=/services/*,name=XFireServlet]^/services(?=/)|^/servicesz]

其对应的类为org.codehaus.xfire.transport.http.XFireConfigurableServlet:

<servlet>
<servlet-name>XFireServletservlet-name>
<display-name>XFireServletdisplay-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>XFireServletservlet-name>
<url-pattern>/services/*url-pattern>
servlet-mapping>

XFire 考古

XFire[1]并不是 ecology 自己的业务代码,而是一个 SOAP Web 服务框架,它是作为 Apache Axis 的有效替代方案而开发的。除了通过使用 StAX 实现良好性能的目标外,XFire 的目标还包括通过各种插件机制实现灵活性,API 的直观操作以及与通用标准的兼容性。此外 XFire 非常适合集成到基于 Spring Framework 的项目中。

值得一提的是,XFire 目前已经不再进行开发,其官方继任者是Apache CXF[2]

XFire 的用法比较简单,首先在META-INF/xfire/services.xml中定义需要导出的服务,比如:

"1.0"encoding="UTF-8"?>

<beansxmlns="http://xfire.codehaus.org/config/1.0">
<service>
<name>WorkflowServicename>
<namespace>webservices.services.weaver.com.cnnamespace>
<serviceClass>weaver.workflow.webservices.WorkflowServiceserviceClass>
<implementationClass>weaver.workflow.webservices.WorkflowServiceImplimplementationClass>
<serviceFactory>org.codehaus.xfire.annotations.AnnotationServiceFactoryserviceFactory>
service>
beans>

这样weaver.workflow.webservices.WorkflowService就被认为是导出服务。

可以直接被客户端进行调用。调用方式主要是通过 SOAP 请求到 XFireServlet,例如调用上述服务可以发送 POST 请求到/services/WorkflowService:

"1.0"encoding="UTF-8"?>
<Body>
<getUserId>
 <p>evilpanp>
 <p>2333p>
getUserId>
Body>

表示以指定参数调用服务的getUserId方法。

SQL 注入

接下来回到漏洞本身,WorkflowService 服务的具体实现为WorkflowServiceImpl,例如其中的 getUserId 就是服务导出的一个方法,其具体实现为:

@Override
publicStringgetUserId(Stringvar1,Stringvar2){
if(Util.null2String(var2).equals("")){
return"-1";
}elseif(Util.null2String(var1).equals("")){
return"-2";
}else{
RecordSetvar3=newRecordSet();
var3.executeQuery("selectidfromHrmResourcewhere"+var1+"=?andstatus<4 ",var2);
return!var3.next()?"0":Util.null2s(var3.getString("id"),"0");
}
}

可以看到,一个教科书式的 SQL 注入就已经找到了。

Service 鉴权

现在漏洞点找到了,触发路径也找到了,可实际测试的时候发现这个接口有些特殊的鉴权,其鉴权逻辑为判断请求地址是否是内网地址,如果是的话就放行。

考虑到很多系统是集群部署的,且前面有一层或者多层负载均衡,因此实际请求服务的可能是经过反向代理的请求,此时客户端的真实 IP 只能通过X-Forward-For等头部获取。

这本来无可厚非,但是 HTTP 请求头是可以被攻击者任意设置的,因此 ecology 在此基础上进行了复杂的过滤,精简后的伪代码如下:

privateStringgetRemoteAddrProxy(){
Stringip=null;
StringtmpIp=null;
tmpIp=this.getRealIp(this.request.getHeaders("RemoteIp"),ipList);
if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){
ip=tmpIp;
}
booleanisInternalIp=IpUtils.internalIp(ip);
if(isInternalIp){
ipList.add(this.request.getRemoteAddr());
tmpIp=IpUtils.getRealIp(ipList);
if(!IpUtils.internalIp(tmpIp)){
ip=tmpIp;
}
}

returnip!=null&&ip.length()!=0&&!"unknown".equalsIgnoreCase(ip)?ip:null;
}

IpUtils#internalIp的判断更为复杂,连byte[]都出来了:

publicstaticbooleaninternalIp(Stringip){
if(ip!=null&&!ip.equals("127.0.0.1")&&!ip.equals("::1")&&!ip.equals("0000:1")){
if(ip.indexOf(":")!=-1&&ip.indexOf(":")==ip.lastIndexOf(":")){
ip=ip.substring(0,ip.indexOf(":"));
}

byte[]addr=(byte[])null;
if(isIpV4(ip)){
addr=textToNumericFormatV4(ip.trim());
}else{
addr=textToNumericFormatV6(ip.trim());
}

returnaddr==null?false:internalIp(addr);
}else{
returntrue;
}
}

publicstaticbooleaninternalIp(byte[]addr){
byteb0=addr[0];
byteb1=addr[1];
byteSECTION_1=true;
byteSECTION_2=true;
byteSECTION_3=true;
byteSECTION_4=true;
byteSECTION_5=true;
byteSECTION_6=true;
switch(b0){
case-84:
if(b1>=16&&b1<= 31){
returntrue;
}
case-64:
switch(b1){
case-88:
returntrue;
}
default:
returnfalse;
case10:
returntrue;
}
}

其逻辑是对 getRemoteAddrProxy 取出来的 IP,如果路径匹配webserviceList且 IP 匹配webserviceIpList前缀,就认为是内网地址的请求从而进行放过:

webserviceList=[
"/online/syncOnlineData.jsp",
"/services/",
"/system/MobileLicenseOperation.jsp",
"/system/PluginLicenseOperation.jsp",
"/system/InPluginLicense.jsp",
"/system/InMobileLicense.jsp"
];

webserviceIpList=[
"localhost",
"127.0.0.1",
"192.168.",
"10.",
"172.16.",
"172.17.",
"172.18.",
"172.19.",
"172.20.",
"172.21.",
"172.22.",
"172.23.",
"172.24.",
"172.25.",
"172.26.",
"172.27.",
"172.28.",
"172.29.",
"172.30.",
"172.31."
]

根据上面的代码,你能发现鉴权绕过的漏洞吗?

Fuzzing

也许对代码比较敏感的审计人员可以通过上述鉴权代码很快发现问题,但说实话我一开始并没有找到漏洞。于是我想到这个鉴权逻辑是否能单独抽离出来使用 Fuzzing 的思路去进行自动化测试。

之前发现 Java 也有一个基于 libFuzzer 的模糊测试框架Jazzer[3],但是试用之后发现比较鸡肋,因为和二进制程序会自动 Crash 不同,Java 的 fuzz 需要自己指定 Sink,令其在触达的时候抛出异常来构造崩溃。

虽然说没法发现通用的漏洞,但是对于现在这个场景来说正好是绝配,我们可以将目标原始的鉴权代码抠出来,然后在未授权通过的时候抛出一个异常即可。构建的 Test Harness 代码如下:

publicstaticvoidfuzzerTestOneInput(FuzzedDataProviderdata){
Stringpoc=data.consumeRemainingAsString();
fuzzIP(poc);
}

publicstaticvoidfuzzIP(Stringpoc){
if(containsNonPrintable(poc))return;
XssRequestWeblogicx=newXssRequestWeblogic();
Stringout=x.getRemoteAddr(poc);
booleancheck2=check2(out);
if(check2){
thrownewFuzzerSecurityIssueHigh("FoundIP["+poc+"]");
}
}

publicstaticbooleancheck2(Stringipstr){
for(Stringip:webserviceIpList){
if(ipstr.startsWith(ip)){
returntrue;
}
}
returnfalse;
}

其中精简了一些 ecology 代码中读取配置相关的依赖,将无关的逻辑进行手动剔除。

编译好代码后,使用以下命令开始进行 fuzz:

$./jazzer--cp=target/Test-1.0-SNAPSHOT.jar--target_class=org.example.App

不多一会儿,就已经有了一个成功的结果!

aaffd0a0-5292-11ee-a25d-92fbcf53809c.pngfuzz.png

可以看到图中给出了127.0.0.10这个 payload,可以触发 IP 鉴权的绕过!反过来分析这个 PoC,可以发现之所以能绕过是因为webserviceIpList只检查了前缀,而127.0.0.10可以在internalIp返回False,即认为不是内部 IP,但实际上 webserviceIpList 却认为是内部 IP,从而导致了绕过。

如果只是从代码上去分析的话,可能一时半会并不一定能发现这个问题,可是通过 Fuzzing 在覆盖率反馈的加持下,却可以在几秒钟之内找到正解,这也是人工审计无法比拟的。

漏洞补丁

通过 IP 的鉴权绕过和 XFire 组件的 SQL 注入,笔者实现了多套前台的攻击路径,并且在 HW 中成功打入多个目标。因为当时提交的报告中带了漏洞细节,因此这个漏洞自然也就被官方修补了。如果没有公开的话这个洞短期也不太会被撞到。

漏洞修复的关键补丁如下:

diff--gita/src/weaver/security/webcontainer/IpUtils.javab/src/weaver/security/webcontainer/IpUtils.java
index6b3d8efc..e7482511100644
---a/src/weaver/security/webcontainer/IpUtils.java
+++b/src/weaver/security/webcontainer/IpUtils.java
@@-48,12+48,16@@publicclassIpUtils{
}

publicstaticbooleaninternalIp(Stringip){
-if(ip!=null&&!ip.equals("127.0.0.1")&&!ip.equals("::1")&&!ip.equals("0000:1")){
+if(ip==null||ip.equals("127.0.0.1")||ip.equals("::1")||ip.equals("0000:1")){
+returntrue;
+}elseif(ip.startsWith("127.0.0.")){
+returntrue;
+}else{
if(ip.indexOf(":")!=-1&&ip.indexOf(":")==ip.lastIndexOf(":")){
ip=ip.substring(0,ip.indexOf(":"));
}

其中把 equals 换成了 startsWith,并且还过滤了我们之前使用的 WorkflowService 组件。当然还是沿袭 ecology 一贯的漏洞修复原则,不改业务代码,只增加安全校验,这也是对历史遗留问题的一种妥协吧。

总结

  • •对于 Java 这样的内存安全编程语言也是可以 fuzz 的,只不过目的是找出逻辑漏洞而不是内存破坏;

  • •漏洞挖掘初期花时间投入到代码审计中是有必要的,有助于理解项目整体结构并在后期进行针对性覆盖;

  • •漏洞挖掘的时候重点关注边界的系统和服务,处于信任边界之外的组件更有可能过于信任外部输入导致安全问题;

  • •对于看起来很复杂的数据处理模块,可以充分利用 Fuzzing 的优势,帮助我们快速找出畸形的 payload;

  • •模块化 Fuzzing 的难点在于抽离代码并构建可编译或者可以独立运行的程序,即构建 Test Harness,跑起来测试用例你就已经成功了 90%;

  • •软件开发和漏洞挖掘正好相反。开发者会出于厌恶情绪刻意避开复杂的历史遗留代码,而这些代码却是更可能出现问题的地方。因此安全研究员要学会克服自己的厌恶情绪,做到 —— “明知山有屎,偏向屎山行”。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 自动化
    +关注

    关注

    29

    文章

    5510

    浏览量

    79093
  • 编程语言
    +关注

    关注

    10

    文章

    1938

    浏览量

    34593
  • 代码
    +关注

    关注

    30

    文章

    4742

    浏览量

    68337

原文标题:总结

文章出处:【微信号:哆啦安全,微信公众号:哆啦安全】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    云计算数据挖掘

    想要自学云计算和数据挖掘想问下这些方面有哪些内容该从何开始求大神们指教谢谢
    发表于 04-19 00:07

    灵玖软件:NLPIR智能挖掘系统专注中文处理

    ,C#等各类开发语言使用。  随着云计算、移动互联网以及物联网等技术的发展和完善,相信大数据在各个领域的应用会越来越广泛和深入,相关的研究也会越来越全面和深入,在信息管理领域,综合应用数据挖掘技术和人工智能技术,获取用户知识、文献知识等各类知识,将是实现知识检索和知识管理
    发表于 01-21 11:39

    AlphaFuzzer漏洞挖掘工具的使用

    AlphaFuzzer是一款多功能的漏洞挖掘工具,到现在为止,该程序以文件格式为主。1.0版本主要包含了:一个智能文件格式的漏洞挖掘框架。一个通用文件格式的fuzz模块。此外,他还包含了一个ftp服务器程序的fuzz模块。一个程序参数的fuzz模块。一些shellcode
    发表于 07-15 06:44

    数据挖掘算法有哪几种?

    针对现有数据挖掘体系结构松散揭合、算法运行效率不高的问题,提出了嵌入式数据挖掘模型。该模型实现了算法的组件化管理,并将整个数据挖掘流程控制在数据库、数据仓库中,在简化数据挖掘过程的同时
    发表于 03-11 06:36

    数据挖掘之基于关联挖掘的商品销售分析

    数据挖掘:基于关联挖掘的商品销售分析
    发表于 06-09 08:32

    机器学习与数据挖掘方法和应用

    机器学习与数据挖掘方法和应用(经典)
    发表于 09-26 07:56

    数据挖掘浅析

    摘要:主要介绍了数据挖掘的产生、发展、定义和任务,讨论了常用的挖掘方法和工具,最后举例介绍了数据挖掘的一些应用.关键词:数据挖掘;知识发现;决策树 Abstract:Th is
    发表于 01-08 21:23 12次下载

    关联规则挖掘在数据录入、校对系统中的应用

    本文介绍了关联规则挖掘在数据录入、校对系统的设计思路、体系结构和实现要点。关键词:数据挖掘;关联规则;关联规则参照表数据的准确录入和高效的校对是各行业的产
    发表于 09-03 11:55 6次下载

    怎么学习数据挖掘_如何系统地学习数据挖掘

    数据挖掘工程师多是通过对海量数据进行挖掘,寻找数据的存在模式,从而通过数据挖掘来解决具体问题。其更多是针对某一个具体的问题,是以解决具体问题为导向的。
    发表于 12-31 12:41 4774次阅读

    代码实例及详细资料带你入门Python数据挖掘与机器学习

    本文结合代码实例待你上手python数据挖掘和机器学习技术。 本文包含了五个知识点: 1. 数据挖掘与机器学习技术简介 2. Python数据预处理实战 3. 常见分类算法介绍 4. 对鸢尾花进行分类案例实战 5. 分类算法
    的头像 发表于 03-03 10:10 3339次阅读

    浅析嵌入式数据挖掘模型应用到银行卡业务中的相关知识

    数据挖掘就是从存放在数据库、数据仓库或者其他信息库中的大量数据中挖掘有趣知识的过程。它是在多种数据存储方式的基础上,借助有效的分析方法和工具,从传统的事务型数据库功能(增加、删除、修改、查询、统计等
    发表于 05-15 16:31 958次阅读
    浅析嵌入式数据<b class='flag-5'>挖掘</b>模型应用到银行卡业务中的<b class='flag-5'>相关</b>知识

    成为数据挖掘工程师有哪些要求

    计算机、统计学等相关专业,具有深厚的统计学、数学、数据挖掘知识,熟悉数据仓库和数据挖掘相关技术;
    的头像 发表于 06-09 17:24 5787次阅读

    某CMS的命令执行漏洞通用挖掘思路分享

    大概是在上半年提交了某个CMS的命令执行漏洞,现在过了那么久,也想通过这次挖掘通用型漏洞,整理一下挖掘思路,分享给大家。
    的头像 发表于 05-18 17:18 3319次阅读
    某CMS的命令执行漏洞通用<b class='flag-5'>挖掘</b><b class='flag-5'>思路</b>分享

    数据挖掘定义及方法 数据挖掘在微电子领域的应用

    制造中的数据挖掘流程示意图,并用主成分分析法分析产生异常的原因,最后得出合理的结论。  数据挖掘相关技术  1、数据挖掘的定义和特点  数据挖掘
    发表于 07-18 15:43 0次下载

    机器学习与数据挖掘的区别 机器学习与数据挖掘的关系

    机器学习与数据挖掘的区别 , 机器学习与数据挖掘的关系 机器学习与数据挖掘是如今热门的领域。随着数据规模的不断扩大,越来越多的人们认识到数据分析的重要性。但是,机器学习和数据挖掘在实践
    的头像 发表于 08-17 16:30 2005次阅读