1
00:00:00,000 --> 00:00:15,065
34c3 intro
2
00:00:15,065 --> 00:00:30,130
Herald: All right, next lecture here is
from Artem. Next to the fact that these,
3
00:00:30,130 --> 00:00:38,819
how would I spell it, earning a nice
amount of money probably at a lab that's
4
00:00:38,819 --> 00:00:46,589
quite renown in the world as Kaspersky and
from that point on he's not just looking
5
00:00:46,589 --> 00:00:52,539
in this lecture to exploit a development
for Cisco stuff we all suffered from this
6
00:00:52,539 --> 00:00:57,609
last year or we all heard about it and
don't know the impact maybe, but he's
7
00:00:57,609 --> 00:01:05,019
going to explain us the work he did on
that field so please can I ask your warm
8
00:01:05,019 --> 00:01:14,299
welcoming applause for Artem Kondratenko,
do you, okay good, please give him a warm
9
00:01:14,299 --> 00:01:21,960
applause and start.
applause
10
00:01:21,960 --> 00:01:26,149
Artem Kondratenko: Hello everyone, so
excited to finally be able to attend Chaos
11
00:01:26,149 --> 00:01:31,880
Communication Congress. Very happy to see
y'all. So without further ado let's jump
12
00:01:31,880 --> 00:01:38,229
into some practical IOS exploitation. So a
few words about myself, my name is Artem,
13
00:01:38,229 --> 00:01:43,659
I do stuff, mostly security related stuff
but mostly my areas of expertise are
14
00:01:43,659 --> 00:01:48,869
penetration tests, both internal external
and also do research in my free time and
15
00:01:48,869 --> 00:01:54,289
get a bug bounty here and there and this
talk is actually kind of a continuation of
16
00:01:54,289 --> 00:01:59,729
my talk this summer at Def Con about Cisco
Catalyst exploitation.
17
00:01:59,729 --> 00:02:04,600
So for those of you who are out of
context, let's recap what happened earlier
18
00:02:04,600 --> 00:02:14,450
this year. So year 2017 was reaching
vulnerabilities for Cisco IOS devices. So
19
00:02:14,450 --> 00:02:20,140
we had at least three major advisories for
Cisco IOS that represented three remote
20
00:02:20,140 --> 00:02:24,280
code execution vulnerabilities.
So the first one is vulnerability in
21
00:02:24,280 --> 00:02:30,600
cluster management protocol which resulted
in unauthenticated remote code
22
00:02:30,600 --> 00:02:36,560
execution via telnet, second one is SNMP
overflow and the DHCP remote code
23
00:02:36,560 --> 00:02:40,310
execution.
In this lecture I'm gonna be talking
24
00:02:40,310 --> 00:02:47,060
about two of those vulnerabilities because
DHCP RCE is yet to be researched. So
25
00:02:47,060 --> 00:02:51,880
hopefully by the end of this talk I'm
going to be able to show you a live demo
26
00:02:51,880 --> 00:02:56,810
of exploiting the SNMP service in Cisco
IOS.
27
00:02:56,810 --> 00:03:05,870
So but first what happened earlier: So on
March 26, 2017 we had a major advisory from
28
00:03:05,870 --> 00:03:10,790
Cisco that announcing that hundreds of
models of different switches are
29
00:03:10,790 --> 00:03:15,230
vulnerable to remote code execution
vulnerability. No public code, no public
30
00:03:15,230 --> 00:03:21,070
exploit was available and no exploitation
in the wild. So it was critical and main
31
00:03:21,070 --> 00:03:24,380
points of the vulnerability were as
follow:
32
00:03:24,380 --> 00:03:30,970
So Cisco switches can be clustered, and
there's a cluster management protocol
33
00:03:30,970 --> 00:03:36,430
built on top of telnet, and this
vulnerability is a result of actually two
34
00:03:36,430 --> 00:03:43,880
errors, a logic error and a binary error.
So the telnet options get parsed
35
00:03:43,880 --> 00:03:49,940
regardless whether the switch is in
cluster mode or not and the incorrect
36
00:03:49,940 --> 00:03:56,560
processing of this cluster management
protocol options result in overflow. So
37
00:03:56,560 --> 00:04:00,980
what is interesting about this
vulnerability that actually the source of
38
00:04:00,980 --> 00:04:06,010
research for Cisco guys was another
internal research. But the "Vault 7" leak
39
00:04:06,010 --> 00:04:13,210
that happened in March this year so many
hacking techniques and tools were released
40
00:04:13,210 --> 00:04:20,440
to public by WikiLeaks, and among many
vendors that were affected was Cisco
41
00:04:20,440 --> 00:04:25,090
Systems.
So basically except for the advisory you
42
00:04:25,090 --> 00:04:30,240
could go to WikiLeaks and read about this
potential exploitation technique for Cisco
43
00:04:30,240 --> 00:04:35,490
Catalyst. So basically these were notes of
an engineer who was testing the actual
44
00:04:35,490 --> 00:04:43,750
exploit, there were no actual exploit in
the leak. So basically this worked as
45
00:04:43,750 --> 00:04:49,210
follows: there was two modes of
interaction, so for example an attacker
46
00:04:49,210 --> 00:04:55,330
could connect to the telnet, overflow the
service and be presented with a privileged
47
00:04:55,330 --> 00:05:02,860
15 shell. The other mode of operation was
the … is to set for all the subsequent
48
00:05:02,860 --> 00:05:08,790
… connections to the telnet, there
will be … without credentials so I
49
00:05:08,790 --> 00:05:14,620
did. We discover this exploit, full
research was presented at DEFCON 25. I was
50
00:05:14,620 --> 00:05:20,620
targeting system catalyst 2960 as a target
switch. I also described a PowerPC
51
00:05:20,620 --> 00:05:25,340
platform exploitation and the way you can
debug it.
52
00:05:25,340 --> 00:05:31,430
You can look at my blog post about
exploiting this service, and also the
53
00:05:31,430 --> 00:05:37,530
proof accounts of exploit on my github
page. But today I want to talk about
54
00:05:37,530 --> 00:05:42,200
something else, about another
vulnerability that was announced this year
55
00:05:42,200 --> 00:05:49,490
about SNMP remote code execution.
So the actual motivation behind this
56
00:05:49,490 --> 00:05:55,840
research was that I was conducting an
external pentest, and it was revealed an
57
00:05:55,840 --> 00:06:00,510
nmap scan revealed that a Cisco router
where the default community string was
58
00:06:00,510 --> 00:06:07,090
available. So the goal was to get access
to the internal network.
59
00:06:07,090 --> 00:06:13,450
So the actual advisory said that the
attacker needs a read-only community
60
00:06:13,450 --> 00:06:19,700
string to gain remote code execution on
the device. The target router was a 2800
61
00:06:19,700 --> 00:06:26,650
integrated services router, which is a
very common device on the networks.
62
00:06:26,650 --> 00:06:34,389
So the technical specs for it is it's a
it has a MIPS big endian architecture, you
63
00:06:34,389 --> 00:06:39,990
don't have any client debugging tools for
it available, and it's interesting in that
64
00:06:39,990 --> 00:06:46,919
sense that the firmware is relatively new
for this router, and it might be
65
00:06:46,919 --> 00:06:52,771
interesting to look at the defensive end
exploit prevention mechanisms employed by
66
00:06:52,771 --> 00:06:59,370
Cisco IOS. When I say relatively new is
the interesting thing is that this device
67
00:06:59,370 --> 00:07:04,040
is actually end of support, it's not
supported. So the last patch for it was
68
00:07:04,040 --> 00:07:12,360
came out at 2016, and to remind you the
advisory for SNMP overflow appeared in
69
00:07:12,360 --> 00:07:19,040
2017, in June 2017, but nonetheless this
is still widely used device.
70
00:07:19,040 --> 00:07:27,760
If you search for SNMP banner on Shodan,
you will find at least 3000 devices with
71
00:07:27,760 --> 00:07:37,550
SNMP service available with default public
string. So this devices are all supposedly
72
00:07:37,550 --> 00:07:43,710
vulnerable to SNMP overflow. And the
question is whether we can build a mount
73
00:07:43,710 --> 00:07:49,140
code execution exploit for it. So since
we're going to be exploiting SME protocol,
74
00:07:49,140 --> 00:07:54,460
let's make a quick quick recap of how it
works, just light touch.
75
00:07:54,460 --> 00:08:01,930
So SNMP comes with several abbreviations
like MIB, which stands for management
76
00:08:01,930 --> 00:08:07,919
information base, and is kind of a
collection of objects that can be
77
00:08:07,919 --> 00:08:12,860
monitored from the SNMP manager. And so a
management information base actually
78
00:08:12,860 --> 00:08:21,370
consists of object identifiers. And as an
example: you all know that printers
79
00:08:21,370 --> 00:08:25,550
usually use SNMP, For example if there is
a certain level of ink in the cartridge,
80
00:08:25,550 --> 00:08:31,729
you can query the SNMP service on this
device for the percentage of ink left. So
81
00:08:31,729 --> 00:08:39,179
that's a kind of example how it works.
Management information base looks like a
82
00:08:39,179 --> 00:08:42,219
tree.
So you have your base element at the top
83
00:08:42,219 --> 00:08:47,839
and your leaf elements, So all these
elements represent an object that could be
84
00:08:47,839 --> 00:08:53,509
queried. We're going to be looking at get
requests. And that is why the advisory
85
00:08:53,509 --> 00:08:57,790
states that for their vulnerability to be
triggered you only have to know the read-
86
00:08:57,790 --> 00:09:03,110
only community string. So it's a
relatively simple protocol, you just
87
00:09:03,110 --> 00:09:08,199
supply the object identifier you're
querying and you'll get back the result.
88
00:09:08,199 --> 00:09:14,999
So here for example we get the router
version, the description field. And you
89
00:09:14,999 --> 00:09:24,170
can also do this with a readily available
Linux tools like snmpget. So before we
90
00:09:24,170 --> 00:09:28,629
will build an exploit, we have a starting
point. So how do we look for for the
91
00:09:28,629 --> 00:09:35,110
crash? So the advisory actually states
that there are nine different vulnerable
92
00:09:35,110 --> 00:09:41,399
management information bases and you only
have to know the read-only community string.
93
00:09:41,399 --> 00:09:50,089
So for the fuzzing to be done I'll be
using Scapy as a tool to as a toolkit to
94
00:09:50,089 --> 00:09:54,310
work with network protocols, and here you
can see that I'm building an object
95
00:09:54,310 --> 00:09:59,160
identifier, a valid object identifier that
references the description field, and then
96
00:09:59,160 --> 00:10:04,921
I'm appending some letters "a" which is 65
in ASCII table. Then I build an IP packet,
97
00:10:04,921 --> 00:10:12,149
I build a UDP packet and an SNMP packet
inside of it with community string public
98
00:10:12,149 --> 00:10:17,320
and object identifier.
So of course this will not trigger the
99
00:10:17,320 --> 00:10:23,589
overflow, because this object identifier
is completely fine. How do we get all the
100
00:10:23,589 --> 00:10:28,670
object identifiers that our router will
respond to? So basically there are two
101
00:10:28,670 --> 00:10:36,230
ways: you can take the firmware and just
extract all the OIDs from it. It's easy to
102
00:10:36,230 --> 00:10:43,670
grab them, they're stored in plain text.
Another way is to actually look at the
103
00:10:43,670 --> 00:10:52,399
vulnerable MIBs and visit the website OID
views and get all object identifiers from
104
00:10:52,399 --> 00:10:59,399
this website. So as a matter of fact the
first crash I had was in ciscoAlpsMIB,
105
00:10:59,399 --> 00:11:08,959
which is kind of related to airplane protocol,
which does not concern us because it's not
106
00:11:08,959 --> 00:11:16,759
a focus of our exploitation.
So the actual overflow was in one of its
107
00:11:16,759 --> 00:11:23,290
object identifiers. So this request this I
actually crashed the router when you
108
00:11:23,290 --> 00:11:30,480
connect to the Cisco router of via a
serial cable you will be and there's a
109
00:11:30,480 --> 00:11:36,480
crash you will be presented with a stack
trace. So we see here that we got a
110
00:11:36,480 --> 00:11:45,890
corrupted program counter, and we also see
the state of registers that we have at the
111
00:11:45,890 --> 00:11:55,270
moment of crash. So here you can see that
we have control of a program counter, it's
112
00:11:55,270 --> 00:12:04,110
called EPC, and also we control the
contents of registers s0, s1, s2, s3, s4,
113
00:12:04,110 --> 00:12:08,160
s5, s6.
Further inspection also provided me with
114
00:12:08,160 --> 00:12:14,959
knowledge that we have 60 spare bytes on
the stack to work with. But before we
115
00:12:14,959 --> 00:12:20,369
build we exploit we have some problems,
issues to be solved.
116
00:12:20,369 --> 00:12:26,149
And that is: yes, we do control the
program counter, but where do we jump to?
117
00:12:26,149 --> 00:12:34,880
Is ASLR on? Can we execute shellcode
directly on the stack? Is stack
118
00:12:34,880 --> 00:12:42,660
executable? If we can place the shellcode
on it, is data caching a problem for us?
119
00:12:42,660 --> 00:12:49,179
And if we launched our shellcode, can we
just bash the code? Is the code section
120
00:12:49,179 --> 00:12:54,060
writable? Is the code integrity check on?
But the most important question is: how
121
00:12:54,060 --> 00:12:59,119
can we return the code flow back to the
SNMP service?
122
00:12:59,119 --> 00:13:07,930
Because IOS is a single binary running in
the memory, and if you have an exception
123
00:13:07,930 --> 00:13:15,019
in any thread of this big binary, the Cisco
device will crash. And if we look at the
124
00:13:15,019 --> 00:13:16,829
advisory, one of the indicators of
125
00:13:16,829 --> 00:13:23,129
compromised Cisco states is device reload,
so exploitation of the vulnerabilities
126
00:13:23,129 --> 00:13:29,499
will cause an affected device to reload.
We will build an exploit we'll try to
127
00:13:29,499 --> 00:13:36,110
build an exploit that will not crash the
SNMP service on it. Before we dive deeper
128
00:13:36,110 --> 00:13:45,149
into the firmware I want to reference
previous researches on this matter. This
129
00:13:45,149 --> 00:13:53,670
is by no means a complete list but these
researchers actually helped me a lot and
130
00:13:53,670 --> 00:14:00,899
seemed interesting and very insightful to
me. You should definitely check them out
131
00:14:00,899 --> 00:14:07,029
so for example "Router Exploitation" by
Felix FX Lindener and "CISCO IOS
132
00:14:07,029 --> 00:14:12,079
SHELLCODE" by George Nosenko is a great
resource for IOS internals and great
133
00:14:12,079 --> 00:14:16,699
reference to how IOS works in terms of
exploitation
134
00:14:16,699 --> 00:14:22,499
and the third resource "How to cook
Cisco" is a great info on exploiting
135
00:14:22,499 --> 00:14:29,189
PowerPC-based Cisco switches and also
great info on bypassing common mechanisms
136
00:14:29,189 --> 00:14:38,129
and exploit prevention stuff in IOS. So
basically if I were to tell you how IOS
137
00:14:38,129 --> 00:14:42,929
works in one slide it's basically a single
binary running in memory. Everything is
138
00:14:42,929 --> 00:14:50,860
statically linked into a single ELF file
which gets loaded on startup, of course
139
00:14:50,860 --> 00:14:57,720
you have no API whatsoever. Everything has
no symbols whatsoever. Yes, there is a
140
00:14:57,720 --> 00:15:03,579
glibc library at the end of the firmware
but it's also kind of hard to use it
141
00:15:03,579 --> 00:15:10,170
because you have so many different
versions of firmware and the offsets jump
142
00:15:10,170 --> 00:15:14,310
and you don't know the exact location of
those functions. So to start with static
143
00:15:14,310 --> 00:15:19,209
analysis you should probably copy the
firmaware from the flash memory of the
144
00:15:19,209 --> 00:15:27,589
router. Use the copy command, it supports
TFTP and FTP protocols so you download
145
00:15:27,589 --> 00:15:32,439
this firmware, the next thing you do is
unpack the firmware. The firmware itself,
146
00:15:32,439 --> 00:15:38,949
when the router starts loading it, has an
initial stop that does the unpacking but
147
00:15:38,949 --> 00:15:43,779
you don't have to reverse engineer that,
you just use binwalk, that will do the
148
00:15:43,779 --> 00:15:53,259
unpacking for you. You load the result of
unpacking with binwalk to IDA Pro, you
149
00:15:53,259 --> 00:15:58,420
have to change the processor type to MIPS
32 big-endian and we know that this is
150
00:15:58,420 --> 00:16:05,139
MIPS, because we saw the registers. These
registers tell us that it was indeed MIPS
151
00:16:05,139 --> 00:16:13,040
architecture. So one thing I want to note,
the actual firmware gets loaded into
152
00:16:13,040 --> 00:16:20,519
address 800F00 but the program counter is
located at address 4 and this is because
153
00:16:20,519 --> 00:16:29,089
IOS when it loaded the firmaware
transfers, I mean maps to memory 2400F00
154
00:16:29,089 --> 00:16:35,120
and this is important because to have
correct cross references in IDA Pro you
155
00:16:35,120 --> 00:16:43,220
have to rebase your program to 4 and after
that you will have all correct string
156
00:16:43,220 --> 00:16:48,929
cross-references. We will have all the
necessary strings and your static analysis
157
00:16:48,929 --> 00:16:56,009
setup will be complete. But in order to
build an exploit it will not suffice to
158
00:16:56,009 --> 00:17:00,740
only have the, you know, IDA Pro loaded
with the firmware with all the cross
159
00:17:00,740 --> 00:17:07,140
references, you probably want to, you
know, set up a debug environment. It is
160
00:17:07,140 --> 00:17:14,689
well known that IOS can be debugged via a
serial port and actually there's a "gdb
161
00:17:14,689 --> 00:17:23,109
kernel" command that is used to start the
internal gdb server, or it was because
162
00:17:23,109 --> 00:17:29,139
functionality was removed in the recent
versions of IOS and you can't really run
163
00:17:29,139 --> 00:17:38,950
the gdb. But nonetheless there's a way to
enable the gdb and this way is to reboot
164
00:17:38,950 --> 00:17:46,389
the device, send an escape sequence to the
serial line, this will bring up the rom
165
00:17:46,389 --> 00:17:52,500
monitor shell so rom monitor is a simple
piece of firmware that gets loaded and run
166
00:17:52,500 --> 00:17:59,720
just before your firmware starts running
and in this ROMMON you can manually boot
167
00:17:59,720 --> 00:18:08,950
your firmware with a flag and which will
launch the whole firmware under gdb. And
168
00:18:08,950 --> 00:18:17,980
after your firmware is loaded, the gdb
will kick in. Now you can't just use your
169
00:18:17,980 --> 00:18:25,919
favorite gdb debugger and Linux and
connect it to IOS via a serial port
170
00:18:25,919 --> 00:18:35,000
because IOS uses a slightly different
subset of commands of gdb protocol. It has
171
00:18:35,000 --> 00:18:43,679
a server-side gdb but the client side
should be accustomed to this gdb server.
172
00:18:43,679 --> 00:18:48,630
Basically there is no publicly and
officially available client-side debugging
173
00:18:48,630 --> 00:18:56,300
tools for IOS and that is because this is
intended for Cisco engineers for to be
174
00:18:56,300 --> 00:19:02,240
done. Although there have been some
efforts from the community to build tools
175
00:19:02,240 --> 00:19:08,750
to debug several versions of routers and
switches with IOS and if you look for ways
176
00:19:08,750 --> 00:19:15,929
to debug Cisco IOS you will find, you most
definitely will find a tutorial that says
177
00:19:15,929 --> 00:19:21,610
that you can actually patch an old version
of gdb that still supports IOS, but it
178
00:19:21,610 --> 00:19:26,120
actually never works because I tried it
and all I could do is read memory, the
179
00:19:26,120 --> 00:19:34,950
stepping, the tracing, it just doesn't
work. So another way is to use a cool tool
180
00:19:34,950 --> 00:19:42,389
by NCC group, it's called IODIDE, it's a
graphical debugger for IOS, it really
181
00:19:42,389 --> 00:19:48,769
works, it's a great tool, but the thing is
it is only, it targets PowerPC
182
00:19:48,769 --> 00:19:54,830
architecture and it has some some problems
you probably have to patch the debugger to
183
00:19:54,830 --> 00:19:58,639
be able to work with it and the third
option, the last resort
184
00:19:58,639 --> 00:20:05,380
is to implement your own debugger for the
router. And to do that you have to know
185
00:20:05,380 --> 00:20:12,370
which commands actually Cisco supports,
and not a lot, so you can basically read
186
00:20:12,370 --> 00:20:18,520
memory and write memory and set and write
registers and the only program counter
187
00:20:18,520 --> 00:20:25,230
control command is a step instruction. So
basically it's kind of easy to implement
188
00:20:25,230 --> 00:20:31,870
such a debugger because all the
information is just sent as a plain text
189
00:20:31,870 --> 00:20:40,820
over a serial cable and appended with a
checksum which is just a CRC. So this way
190
00:20:40,820 --> 00:20:48,179
I was able to, you know, make a quick
Python script using Capstone to be able to
191
00:20:48,179 --> 00:20:55,450
debug IOS, you can inspect registers,
there's a basic breakpoint management, you
192
00:20:55,450 --> 00:21:02,169
just write a special control double word
to be able to break. You can step over a
193
00:21:02,169 --> 00:21:06,789
step over step into and also a good feature is
to be able to dump memory, which we will
194
00:21:06,789 --> 00:21:15,170
use later. So to find the overflow, the
SNMP overflowing the code, how do you do
195
00:21:15,170 --> 00:21:20,840
it? Basically you can follow, since we
have all the string cross-references, you
196
00:21:20,840 --> 00:21:28,960
can follow the strings, that reference
SNMP get requests and just step until the
197
00:21:28,960 --> 00:21:35,139
crash, but a more efficient method is just
to crash the device and start inspecting
198
00:21:35,139 --> 00:21:41,570
the stack after the device is already
crashed. You just have to dump some memory
199
00:21:41,570 --> 00:21:47,180
on the stack and look into the values that
reference the code, some of them will be
200
00:21:47,180 --> 00:21:58,809
return addresses and this will give you a
hint where the crash actually is. So the
201
00:21:58,809 --> 00:22:03,500
actual program counter corruption happens
in the function epilog, I call this
202
00:22:03,500 --> 00:22:12,549
function snmp_stack_overflow, so you can
see here that at the end of a function we
203
00:22:12,549 --> 00:22:18,720
load the values from the stack to
registers $s0 to $s6 and also we load
204
00:22:18,720 --> 00:22:24,610
value into register $ra and this is an
important register, it's called a return
205
00:22:24,610 --> 00:22:31,049
address register and almost every function
in MIPS uses this register to jump back to
206
00:22:31,049 --> 00:22:39,779
its parent function. So basically we have
some space on the stack, but the question
207
00:22:39,779 --> 00:22:47,789
is can we place our shellcode on this on
the stack? And can we execute it? Because,
208
00:22:47,789 --> 00:22:51,789
you know, stack location is
unpredictable, every time you trigger this
209
00:22:51,789 --> 00:22:57,370
vulnerability a separate space on the
stack is allocated and you cannot really
210
00:22:57,370 --> 00:23:04,679
predict it. So, no valid jump to stack
instructions in the firmware like we did
211
00:23:04,679 --> 00:23:11,980
on Intel x86 like jump ESP. No such
instructions in the firmware, but even if
212
00:23:11,980 --> 00:23:19,131
we could find such an instruction, the
address space layout randomization (ALSR)
213
00:23:19,131 --> 00:23:26,070
is on, which means the code section and
data section is based on different offsets
214
00:23:26,070 --> 00:23:31,789
each time we reboot the device, which
means that we can't reliably jump to the
215
00:23:31,789 --> 00:23:39,950
instruction. And also an unfortunate thing
is that data caching is also in place. So,
216
00:23:39,950 --> 00:23:49,309
about ASLR, this is the first first time I
encountered the randomization in IOS.
217
00:23:49,309 --> 00:23:56,120
Previous researchers, that I've been doing
with, they said a lot about diversity of
218
00:23:56,120 --> 00:24:01,919
the firmware. So, basically you had so
many different versions of firmware when
219
00:24:01,919 --> 00:24:07,139
you exploited the Cisco device it couldn't
really reliably jump to any code because
220
00:24:07,139 --> 00:24:11,940
there's so a vast diversity of different
firmware that was built by different
221
00:24:11,940 --> 00:24:17,990
people but here we actually have the stack
address based randomization and the text
222
00:24:17,990 --> 00:24:26,110
section and data section is loaded on
different offsets after each reboot. So,
223
00:24:26,110 --> 00:24:32,929
another thing that really upsets us is
data caching, so when we write our shell
224
00:24:32,929 --> 00:24:38,580
code to stack, we think that it will be on
the stack but what actually happens,
225
00:24:38,580 --> 00:24:43,070
everything gets written into data cache
and when we place our program counter to
226
00:24:43,070 --> 00:24:51,140
the stack we get executing garbage
instructions which results in a crash once
227
00:24:51,140 --> 00:24:58,539
again. So this problem this is basically a
data execution prevention, well it's not
228
00:24:58,539 --> 00:25:06,150
it's a it's a cache but the solution to
this problem is the same as for data
229
00:25:06,150 --> 00:25:12,419
execution prevention and it is return
oriented programming, so but unfortunately
230
00:25:12,419 --> 00:25:21,139
we still have ASLR so we can't really jump
to anything because it's on a random
231
00:25:21,139 --> 00:25:28,580
offset but here the rom monitor, that I
was talking about comes to our rescue. So
232
00:25:28,580 --> 00:25:34,620
this little piece of software that gets
loaded before the actual firmware might
233
00:25:34,620 --> 00:25:40,149
actually help us. So
the first thing we want to find where
234
00:25:40,149 --> 00:25:45,549
this bare-bones firmware is
located and the interesting feature of
235
00:25:45,549 --> 00:25:52,740
this ROMMON shell, it's actually allowing
you to disassemble arbitrary memory parts
236
00:25:52,740 --> 00:25:59,179
and if you target the disassembler at an
invalid address you will get a stack trace
237
00:25:59,179 --> 00:26:06,039
revealing the actual address of the rom
monitor. And what's the most interesting
238
00:26:06,039 --> 00:26:13,070
thing as the rom monitor is located at
bfc0000 and you can dump it using the
239
00:26:13,070 --> 00:26:19,070
debugger or you can just search the
internet for the version and download it.
240
00:26:19,070 --> 00:26:28,620
The most interesting part about this piece
of firmware, is that rom monitor is
241
00:26:28,620 --> 00:26:34,470
located at the same address and it's
persistent across reboots and it's really
242
00:26:34,470 --> 00:26:41,610
great because we can use it for building
ROP chains inside of it. So now we have a
243
00:26:41,610 --> 00:26:49,610
theoretical possibility of circumventing
ASLR, defeating the cache problem. So how
244
00:26:49,610 --> 00:26:56,190
do we build an exploit, so the overview is
as follows: we jump to ROMMON, we initiate
245
00:26:56,190 --> 00:27:02,929
a ROP chain, which makes an arbitrary
write using the code reuse technique and
246
00:27:02,929 --> 00:27:10,669
after that we have to recover the stack
frame to allow the SNMP service to restore
247
00:27:10,669 --> 00:27:16,049
the legitimate code flow. This is really
important because we will be writing only
248
00:27:16,049 --> 00:27:22,470
four bytes and that is not enough for a
full fledged shellcode and if we don't
249
00:27:22,470 --> 00:27:28,529
crash SNMP we can exploit this
vulnerability over and over again, thus
250
00:27:28,529 --> 00:27:33,090
building a shellcode in the memory. So
after we build the shellcode we make a
251
00:27:33,090 --> 00:27:44,289
jump to it. So, here's how it works: we
overflow the stack, we overflow the return
252
00:27:44,289 --> 00:27:51,779
address so it points to rom monitor, we
jump to the rom monitor, then what we do
253
00:27:51,779 --> 00:27:57,680
we actually find a gadget that reuses the
data on our stack to make an arbitrary
254
00:27:57,680 --> 00:28:04,499
four byte write just before the text
section. Then we have to find a gadget
255
00:28:04,499 --> 00:28:11,529
that will recover stack for us so we can
restore the legitimate SNMP execution call
256
00:28:11,529 --> 00:28:19,730
flow. So this is basically an overview of
one cycle of how we write a four byte
257
00:28:19,730 --> 00:28:27,970
double word. Now, a little bit on building
ROP chains, so what is it? what is return
258
00:28:27,970 --> 00:28:38,179
oriented programming? So basically the
idea is to not execute the shellcode
259
00:28:38,179 --> 00:28:45,389
directly but is to use existing
code in the binary to execute your
260
00:28:45,389 --> 00:28:52,200
payload. So you use stack not as a source
of instructions but you use stack as data
261
00:28:52,200 --> 00:28:59,720
for the code that you're reusing. So
basically you change the snippets of code
262
00:28:59,720 --> 00:29:07,720
we call them gadgets and you chain them
together with jump or call instructions
263
00:29:07,720 --> 00:29:17,159
and candidate gadgets has to meet two
requirements: It has to actually execute
264
00:29:17,159 --> 00:29:22,820
our payload and also it also has to
contain instructions that will transfer
265
00:29:22,820 --> 00:29:28,340
execution flow to the next gadget or, if
it's the last gadget it should transfer
266
00:29:28,340 --> 00:29:37,780
execution back to the SNMP service. The
problems with the return oriented approach
267
00:29:37,780 --> 00:29:42,419
is that there is a limited set of gadgets
available, so if you're talking about the
268
00:29:42,419 --> 00:29:46,980
firmware it's around 200 megabytes of code
so there are plenty of different gadgets
269
00:29:46,980 --> 00:29:51,330
there, if we're talking about a rom
monitor it's only 500 kilobytes of code,
270
00:29:51,330 --> 00:29:58,669
so not a lot of code available and the
second major problem is that gadgets,
271
00:29:58,669 --> 00:30:04,549
because most of them are function
epilogues, they modify the stack frame
272
00:30:04,549 --> 00:30:09,409
because they delete the local variables
after they jump back to the parent
273
00:30:09,409 --> 00:30:15,790
function and you have to account for that
because this, my crash, the process you
274
00:30:15,790 --> 00:30:23,720
are exploiting. ROP chains can be
basically forced to do anything but
275
00:30:23,720 --> 00:30:31,419
mostly, most of the times we do arbitrary
memory writes and this actually might lead
276
00:30:31,419 --> 00:30:39,600
to arbitrary code execution. So the idea
for for looking for gadgets is that you
277
00:30:39,600 --> 00:30:46,200
find a gadget that loads data from the
stack into the registers and then you find
278
00:30:46,200 --> 00:30:50,580
a second gadget that works with the data
in the, in those pages for example you
279
00:30:50,580 --> 00:30:58,399
have one register $v0 which contains the
value you want to write and the other
280
00:30:58,399 --> 00:31:09,929
gadget $s0 which has the address you want
to write to. So we actually want to find
281
00:31:09,929 --> 00:31:15,659
gadgets that also load data from stack to
return registers so we can jump to the
282
00:31:15,659 --> 00:31:24,159
next gadget. I don't have to look for
these gadgets manually in IODIDE, in there
283
00:31:24,159 --> 00:31:29,860
are a lot of different tools for building
ROP chains, one of those tools is Ropper
284
00:31:29,860 --> 00:31:32,480
you can find it on GitHub it's a really
handy tool.
285
00:31:32,480 --> 00:31:36,379
You just search for necessary
instructions to build
286
00:31:36,379 --> 00:31:48,669
the necessary ROP chain. So now the last
technical part of how the ROP chains in
287
00:31:48,669 --> 00:31:54,940
this particular exploit work and then
we'll get to the demo. So this is how a
288
00:31:54,940 --> 00:32:02,830
perfectly, you know, healthy stack frame
looks like. So you basically have local
289
00:32:02,830 --> 00:32:07,499
variables on the stack, you have return
adress, you also have a stack frame of
290
00:32:07,499 --> 00:32:13,389
parent functions underneath the stack
frame of our vulnerable function. So when
291
00:32:13,389 --> 00:32:19,679
we overflow the local variables with our
long object identifier here's what
292
00:32:19,679 --> 00:32:27,769
happens: We overflow the local variables
and these variables actually partly get
293
00:32:27,769 --> 00:32:34,210
written to $s0 and $s6 general purpose
registers we also, of course overflow the
294
00:32:34,210 --> 00:32:41,299
return address, which will jump for us to
rom monitor and we also have some 60
295
00:32:41,299 --> 00:32:46,590
bytes, after that we overflow the stack
frame of the next function and we use that
296
00:32:46,590 --> 00:32:54,970
data also for our ROP chain. What we do
here, we take the value of $a0, we control
297
00:32:54,970 --> 00:33:01,919
the value of $a0 as you remember and we
move it to register $v0 and that's for
298
00:33:01,919 --> 00:33:10,039
only solely purpose because there are no
other gadgets in rom monitor that use $s0
299
00:33:10,039 --> 00:33:16,510
as a target register to write data so we
have to use register $v0. After that the
300
00:33:16,510 --> 00:33:22,279
most important part is that we load the
return address from the ROP data too and
301
00:33:22,279 --> 00:33:31,289
also we load the address we will write to
from the ROP data too. So basically right
302
00:33:31,289 --> 00:33:40,539
now after this gadget stops executing we
have $s0 points to a memory we want to
303
00:33:40,539 --> 00:33:49,700
write to and $v0 contains 4 bytes we will
be writing just before the code section.
304
00:33:49,700 --> 00:33:57,649
So the final gadget that is performing the
arbitrary write is the gadget that takes
305
00:33:57,649 --> 00:34:08,190
the value of register $v0 and writes it to
a pointer reference that referenced by
306
00:34:08,190 --> 00:34:15,040
register $s0 and the last thing it does
actually transfers the control back to the
307
00:34:15,040 --> 00:34:22,150
gadget, which will recover the stack for
us. Most important gadgets it allows us to
308
00:34:22,150 --> 00:34:28,139
run the exploit several times, you might
have noticed that the previous gadgets
309
00:34:28,139 --> 00:34:36,460
actually moved the stack pointer 30 bytes
and hacks down them down the
310
00:34:36,460 --> 00:34:38,360
stack and this actually means
311
00:34:38,360 --> 00:34:44,510
that the process that we will return
to will crash if we don't point the stack
312
00:34:44,510 --> 00:34:50,770
pointer just between two stack frames. We
find a gadget that will move the stack
313
00:34:50,770 --> 00:35:00,340
pointer down to 228 bytes in hex, which
will result in a perfectly healthy stack.
314
00:35:00,340 --> 00:35:08,690
Also we load the return address to
register $ra and it points to the parent
315
00:35:08,690 --> 00:35:16,660
function that called our own vulnerable
function so this way we perform an
316
00:35:16,660 --> 00:35:22,850
arbitrary four byte write. We can do this
several times until our shellcode is
317
00:35:22,850 --> 00:35:28,350
actually built, just before the text
section and the final thing we do, we
318
00:35:28,350 --> 00:35:34,850
overflow the stack again and jump to the
shellcode. A few words about the
319
00:35:34,850 --> 00:35:45,910
shellcode: The device I was working with had a
telnet service and it had a password, so I
320
00:35:45,910 --> 00:35:52,150
designed a simple shell code that will
just patch the authentication call flow.
321
00:35:52,150 --> 00:35:58,610
So as you can see here we have a function
"login password check" and a result which
322
00:35:58,610 --> 00:36:09,170
is in $v0 register is checked whether the
authentication was successful or not. We
323
00:36:09,170 --> 00:36:13,700
can build a shell code which which will
just patch this instruction which checks
324
00:36:13,700 --> 00:36:19,900
"login password check" and it will allow
us to make a credential list
325
00:36:19,900 --> 00:36:29,780
authentication against telnet service. So
what it does: basically the shell code
326
00:36:29,780 --> 00:36:35,780
inspects the stack and the return address
in it to calculate the ASLR offset
327
00:36:35,780 --> 00:36:43,170
because, of course the ASLR is on for the
code section and we want to patch
328
00:36:43,170 --> 00:36:52,470
something in it and after that it writes a
0, which is a nop instruction in MIPS, to
329
00:36:52,470 --> 00:37:00,770
a call that checks for password for telnet
and also for enable password and then it
330
00:37:00,770 --> 00:37:10,610
just jumps back to SNMP service. So now
the long-awaited demo. Let's see if I can
331
00:37:10,610 --> 00:37:42,480
make it a live demo. All righty, so here
we have the serial connection to the
332
00:37:42,480 --> 00:37:52,820
device, you can see we have a shell. So
what we do now, we inspect the password on
333
00:37:52,820 --> 00:37:56,460
the telnet service to make sure it's
working as intended. So we see that bad
334
00:37:56,460 --> 00:38:03,700
passwords. We don't know the valid
password for the device, what we do now is
335
00:38:03,700 --> 00:38:16,050
we launch the actual exploit, as
parameters it takes the host, community
336
00:38:16,050 --> 00:38:26,200
and shell code in hex. So this is the shell
337
00:38:26,200 --> 00:38:41,300
code I was talking about that patches the
code flow in authentication. So let's
338
00:38:41,300 --> 00:38:53,580
write sudo. So here you see that we
initiate writing the four byte sequences
339
00:38:53,580 --> 00:39:02,490
into the text section. Basically this
writes the shell code into the memory. So
340
00:39:02,490 --> 00:39:17,180
after the exploit finishes this, we just
have to jump to the shell code. So let's
341
00:39:17,180 --> 00:39:57,530
see. Please do not crash. So, yes. So back
to the slides. And of course you can build
342
00:39:57,530 --> 00:40:02,500
a shell code that will unset this behavior
and patch the process back to enable the
343
00:40:02,500 --> 00:40:07,940
password and on the side notes how
reliably can you exploit this
344
00:40:07,940 --> 00:40:15,220
vulnerability? So, of course the SNMP
public community will leak you the version
345
00:40:15,220 --> 00:40:20,560
of the particular router but it does not
leak you the version of ROMMON and we're
346
00:40:20,560 --> 00:40:29,380
basically constructing ROP chains in the
rom monitor. So actually you have not that
347
00:40:29,380 --> 00:40:34,080
many versions of rom monitor available.
You have only five if we're talking about
348
00:40:34,080 --> 00:40:41,500
2800 router. So the worst-case scenario is
just you crash it four times. It's not
349
00:40:41,500 --> 00:40:46,410
like you have to crash it four thousand
times to you know beat the ASLR but
350
00:40:46,410 --> 00:40:52,340
there's a second option which is
interesting. ROMMON is designed to be
351
00:40:52,340 --> 00:40:57,590
upgraded, so basically a system
administrator can download a new version
352
00:40:57,590 --> 00:41:02,800
and update it but the thing is that read-
only region that contains the stock ROMMON
353
00:41:02,800 --> 00:41:10,300
is always in place and it is always at the
same offset, so even if you updated the
354
00:41:10,300 --> 00:41:15,760
rom monitor, the read-only version of it,
the old version that always been there,
355
00:41:15,760 --> 00:41:24,650
will always be at bfc00000. So basically
the assumption is that all the devices
356
00:41:24,650 --> 00:41:29,031
manufactured at the same time and place,
they will have the same read-only rom
357
00:41:29,031 --> 00:41:38,030
monitor, you can query your serial number
of your router using snmpget. So for
358
00:41:38,030 --> 00:41:44,760
example my lab router is manufactured in
the year of 2008 and Czech Republic. So
359
00:41:44,760 --> 00:41:51,720
and it has the following version of rom
monitor. So guys to, you know, to
360
00:41:51,720 --> 00:41:57,210
summarise about all this, do not leave
default credentials on external networks.
361
00:41:57,210 --> 00:42:02,730
So public communities are not designed to
be placed on external networks
362
00:42:02,730 --> 00:42:09,990
for the Shodan to find it. Take care of
what you expose on the external networks.
363
00:42:09,990 --> 00:42:17,270
Of course patch your devices and watch
for the end-of-life announcement by
364
00:42:17,270 --> 00:42:28,200
Cisco. Sorry? Sure why not? Alright guys
thank you so much for your attention
365
00:42:28,200 --> 00:42:40,510
applause
thanks for having me.
366
00:42:40,510 --> 00:42:42,600
Herald: I suppose there are some questions
367
00:42:42,600 --> 00:42:50,250
in this audience, please take a microphone
if you can. no one on the internet? They
368
00:42:50,250 --> 00:43:00,590
are flabbergasted there it seems.
Microphone number one.
369
00:43:00,590 --> 00:43:07,110
Mic 1: Yeah, I'm a random network admin
and I know that people tend to use the
370
00:43:07,110 --> 00:43:13,320
same SNMP community on many of their
routers. My view is that basically if you
371
00:43:13,320 --> 00:43:19,171
can get access to read only on those
routers you will be able to hijack that or
372
00:43:19,171 --> 00:43:25,140
like use the same principle. So basically
don't use the same SNMP community on all
373
00:43:25,140 --> 00:43:29,910
your devices that would be also something.
Artem Kondratenko: the main thing is to
374
00:43:29,910 --> 00:43:34,800
update your routers because it's a patched
vulnerability, the patch was released in
375
00:43:34,800 --> 00:43:42,860
September of 2017 but if you tend to use
the end-of-life products like router 2800
376
00:43:42,860 --> 00:43:48,940
you probably should use a strong community
strength for it.
377
00:43:48,940 --> 00:43:55,040
Herald: Thank you. Someone else having a
question there? Yes someone on the
378
00:43:55,040 --> 00:44:00,390
internet is alive. It's alive.
Signal Angel: Let's try it. Yeah now I've
379
00:44:00,390 --> 00:44:05,050
actually got a microphone. The Internet is
asking how much time did you put into this
380
00:44:05,050 --> 00:44:08,830
whole project?
Artem Kondratenko: While working on this
381
00:44:08,830 --> 00:44:19,070
exploit consumed around I'd say four
weeks. Four weeks from the discovering the
382
00:44:19,070 --> 00:44:26,320
device on the external network to the
final exploit. Yes. Thank you.
383
00:44:26,320 --> 00:44:31,460
Herald: I have a question maybe for you as
well. Is that you you're as well a lot of
384
00:44:31,460 --> 00:44:36,070
you have lots of volunteers who are
working with you as well in researching
385
00:44:36,070 --> 00:44:38,440
these exploits or?
Artem Kondratenko: Volunteers?
386
00:44:38,440 --> 00:44:41,730
Herald: Yeah I don't know.
Artem Kondratenko: No, actually we don't
387
00:44:41,730 --> 00:44:44,260
have any volunteers, this is all part of
my work.
388
00:44:44,260 --> 00:44:52,300
Herald: Okay. Thank you very much for
thank you very much for this in its really
389
00:44:52,300 --> 00:44:56,420
revealing lecture, if someone wants to...
Artem Kondratenko: Oh I just forgot to
390
00:44:56,420 --> 00:45:02,460
say, is my mic on? okay so the actual
proof of concept and the debugger will be
391
00:45:02,460 --> 00:45:07,570
released in a few days, so the Python
script with the capstone and the actual
392
00:45:07,570 --> 00:45:12,070
proof of concept I'll publish it and in a
week or so.
393
00:45:12,070 --> 00:45:16,039
Herald: okay thank you.
394
00:45:16,039 --> 00:45:20,550
34c3 outro
395
00:45:20,550 --> 00:45:36,741
subtitles created by c3subtitles.de
in the year 2018. Join, and help us!