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:36,741
*34c3 outro*
