关于我在梦里在EDUSRC刷屏的事

admin 2024年1月21日16:22:23评论16 views字数 5042阅读16分48秒阅读模式

0x01、前言

本文仅进行思路分享,漏洞已全部修复【请勿非法测试】。当你看到这篇文章的时候,我可能就已经没什么时间继续写了。即将专升本了,接下来好长一段时间将会投入复习。希望可以上岸

关于我在梦里在EDUSRC刷屏的事
image.png

老生常谈,也找了几个getshell的点,但是利用起来有点怪,就先放着,后面再写。这个系统基于springboot来写的,那就直接先拼接路由,如下:

关于我在梦里在EDUSRC刷屏的事
image.png

直接访问系统会如上图所示,服务器返回500。抓个正常的登录包看看是什么情况。

关于我在梦里在EDUSRC刷屏的事
image.png

可以看到正常业务请求包中是有sign,timestamp,noceid和app-key。

关于我在梦里在EDUSRC刷屏的事

这时候如果直接拷贝过来,会提示非法请求接口。这时候就直接全局搜索报错关键字。尝试破解请求头信息

0x02、请求头破解绕过

关于我在梦里在EDUSRC刷屏的事
image.png

如图查看校验的一个过程,先是通过这行代码获取到sign的配置文件

SignProperties signProperties = (SignProperties)SpringUtils.getBean(SignProperties.class);
关于我在梦里在EDUSRC刷屏的事
image.png

看到配置文件前缀是string.sign,那么我们直接去搜索一下,先把能拿到的先拿出来

关于我在梦里在EDUSRC刷屏的事
image.png
string.sign.appKey= edu
string.sign.timeout= 10000
string.sign.appSecret= EDUstring@1307

继续返回到上文当中。

关于我在梦里在EDUSRC刷屏的事
image.png

获取完配置文件信息之后再去看接下来的代码

public static DcHttpHeader get() {
        DcHttpHeader httpHeader = new DcHttpHeader();
        HttpServletRequest request = ServletHttpUtils.getRequestAttributes().getRequest();
        String parameter = request.getParameter("download_token");
        log.info("检测链接参数download_token:{}", parameter);
        String token;
        if (ObjectUtils.isNotEmpty(parameter)) {
            httpHeader = (DcHttpHeader)JSONObject.parseObject(parameter, DcHttpHeader.class);
            httpHeader.setUrl(request.getRequestURI());
            token = httpHeader.getToken();
            if (StringUtils.isNotBlank(token)) {
                Map<String, String> header = new HashMap();
                header.put("token", token);
                if (request instanceof RequestWrapper) {
                    ((RequestWrapper)request).addHeader(header);
                } else {
                    ServletUtils.addHeader(request, header);
                }
            }

            if (StringUtils.isNotEmpty(token)) {
                SecurityContextHolder.setUserId(ServletUtils.getHeader(request, "userId"));
                SecurityContextHolder.setUserCode(ServletUtils.getHeader(request, "userCode"));
                SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, "userKey"));
                LoginUser loginUser = AuthUtil.getLoginUser(token);
                if (ObjectUtils.isNotEmpty(loginUser)) {
                    log.info("webtoken值:{}", token);
                    AuthUtil.verifyLoginUserExpire(loginUser);
                    SecurityContextHolder.set("login_user", loginUser);
                }
            }

            return httpHeader;
        } else {
            token = request.getHeader("app-key");
            String token = request.getHeader("token");
            String sign = request.getHeader("sign");
            if (ObjectUtils.isNotEmpty(request.getHeader("timestamp"))) {
                Long timestamp = Long.parseLong(request.getHeader("timestamp"));
                httpHeader.setTimestamp(timestamp);
            }

            String noceId = request.getHeader("noceId");
            httpHeader.setUrl(request.getRequestURI());
            httpHeader.setSign(sign);
            httpHeader.setNoceId(noceId);
            httpHeader.setAppKey(token);
            httpHeader.setToken(token);
            return httpHeader;
        }
    }

有两个条件这边会判断download_token不为空,为空则进入else,去获取app-key,token,sign,timestamp四个请求头。并且判断timestamp也就是时间戳不为空。然后把时间戳给到一个请求头的对象中。

依次是:timestamp -> URI路径 -> sign -> noceId -> token。最后再返回对象

关于我在梦里在EDUSRC刷屏的事
image.png

随后if判断app-key不为空, 然后获取数据,与枚举类型中的值进行对比是否正确。这边是没用的,校验还是不通过。继续看下面的代码。

