TCP Proxy for MITM Attacks in Metasploit
Posted on So, 2011-11-20 in coding
Some time ago I wrote my first metasploit module and therefore had to play around with ruby. The metasploit module I wrote implements a man-in-the-middle attack on an application layer protocol. So my module is both TCP Server and Client and therefore I like to call it TCP Proxy.
Coming from a python background ruby was kind of strange at the beginning. I still don't know what to think of ruby. Some things are pretty cool, while other just seem weird. Anyway that's not the topic today.
Implementing such a TCP Proxy with the mixins, which the metasploit framework provides, is quite easy... If you know your way around ruby, which I don't. Anyway here's the code so that you can see for yourself how I managed to get this to run. I used the Tcp and the TcpServer server mixins. The TcpServer mixin opens a listen port. When a client connects, I let the Tcp mixin connect to the real server and receive data from the client, send it to the server and then back. In the middle I can inspect or modify the data.
# Copyright (c) 2012, Michael Rodler (contact@f0rki.at) # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. require 'msf/core' class Metasploit3 < Msf::Auxiliary # mixin Tcp include Msf::Exploit::Remote::Tcp # create alias methods alias_method :cleanup_tcp, :cleanup alias_method :run_tcp, :run # mixin TcpServer include Msf::Exploit::Remote::TcpServer # create alias methods alias_method :cleanup_tcpserver, :cleanup alias_method :run_tcpserver, :run alias_method :exploit_tcpserver, :exploit def initialize(info = {}) super(update_info(info,)) # in my case I didn't need this SSL stuff deregister_options('SSL', 'SSLCert', 'SSLVersion', 'RPORT') register_options( [ OptPort.new('SRVPORT', [ true, "", 0 ]), OptString.new('SRVHOST', [ true, "Local listen address", "0.0.0.0" ]), OptString.new('RHOST', [ true, "", "0.0.0.0" ]), ], self.class) # datastore["RPORT"] = datastore["SRVPORT"] end # run tcp server, i.e. start listening port def run exploit_tcpserver end alias_method :exploit, :run # cleanup method, which calls both Tcp and TcpServer cleanup def cleanup cleanup_tcp() cleanup_tcpserver() end # client connected, so we let the Tcp mixin connect def on_client_connect(client) print_status("client connected " + client.peerinfo()) connect() end # client disconnected, so we let the Tcp mixin disconnect def on_client_close(client) print_status("client disconnected " + client.peerinfo()) disconnect() end def on_client_data(client) begin # receive from client data = client.get_once() return if data.nil? or data.length == 0 ### do something evil with the tcp data here # send data to server sock.send(data, 0) # receive data from server respdata = sock.get_once() return if respdata.nil? or respdata.length == 0 ### do something evil with the tcp data here # send data back to client client.put(respdata) rescue ::EOFError, ::Errno::EACCES, ::Errno::ECONNABORTED, ::Errno::ECONNRESET rescue ::Exception print_status("Error: #{$!.class} #{$!} #{$!.backtrace}") end end end
But assuming that we do a mitm attack (like arpspoofing in my case) we get a packet which is not directed at one of our own IP addresses. We can circumvent this by either configuring the IP address on our system or use the firewall to redirect the packet to our own machine:
$ iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 80
If you know how to improve this PLEASE contect me via mail/twitter/whatever. If you are the metasploit/ruby guru and still can't think of a better way, also let me know ;).