Return to Video

34C3 - 1-day exploit development for Cisco IOS

  • 0:00 - 0:15
    34c3 intro
  • 0:15 - 0:30
    Herald: All right, next lecture here is
    from Artem. Next to the fact that these,
  • 0:30 - 0:39
    how would I spell it, earning a nice
    amount of money probably at a lab that's
  • 0:39 - 0:47
    quite renown in the world as Kaspersky and
    from that point on he's not just looking
  • 0:47 - 0:53
    in this lecture to exploit a development
    for Cisco stuff we all suffered from this
  • 0:53 - 0:58
    last year or we all heard about it and
    don't know the impact maybe, but he's
  • 0:58 - 1:05
    going to explain us the work he did on
    that field so please can I ask your warm
  • 1:05 - 1:14
    welcoming applause for Artem Kondratenko,
    do you, okay good, please give him a warm
  • 1:14 - 1:22
    applause and start.
    applause
  • 1:22 - 1:26
    Artem Kondratenko: Hello everyone, so
    excited to finally be able to attend Chaos
  • 1:26 - 1:32
    Communication Congress. Very happy to see
    y'all. So without further ado let's jump
  • 1:32 - 1:38
    into some practical IOS exploitation. So a
    few words about myself, my name is Artem,
  • 1:38 - 1:44
    I do stuff, mostly security related stuff
    but mostly my areas of expertise are
  • 1:44 - 1:49
    penetration tests, both internal external
    and also do research in my free time and
  • 1:49 - 1:54
    get a bug bounty here and there and this
    talk is actually kind of a continuation of
  • 1:54 - 2:00
    my talk this summer at Def Con about Cisco
    Catalyst exploitation.
  • 2:00 - 2:05
    So for those of you who are out of
    context, let's recap what happened earlier
  • 2:05 - 2:14
    this year. So year 2017 was reaching
    vulnerabilities for Cisco IOS devices. So
  • 2:14 - 2:20
    we had at least three major advisories for
    Cisco IOS that represented three remote
  • 2:20 - 2:24
    code execution vulnerabilities.
    So the first one is vulnerability in
  • 2:24 - 2:31
    cluster management protocol which resulted
    in unauthenticated remote code
  • 2:31 - 2:37
    execution via telnet, second one is SNMP
    overflow and the DHCP remote code
  • 2:37 - 2:40
    execution.
    In this lecture I'm gonna be talking
  • 2:40 - 2:47
    about two of those vulnerabilities because
    DHCP RCE is yet to be researched. So
  • 2:47 - 2:52
    hopefully by the end of this talk I'm
    going to be able to show you a live demo
  • 2:52 - 2:57
    of exploiting the SNMP service in Cisco
    IOS.
  • 2:57 - 3:06
    So but first what happened earlier: So on
    March 26, 2017 we had a major advisory from
  • 3:06 - 3:11
    Cisco that announcing that hundreds of
    models of different switches are
  • 3:11 - 3:15
    vulnerable to remote code execution
    vulnerability. No public code, no public
  • 3:15 - 3:21
    exploit was available and no exploitation
    in the wild. So it was critical and main
  • 3:21 - 3:24
    points of the vulnerability were as
    follow:
  • 3:24 - 3:31
    So Cisco switches can be clustered, and
    there's a cluster management protocol
  • 3:31 - 3:36
    built on top of telnet, and this
    vulnerability is a result of actually two
  • 3:36 - 3:44
    errors, a logic error and a binary error.
    So the telnet options get parsed
  • 3:44 - 3:50
    regardless whether the switch is in
    cluster mode or not and the incorrect
  • 3:50 - 3:57
    processing of this cluster management
    protocol options result in overflow. So
  • 3:57 - 4:01
    what is interesting about this
    vulnerability that actually the source of
  • 4:01 - 4:06
    research for Cisco guys was another
    internal research. But the "Vault 7" leak
  • 4:06 - 4:13
    that happened in March this year so many
    hacking techniques and tools were released
  • 4:13 - 4:20
    to public by WikiLeaks, and among many
    vendors that were affected was Cisco
  • 4:20 - 4:25
    Systems.
    So basically except for the advisory you
  • 4:25 - 4:30
    could go to WikiLeaks and read about this
    potential exploitation technique for Cisco
  • 4:30 - 4:35
    Catalyst. So basically these were notes of
    an engineer who was testing the actual
  • 4:35 - 4:44
    exploit, there were no actual exploit in
    the leak. So basically this worked as
  • 4:44 - 4:49
    follows: there was two modes of
    interaction, so for example an attacker
  • 4:49 - 4:55
    could connect to the telnet, overflow the
    service and be presented with a privileged
  • 4:55 - 5:03
    15 shell. The other mode of operation was
    the … is to set for all the subsequent
  • 5:03 - 5:09
    … connections to the telnet, there
    will be … without credentials so I
  • 5:09 - 5:15
    did. We discover this exploit, full
    research was presented at DEFCON 25. I was
  • 5:15 - 5:21
    targeting system catalyst 2960 as a target
    switch. I also described a PowerPC
  • 5:21 - 5:25
    platform exploitation and the way you can
    debug it.
  • 5:25 - 5:31
    You can look at my blog post about
    exploiting this service, and also the
  • 5:31 - 5:38
    proof accounts of exploit on my github
    page. But today I want to talk about
  • 5:38 - 5:42
    something else, about another
    vulnerability that was announced this year
  • 5:42 - 5:49
    about SNMP remote code execution.
    So the actual motivation behind this
  • 5:49 - 5:56
    research was that I was conducting an
    external pentest, and it was revealed an
  • 5:56 - 6:01
    nmap scan revealed that a Cisco router
    where the default community string was
  • 6:01 - 6:07
    available. So the goal was to get access
    to the internal network.
  • 6:07 - 6:13
    So the actual advisory said that the
    attacker needs a read-only community
  • 6:13 - 6:20
    string to gain remote code execution on
    the device. The target router was a 2800
  • 6:20 - 6:27
    integrated services router, which is a
    very common device on the networks.
  • 6:27 - 6:34
    So the technical specs for it is it's a
    it has a MIPS big endian architecture, you
  • 6:34 - 6:40
    don't have any client debugging tools for
    it available, and it's interesting in that
  • 6:40 - 6:47
    sense that the firmware is relatively new
    for this router, and it might be
  • 6:47 - 6:53
    interesting to look at the defensive end
    exploit prevention mechanisms employed by
  • 6:53 - 6:59
    Cisco IOS. When I say relatively new is
    the interesting thing is that this device
  • 6:59 - 7:04
    is actually end of support, it's not
    supported. So the last patch for it was
  • 7:04 - 7:12
    came out at 2016, and to remind you the
    advisory for SNMP overflow appeared in
  • 7:12 - 7:19
    2017, in June 2017, but nonetheless this
    is still widely used device.
  • 7:19 - 7:28
    If you search for SNMP banner on Shodan,
    you will find at least 3000 devices with
  • 7:28 - 7:38
    SNMP service available with default public
    string. So this devices are all supposedly
  • 7:38 - 7:44
    vulnerable to SNMP overflow. And the
    question is whether we can build a mount
  • 7:44 - 7:49
    code execution exploit for it. So since
    we're going to be exploiting SME protocol,
  • 7:49 - 7:54
    let's make a quick quick recap of how it
    works, just light touch.
  • 7:54 - 8:02
    So SNMP comes with several abbreviations
    like MIB, which stands for management
  • 8:02 - 8:08
    information base, and is kind of a
    collection of objects that can be
  • 8:08 - 8:13
    monitored from the SNMP manager. And so a
    management information base actually
  • 8:13 - 8:21
    consists of object identifiers. And as an
    example: you all know that printers
  • 8:21 - 8:26
    usually use SNMP, For example if there is
    a certain level of ink in the cartridge,
  • 8:26 - 8:32
    you can query the SNMP service on this
    device for the percentage of ink left. So
  • 8:32 - 8:39
    that's a kind of example how it works.
    Management information base looks like a
  • 8:39 - 8:42
    tree.
    So you have your base element at the top
  • 8:42 - 8:48
    and your leaf elements, So all these
    elements represent an object that could be
  • 8:48 - 8:54
    queried. We're going to be looking at get
    requests. And that is why the advisory
  • 8:54 - 8:58
    states that for their vulnerability to be
    triggered you only have to know the read-
  • 8:58 - 9:03
    only community string. So it's a
    relatively simple protocol, you just
  • 9:03 - 9:08
    supply the object identifier you're
    querying and you'll get back the result.
  • 9:08 - 9:15
    So here for example we get the router
    version, the description field. And you
  • 9:15 - 9:24
    can also do this with a readily available
    Linux tools like snmpget. So before we
  • 9:24 - 9:29
    will build an exploit, we have a starting
    point. So how do we look for for the
  • 9:29 - 9:35
    crash? So the advisory actually states
    that there are nine different vulnerable
  • 9:35 - 9:41
    management information bases and you only
    have to know the read-only community string.
  • 9:41 - 9:50
    So for the fuzzing to be done I'll be
    using Scapy as a tool to as a toolkit to
  • 9:50 - 9:54
    work with network protocols, and here you
    can see that I'm building an object
  • 9:54 - 9:59
    identifier, a valid object identifier that
    references the description field, and then
  • 9:59 - 10:05
    I'm appending some letters "a" which is 65
    in ASCII table. Then I build an IP packet,
  • 10:05 - 10:12
    I build a UDP packet and an SNMP packet
    inside of it with community string public
  • 10:12 - 10:17
    and object identifier.
    So of course this will not trigger the
  • 10:17 - 10:24
    overflow, because this object identifier
    is completely fine. How do we get all the
  • 10:24 - 10:29
    object identifiers that our router will
    respond to? So basically there are two
  • 10:29 - 10:36
    ways: you can take the firmware and just
    extract all the OIDs from it. It's easy to
  • 10:36 - 10:44
    grab them, they're stored in plain text.
    Another way is to actually look at the
  • 10:44 - 10:52
    vulnerable MIBs and visit the website OID
    views and get all object identifiers from
  • 10:52 - 10:59
    this website. So as a matter of fact the
    first crash I had was in ciscoAlpsMIB,
  • 10:59 - 11:09
    which is kind of related to airplane protocol,
    which does not concern us because it's not
  • 11:09 - 11:17
    a focus of our exploitation.
    So the actual overflow was in one of its
  • 11:17 - 11:23
    object identifiers. So this request this I
    actually crashed the router when you
  • 11:23 - 11:30
    connect to the Cisco router of via a
    serial cable you will be and there's a
  • 11:30 - 11:36
    crash you will be presented with a stack
    trace. So we see here that we got a
  • 11:36 - 11:46
    corrupted program counter, and we also see
    the state of registers that we have at the
  • 11:46 - 11:55
    moment of crash. So here you can see that
    we have control of a program counter, it's
  • 11:55 - 12:04
    called EPC, and also we control the
    contents of registers s0, s1, s2, s3, s4,
  • 12:04 - 12:08
    s5, s6.
    Further inspection also provided me with
  • 12:08 - 12:15
    knowledge that we have 60 spare bytes on
    the stack to work with. But before we
  • 12:15 - 12:20
    build we exploit we have some problems,
    issues to be solved.
  • 12:20 - 12:26
    And that is: yes, we do control the
    program counter, but where do we jump to?
  • 12:26 - 12:35
    Is ASLR on? Can we execute shellcode
    directly on the stack? Is stack
  • 12:35 - 12:43
    executable? If we can place the shellcode
    on it, is data caching a problem for us?
  • 12:43 - 12:49
    And if we launched our shellcode, can we
    just bash the code? Is the code section
  • 12:49 - 12:54
    writable? Is the code integrity check on?
    But the most important question is: how
  • 12:54 - 12:59
    can we return the code flow back to the
    SNMP service?
  • 12:59 - 13:08
    Because IOS is a single binary running in
    the memory, and if you have an exception
  • 13:08 - 13:15
    in any thread of this big binary, the Cisco
    device will crash. And if we look at the
  • 13:15 - 13:17
    advisory, one of the indicators of
  • 13:17 - 13:23
    compromised Cisco states is device reload,
    so exploitation of the vulnerabilities
  • 13:23 - 13:29
    will cause an affected device to reload.
    We will build an exploit we'll try to
  • 13:29 - 13:36
    build an exploit that will not crash the
    SNMP service on it. Before we dive deeper
  • 13:36 - 13:45
    into the firmware I want to reference
    previous researches on this matter. This
  • 13:45 - 13:54
    is by no means a complete list but these
    researchers actually helped me a lot and
  • 13:54 - 14:01
    seemed interesting and very insightful to
    me. You should definitely check them out
  • 14:01 - 14:07
    so for example "Router Exploitation" by
    Felix FX Lindener and "CISCO IOS
  • 14:07 - 14:12
    SHELLCODE" by George Nosenko is a great
    resource for IOS internals and great
  • 14:12 - 14:17
    reference to how IOS works in terms of
    exploitation
  • 14:17 - 14:22
    and the third resource "How to cook
    Cisco" is a great info on exploiting
  • 14:22 - 14:29
    PowerPC-based Cisco switches and also
    great info on bypassing common mechanisms
  • 14:29 - 14:38
    and exploit prevention stuff in IOS. So
    basically if I were to tell you how IOS
  • 14:38 - 14:43
    works in one slide it's basically a single
    binary running in memory. Everything is
  • 14:43 - 14:51
    statically linked into a single ELF file
    which gets loaded on startup, of course
  • 14:51 - 14:58
    you have no API whatsoever. Everything has
    no symbols whatsoever. Yes, there is a
  • 14:58 - 15:04
    glibc library at the end of the firmware
    but it's also kind of hard to use it
  • 15:04 - 15:10
    because you have so many different
    versions of firmware and the offsets jump
  • 15:10 - 15:14
    and you don't know the exact location of
    those functions. So to start with static
  • 15:14 - 15:19
    analysis you should probably copy the
    firmaware from the flash memory of the
  • 15:19 - 15:28
    router. Use the copy command, it supports
    TFTP and FTP protocols so you download
  • 15:28 - 15:32
    this firmware, the next thing you do is
    unpack the firmware. The firmware itself,
  • 15:32 - 15:39
    when the router starts loading it, has an
    initial stop that does the unpacking but
  • 15:39 - 15:44
    you don't have to reverse engineer that,
    you just use binwalk, that will do the
  • 15:44 - 15:53
    unpacking for you. You load the result of
    unpacking with binwalk to IDA Pro, you
  • 15:53 - 15:58
    have to change the processor type to MIPS
    32 big-endian and we know that this is
  • 15:58 - 16:05
    MIPS, because we saw the registers. These
    registers tell us that it was indeed MIPS
  • 16:05 - 16:13
    architecture. So one thing I want to note,
    the actual firmware gets loaded into
  • 16:13 - 16:21
    address 800F00 but the program counter is
    located at address 4 and this is because
  • 16:21 - 16:29
    IOS when it loaded the firmaware
    transfers, I mean maps to memory 2400F00
  • 16:29 - 16:35
    and this is important because to have
    correct cross references in IDA Pro you
  • 16:35 - 16:43
    have to rebase your program to 4 and after
    that you will have all correct string
  • 16:43 - 16:49
    cross-references. We will have all the
    necessary strings and your static analysis
  • 16:49 - 16:56
    setup will be complete. But in order to
    build an exploit it will not suffice to
  • 16:56 - 17:01
    only have the, you know, IDA Pro loaded
    with the firmware with all the cross
  • 17:01 - 17:07
    references, you probably want to, you
    know, set up a debug environment. It is
  • 17:07 - 17:15
    well known that IOS can be debugged via a
    serial port and actually there's a "gdb
  • 17:15 - 17:23
    kernel" command that is used to start the
    internal gdb server, or it was because
  • 17:23 - 17:29
    functionality was removed in the recent
    versions of IOS and you can't really run
  • 17:29 - 17:39
    the gdb. But nonetheless there's a way to
    enable the gdb and this way is to reboot
  • 17:39 - 17:46
    the device, send an escape sequence to the
    serial line, this will bring up the rom
  • 17:46 - 17:52
    monitor shell so rom monitor is a simple
    piece of firmware that gets loaded and run
  • 17:52 - 18:00
    just before your firmware starts running
    and in this ROMMON you can manually boot
  • 18:00 - 18:09
    your firmware with a flag and which will
    launch the whole firmware under gdb. And
  • 18:09 - 18:18
    after your firmware is loaded, the gdb
    will kick in. Now you can't just use your
  • 18:18 - 18:26
    favorite gdb debugger and Linux and
    connect it to IOS via a serial port
  • 18:26 - 18:35
    because IOS uses a slightly different
    subset of commands of gdb protocol. It has
  • 18:35 - 18:44
    a server-side gdb but the client side
    should be accustomed to this gdb server.
  • 18:44 - 18:49
    Basically there is no publicly and
    officially available client-side debugging
  • 18:49 - 18:56
    tools for IOS and that is because this is
    intended for Cisco engineers for to be
  • 18:56 - 19:02
    done. Although there have been some
    efforts from the community to build tools
  • 19:02 - 19:09
    to debug several versions of routers and
    switches with IOS and if you look for ways
  • 19:09 - 19:16
    to debug Cisco IOS you will find, you most
    definitely will find a tutorial that says
  • 19:16 - 19:22
    that you can actually patch an old version
    of gdb that still supports IOS, but it
  • 19:22 - 19:26
    actually never works because I tried it
    and all I could do is read memory, the
  • 19:26 - 19:35
    stepping, the tracing, it just doesn't
    work. So another way is to use a cool tool
  • 19:35 - 19:42
    by NCC group, it's called IODIDE, it's a
    graphical debugger for IOS, it really
  • 19:42 - 19:49
    works, it's a great tool, but the thing is
    it is only, it targets PowerPC
  • 19:49 - 19:55
    architecture and it has some some problems
    you probably have to patch the debugger to
  • 19:55 - 19:59
    be able to work with it and the third
    option, the last resort
  • 19:59 - 20:05
    is to implement your own debugger for the
    router. And to do that you have to know
  • 20:05 - 20:12
    which commands actually Cisco supports,
    and not a lot, so you can basically read
  • 20:12 - 20:19
    memory and write memory and set and write
    registers and the only program counter
  • 20:19 - 20:25
    control command is a step instruction. So
    basically it's kind of easy to implement
  • 20:25 - 20:32
    such a debugger because all the
    information is just sent as a plain text
  • 20:32 - 20:41
    over a serial cable and appended with a
    checksum which is just a CRC. So this way
  • 20:41 - 20:48
    I was able to, you know, make a quick
    Python script using Capstone to be able to
  • 20:48 - 20:55
    debug IOS, you can inspect registers,
    there's a basic breakpoint management, you
  • 20:55 - 21:02
    just write a special control double word
    to be able to break. You can step over a
  • 21:02 - 21:07
    step over step into and also a good feature is
    to be able to dump memory, which we will
  • 21:07 - 21:15
    use later. So to find the overflow, the
    SNMP overflowing the code, how do you do
  • 21:15 - 21:21
    it? Basically you can follow, since we
    have all the string cross-references, you
  • 21:21 - 21:29
    can follow the strings, that reference
    SNMP get requests and just step until the
  • 21:29 - 21:35
    crash, but a more efficient method is just
    to crash the device and start inspecting
  • 21:35 - 21:42
    the stack after the device is already
    crashed. You just have to dump some memory
  • 21:42 - 21:47
    on the stack and look into the values that
    reference the code, some of them will be
  • 21:47 - 21:59
    return addresses and this will give you a
    hint where the crash actually is. So the
  • 21:59 - 22:04
    actual program counter corruption happens
    in the function epilog, I call this
  • 22:04 - 22:13
    function snmp_stack_overflow, so you can
    see here that at the end of a function we
  • 22:13 - 22:19
    load the values from the stack to
    registers $s0 to $s6 and also we load
  • 22:19 - 22:25
    value into register $ra and this is an
    important register, it's called a return
  • 22:25 - 22:31
    address register and almost every function
    in MIPS uses this register to jump back to
  • 22:31 - 22:40
    its parent function. So basically we have
    some space on the stack, but the question
  • 22:40 - 22:48
    is can we place our shellcode on this on
    the stack? And can we execute it? Because,
  • 22:48 - 22:52
    you know, stack location is
    unpredictable, every time you trigger this
  • 22:52 - 22:57
    vulnerability a separate space on the
    stack is allocated and you cannot really
  • 22:57 - 23:05
    predict it. So, no valid jump to stack
    instructions in the firmware like we did
  • 23:05 - 23:12
    on Intel x86 like jump ESP. No such
    instructions in the firmware, but even if
  • 23:12 - 23:19
    we could find such an instruction, the
    address space layout randomization (ALSR)
  • 23:19 - 23:26
    is on, which means the code section and
    data section is based on different offsets
  • 23:26 - 23:32
    each time we reboot the device, which
    means that we can't reliably jump to the
  • 23:32 - 23:40
    instruction. And also an unfortunate thing
    is that data caching is also in place. So,
  • 23:40 - 23:49
    about ASLR, this is the first first time I
    encountered the randomization in IOS.
  • 23:49 - 23:56
    Previous researchers, that I've been doing
    with, they said a lot about diversity of
  • 23:56 - 24:02
    the firmware. So, basically you had so
    many different versions of firmware when
  • 24:02 - 24:07
    you exploited the Cisco device it couldn't
    really reliably jump to any code because
  • 24:07 - 24:12
    there's so a vast diversity of different
    firmware that was built by different
  • 24:12 - 24:18
    people but here we actually have the stack
    address based randomization and the text
  • 24:18 - 24:26
    section and data section is loaded on
    different offsets after each reboot. So,
  • 24:26 - 24:33
    another thing that really upsets us is
    data caching, so when we write our shell
  • 24:33 - 24:39
    code to stack, we think that it will be on
    the stack but what actually happens,
  • 24:39 - 24:43
    everything gets written into data cache
    and when we place our program counter to
  • 24:43 - 24:51
    the stack we get executing garbage
    instructions which results in a crash once
  • 24:51 - 24:59
    again. So this problem this is basically a
    data execution prevention, well it's not
  • 24:59 - 25:06
    it's a it's a cache but the solution to
    this problem is the same as for data
  • 25:06 - 25:12
    execution prevention and it is return
    oriented programming, so but unfortunately
  • 25:12 - 25:21
    we still have ASLR so we can't really jump
    to anything because it's on a random
  • 25:21 - 25:29
    offset but here the rom monitor, that I
    was talking about comes to our rescue. So
  • 25:29 - 25:35
    this little piece of software that gets
    loaded before the actual firmware might
  • 25:35 - 25:40
    actually help us. So
    the first thing we want to find where
  • 25:40 - 25:46
    this bare-bones firmware is
    located and the interesting feature of
  • 25:46 - 25:53
    this ROMMON shell, it's actually allowing
    you to disassemble arbitrary memory parts
  • 25:53 - 25:59
    and if you target the disassembler at an
    invalid address you will get a stack trace
  • 25:59 - 26:06
    revealing the actual address of the rom
    monitor. And what's the most interesting
  • 26:06 - 26:13
    thing as the rom monitor is located at
    bfc0000 and you can dump it using the
  • 26:13 - 26:19
    debugger or you can just search the
    internet for the version and download it.
  • 26:19 - 26:29
    The most interesting part about this piece
    of firmware, is that rom monitor is
  • 26:29 - 26:34
    located at the same address and it's
    persistent across reboots and it's really
  • 26:34 - 26:42
    great because we can use it for building
    ROP chains inside of it. So now we have a
  • 26:42 - 26:50
    theoretical possibility of circumventing
    ASLR, defeating the cache problem. So how
  • 26:50 - 26:56
    do we build an exploit, so the overview is
    as follows: we jump to ROMMON, we initiate
  • 26:56 - 27:03
    a ROP chain, which makes an arbitrary
    write using the code reuse technique and
  • 27:03 - 27:11
    after that we have to recover the stack
    frame to allow the SNMP service to restore
  • 27:11 - 27:16
    the legitimate code flow. This is really
    important because we will be writing only
  • 27:16 - 27:22
    four bytes and that is not enough for a
    full fledged shellcode and if we don't
  • 27:22 - 27:29
    crash SNMP we can exploit this
    vulnerability over and over again, thus
  • 27:29 - 27:33
    building a shellcode in the memory. So
    after we build the shellcode we make a
  • 27:33 - 27:44
    jump to it. So, here's how it works: we
    overflow the stack, we overflow the return
  • 27:44 - 27:52
    address so it points to rom monitor, we
    jump to the rom monitor, then what we do
  • 27:52 - 27:58
    we actually find a gadget that reuses the
    data on our stack to make an arbitrary
  • 27:58 - 28:04
    four byte write just before the text
    section. Then we have to find a gadget
  • 28:04 - 28:12
    that will recover stack for us so we can
    restore the legitimate SNMP execution call
  • 28:12 - 28:20
    flow. So this is basically an overview of
    one cycle of how we write a four byte
  • 28:20 - 28:28
    double word. Now, a little bit on building
    ROP chains, so what is it? what is return
  • 28:28 - 28:38
    oriented programming? So basically the
    idea is to not execute the shellcode
  • 28:38 - 28:45
    directly but is to use existing
    code in the binary to execute your
  • 28:45 - 28:52
    payload. So you use stack not as a source
    of instructions but you use stack as data
  • 28:52 - 29:00
    for the code that you're reusing. So
    basically you change the snippets of code
  • 29:00 - 29:08
    we call them gadgets and you chain them
    together with jump or call instructions
  • 29:08 - 29:17
    and candidate gadgets has to meet two
    requirements: It has to actually execute
  • 29:17 - 29:23
    our payload and also it also has to
    contain instructions that will transfer
  • 29:23 - 29:28
    execution flow to the next gadget or, if
    it's the last gadget it should transfer
  • 29:28 - 29:38
    execution back to the SNMP service. The
    problems with the return oriented approach
  • 29:38 - 29:42
    is that there is a limited set of gadgets
    available, so if you're talking about the
  • 29:42 - 29:47
    firmware it's around 200 megabytes of code
    so there are plenty of different gadgets
  • 29:47 - 29:51
    there, if we're talking about a rom
    monitor it's only 500 kilobytes of code,
  • 29:51 - 29:59
    so not a lot of code available and the
    second major problem is that gadgets,
  • 29:59 - 30:05
    because most of them are function
    epilogues, they modify the stack frame
  • 30:05 - 30:09
    because they delete the local variables
    after they jump back to the parent
  • 30:09 - 30:16
    function and you have to account for that
    because this, my crash, the process you
  • 30:16 - 30:24
    are exploiting. ROP chains can be
    basically forced to do anything but
  • 30:24 - 30:31
    mostly, most of the times we do arbitrary
    memory writes and this actually might lead
  • 30:31 - 30:40
    to arbitrary code execution. So the idea
    for for looking for gadgets is that you
  • 30:40 - 30:46
    find a gadget that loads data from the
    stack into the registers and then you find
  • 30:46 - 30:51
    a second gadget that works with the data
    in the, in those pages for example you
  • 30:51 - 30:58
    have one register $v0 which contains the
    value you want to write and the other
  • 30:58 - 31:10
    gadget $s0 which has the address you want
    to write to. So we actually want to find
  • 31:10 - 31:16
    gadgets that also load data from stack to
    return registers so we can jump to the
  • 31:16 - 31:24
    next gadget. I don't have to look for
    these gadgets manually in IODIDE, in there
  • 31:24 - 31:30
    are a lot of different tools for building
    ROP chains, one of those tools is Ropper
  • 31:30 - 31:32
    you can find it on GitHub it's a really
    handy tool.
  • 31:32 - 31:36
    You just search for necessary
    instructions to build
  • 31:36 - 31:49
    the necessary ROP chain. So now the last
    technical part of how the ROP chains in
  • 31:49 - 31:55
    this particular exploit work and then
    we'll get to the demo. So this is how a
  • 31:55 - 32:03
    perfectly, you know, healthy stack frame
    looks like. So you basically have local
  • 32:03 - 32:07
    variables on the stack, you have return
    adress, you also have a stack frame of
  • 32:07 - 32:13
    parent functions underneath the stack
    frame of our vulnerable function. So when
  • 32:13 - 32:20
    we overflow the local variables with our
    long object identifier here's what
  • 32:20 - 32:28
    happens: We overflow the local variables
    and these variables actually partly get
  • 32:28 - 32:34
    written to $s0 and $s6 general purpose
    registers we also, of course overflow the
  • 32:34 - 32:41
    return address, which will jump for us to
    rom monitor and we also have some 60
  • 32:41 - 32:47
    bytes, after that we overflow the stack
    frame of the next function and we use that
  • 32:47 - 32:55
    data also for our ROP chain. What we do
    here, we take the value of $a0, we control
  • 32:55 - 33:02
    the value of $a0 as you remember and we
    move it to register $v0 and that's for
  • 33:02 - 33:10
    only solely purpose because there are no
    other gadgets in rom monitor that use $s0
  • 33:10 - 33:17
    as a target register to write data so we
    have to use register $v0. After that the
  • 33:17 - 33:22
    most important part is that we load the
    return address from the ROP data too and
  • 33:22 - 33:31
    also we load the address we will write to
    from the ROP data too. So basically right
  • 33:31 - 33:41
    now after this gadget stops executing we
    have $s0 points to a memory we want to
  • 33:41 - 33:50
    write to and $v0 contains 4 bytes we will
    be writing just before the code section.
  • 33:50 - 33:58
    So the final gadget that is performing the
    arbitrary write is the gadget that takes
  • 33:58 - 34:08
    the value of register $v0 and writes it to
    a pointer reference that referenced by
  • 34:08 - 34:15
    register $s0 and the last thing it does
    actually transfers the control back to the
  • 34:15 - 34:22
    gadget, which will recover the stack for
    us. Most important gadgets it allows us to
  • 34:22 - 34:28
    run the exploit several times, you might
    have noticed that the previous gadgets
  • 34:28 - 34:36
    actually moved the stack pointer 30 bytes
    and hacks down them down the
  • 34:36 - 34:38
    stack and this actually means
  • 34:38 - 34:45
    that the process that we will return
    to will crash if we don't point the stack
  • 34:45 - 34:51
    pointer just between two stack frames. We
    find a gadget that will move the stack
  • 34:51 - 35:00
    pointer down to 228 bytes in hex, which
    will result in a perfectly healthy stack.
  • 35:00 - 35:09
    Also we load the return address to
    register $ra and it points to the parent
  • 35:09 - 35:17
    function that called our own vulnerable
    function so this way we perform an
  • 35:17 - 35:23
    arbitrary four byte write. We can do this
    several times until our shellcode is
  • 35:23 - 35:28
    actually built, just before the text
    section and the final thing we do, we
  • 35:28 - 35:35
    overflow the stack again and jump to the
    shellcode. A few words about the
  • 35:35 - 35:46
    shellcode: The device I was working with had a
    telnet service and it had a password, so I
  • 35:46 - 35:52
    designed a simple shell code that will
    just patch the authentication call flow.
  • 35:52 - 35:59
    So as you can see here we have a function
    "login password check" and a result which
  • 35:59 - 36:09
    is in $v0 register is checked whether the
    authentication was successful or not. We
  • 36:09 - 36:14
    can build a shell code which which will
    just patch this instruction which checks
  • 36:14 - 36:20
    "login password check" and it will allow
    us to make a credential list
  • 36:20 - 36:30
    authentication against telnet service. So
    what it does: basically the shell code
  • 36:30 - 36:36
    inspects the stack and the return address
    in it to calculate the ASLR offset
  • 36:36 - 36:43
    because, of course the ASLR is on for the
    code section and we want to patch
  • 36:43 - 36:52
    something in it and after that it writes a
    0, which is a nop instruction in MIPS, to
  • 36:52 - 37:01
    a call that checks for password for telnet
    and also for enable password and then it
  • 37:01 - 37:11
    just jumps back to SNMP service. So now
    the long-awaited demo. Let's see if I can
  • 37:11 - 37:42
    make it a live demo. All righty, so here
    we have the serial connection to the
  • 37:42 - 37:53
    device, you can see we have a shell. So
    what we do now, we inspect the password on
  • 37:53 - 37:56
    the telnet service to make sure it's
    working as intended. So we see that bad
  • 37:56 - 38:04
    passwords. We don't know the valid
    password for the device, what we do now is
  • 38:04 - 38:16
    we launch the actual exploit, as
    parameters it takes the host, community
  • 38:16 - 38:26
    and shell code in hex. So this is the shell
  • 38:26 - 38:41
    code I was talking about that patches the
    code flow in authentication. So let's
  • 38:41 - 38:54
    write sudo. So here you see that we
    initiate writing the four byte sequences
  • 38:54 - 39:02
    into the text section. Basically this
    writes the shell code into the memory. So
  • 39:02 - 39:17
    after the exploit finishes this, we just
    have to jump to the shell code. So let's
  • 39:17 - 39:58
    see. Please do not crash. So, yes. So back
    to the slides. And of course you can build
  • 39:58 - 40:02
    a shell code that will unset this behavior
    and patch the process back to enable the
  • 40:02 - 40:08
    password and on the side notes how
    reliably can you exploit this
  • 40:08 - 40:15
    vulnerability? So, of course the SNMP
    public community will leak you the version
  • 40:15 - 40:21
    of the particular router but it does not
    leak you the version of ROMMON and we're
  • 40:21 - 40:29
    basically constructing ROP chains in the
    rom monitor. So actually you have not that
  • 40:29 - 40:34
    many versions of rom monitor available.
    You have only five if we're talking about
  • 40:34 - 40:42
    2800 router. So the worst-case scenario is
    just you crash it four times. It's not
  • 40:42 - 40:46
    like you have to crash it four thousand
    times to you know beat the ASLR but
  • 40:46 - 40:52
    there's a second option which is
    interesting. ROMMON is designed to be
  • 40:52 - 40:58
    upgraded, so basically a system
    administrator can download a new version
  • 40:58 - 41:03
    and update it but the thing is that read-
    only region that contains the stock ROMMON
  • 41:03 - 41:10
    is always in place and it is always at the
    same offset, so even if you updated the
  • 41:10 - 41:16
    rom monitor, the read-only version of it,
    the old version that always been there,
  • 41:16 - 41:25
    will always be at bfc00000. So basically
    the assumption is that all the devices
  • 41:25 - 41:29
    manufactured at the same time and place,
    they will have the same read-only rom
  • 41:29 - 41:38
    monitor, you can query your serial number
    of your router using snmpget. So for
  • 41:38 - 41:45
    example my lab router is manufactured in
    the year of 2008 and Czech Republic. So
  • 41:45 - 41:52
    and it has the following version of rom
    monitor. So guys to, you know, to
  • 41:52 - 41:57
    summarise about all this, do not leave
    default credentials on external networks.
  • 41:57 - 42:03
    So public communities are not designed to
    be placed on external networks
  • 42:03 - 42:10
    for the Shodan to find it. Take care of
    what you expose on the external networks.
  • 42:10 - 42:17
    Of course patch your devices and watch
    for the end-of-life announcement by
  • 42:17 - 42:28
    Cisco. Sorry? Sure why not? Alright guys
    thank you so much for your attention
  • 42:28 - 42:41
    applause
    thanks for having me.
  • 42:41 - 42:43
    Herald: I suppose there are some questions
  • 42:43 - 42:50
    in this audience, please take a microphone
    if you can. no one on the internet? They
  • 42:50 - 43:01
    are flabbergasted there it seems.
    Microphone number one.
  • 43:01 - 43:07
    Mic 1: Yeah, I'm a random network admin
    and I know that people tend to use the
  • 43:07 - 43:13
    same SNMP community on many of their
    routers. My view is that basically if you
  • 43:13 - 43:19
    can get access to read only on those
    routers you will be able to hijack that or
  • 43:19 - 43:25
    like use the same principle. So basically
    don't use the same SNMP community on all
  • 43:25 - 43:30
    your devices that would be also something.
    Artem Kondratenko: the main thing is to
  • 43:30 - 43:35
    update your routers because it's a patched
    vulnerability, the patch was released in
  • 43:35 - 43:43
    September of 2017 but if you tend to use
    the end-of-life products like router 2800
  • 43:43 - 43:49
    you probably should use a strong community
    strength for it.
  • 43:49 - 43:55
    Herald: Thank you. Someone else having a
    question there? Yes someone on the
  • 43:55 - 44:00
    internet is alive. It's alive.
    Signal Angel: Let's try it. Yeah now I've
  • 44:00 - 44:05
    actually got a microphone. The Internet is
    asking how much time did you put into this
  • 44:05 - 44:09
    whole project?
    Artem Kondratenko: While working on this
  • 44:09 - 44:19
    exploit consumed around I'd say four
    weeks. Four weeks from the discovering the
  • 44:19 - 44:26
    device on the external network to the
    final exploit. Yes. Thank you.
  • 44:26 - 44:31
    Herald: I have a question maybe for you as
    well. Is that you you're as well a lot of
  • 44:31 - 44:36
    you have lots of volunteers who are
    working with you as well in researching
  • 44:36 - 44:38
    these exploits or?
    Artem Kondratenko: Volunteers?
  • 44:38 - 44:42
    Herald: Yeah I don't know.
    Artem Kondratenko: No, actually we don't
  • 44:42 - 44:44
    have any volunteers, this is all part of
    my work.
  • 44:44 - 44:52
    Herald: Okay. Thank you very much for
    thank you very much for this in its really
  • 44:52 - 44:56
    revealing lecture, if someone wants to...
    Artem Kondratenko: Oh I just forgot to
  • 44:56 - 45:02
    say, is my mic on? okay so the actual
    proof of concept and the debugger will be
  • 45:02 - 45:08
    released in a few days, so the Python
    script with the capstone and the actual
  • 45:08 - 45:12
    proof of concept I'll publish it and in a
    week or so.
  • 45:12 - 45:16
    Herald: okay thank you.
  • 45:16 - 45:21
    34c3 outro
  • 45:21 - 45:37
    subtitles created by c3subtitles.de
    in the year 2018. Join, and help us!
Title:
34C3 - 1-day exploit development for Cisco IOS
Description:

more » « less
Video Language:
English
Duration:
45:37

English subtitles

Revisions