Map<String, String> param = new HashMap();
String url = dcHttpHeader.getUrl();
param.put("url", url);
String sign = dcHttpHeader.getSign();
String noceId = dcHttpHeader.getNoceId();
param.put("sign", sign);
param.put("noceId", noceId);
param.put("timestamp", dcHttpHeader.getTimestamp().toString());
param.put("appKey", signProperties.getAppKey());

flag = SignUtil.verifyTimeStampNotify(param, signProperties.getAppSecret(), SignType.MD5, signProperties.getTimeout());

创建hashmap,随后把URI,sign,noceid,timestamp,服务端的appKey设置进去。其实单看到dcHttpHeader就应该知道,这些是从客户端那边获取的请求头,并没什么卵用。只有一个appKey是从配置文件中获取的,也就是“edu”。

重点看verifyTimeStampNotify()方法。除了第一个参数是从客户端获取的,其他三个都是从配置文件获取

string.sign.appKey= edu
string.sign.timeout= 10000
string.sign.appSecret= EDUstring@1307
关于我在梦里在EDUSRC刷屏的事
image.png

跟尽量查看,先判断时间戳不为空,最后判断时效性。然后再次进行校验。继续跟进来

关于我在梦里在EDUSRC刷屏的事
image.png

这边就可以看到是先从客户端获取sign,再本地创建个localSign。最后将两者对比查看是否正确。正确则校验通过。继续跟进createSign(params, appSecret, signType) 方法

关于我在梦里在EDUSRC刷屏的事
image.png

第一行就不用看了。主要看下面一行,服务端会把客户端的sign删除掉,然后创建个临时字符串,

关于我在梦里在EDUSRC刷屏的事
image.png

回顾上面的方法,其实就是把URI,noceid,timestamp,服务端的appKey使用&串起来。最后再加个&key=" + appSecret

 return signType == SignType.MD5 ? md5(stringSignTemp).toUpperCase() : hmacSha256(stringSignTemp, appSecret).toUpperCase();

再经过这最后一行判断,通过拦截器就可以知道类型是MD5德,所以是对这一串字符串进行MD5加密,并转换为大写。至此,请求头已经破解了。可以发现一开始的请求头生效的没几个,除了时间戳需要验证时效性,其他的目前是没什么用处了,noceid可以一直用,token默认为null即可

关于我在梦里在EDUSRC刷屏的事
image.png
关于我在梦里在EDUSRC刷屏的事
image.png

0x03、备份文件下载

关于我在梦里在EDUSRC刷屏的事
image.png

数据库备份文件下载就需要用到上面的code了。跟踪Service的实现类如下

关于我在梦里在EDUSRC刷屏的事
image.png

会通过code去下载数据库的备份文件,只需要对的code即可。

关于我在梦里在EDUSRC刷屏的事
image.png

其实这边解压还有问题,下载解压发现里面需要解密,最后发现原来再备份的时候发现进行了openssl加密了。

关于我在梦里在EDUSRC刷屏的事
image.png
关于我在梦里在EDUSRC刷屏的事
image.png

密码的话其实就是code,也就是下载下来的文件名。

0x04、任意用户添加

虽然获取到了管理员信息,但是用户密码加密且不可逆。只能去尝试添加用户

关于我在梦里在EDUSRC刷屏的事
image.png
关于我在梦里在EDUSRC刷屏的事
image.png

这时候会发现创建管理员其实是存在一定的概率,但是虽然管理员有约束,但是其他教育厅用户等等没有限制

关于我在梦里在EDUSRC刷屏的事
image.png

如图,图中四个用户权限有限制,但是其他用户不存在限制可以加其他权限的用户。之后再根据权限,去添加相关功能的权限值,比如相关功能点校验

关于我在梦里在EDUSRC刷屏的事
image.png

同时添加的用户也有问题,密码也是很神奇。

关于我在梦里在EDUSRC刷屏的事
image.png
关于我在梦里在EDUSRC刷屏的事
image.png

密码规律是姓名拼音的首字母大写+@+账号

0x05、结语

感谢看到这里,与君共勉,几个月后见

关于我在梦里在EDUSRC刷屏的事

原文始发于微信公众号(赛博搬砖工):关于我在梦里在EDUSRC刷屏的事

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月21日16:22:23
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   关于我在梦里在EDUSRC刷屏的事https://cn-sec.com/archives/2414671.html

发表评论

匿名网友 填写信息