SMS DOS: Cellphone Denial Of Service via text messages

A while ago I wondered how well modern cellphones could handle a flood of text messages. So I created a simple python program to test just that. The program works by sending emails to a SMS Gateway which will forward the message to the phone in the form of a text message.

I tested my program on two devices, my modern HTC Incredible running Android and my aging LG Chocolate dumb-phone. The results where surprising! After starting the program my HTC Incredible froze after receiving the first 20 messages. A battery pull was required to get it to respond. The second it finished booting it froze again! I was only able to make it respond by stopping my program and rebooting the phone. After it boot it froze again while catching up on all the messages that where sent.

My LG Chocolate was another story. While it never froze, it did make the phone almost impossible to use. 10 times a second it would display a notification of the new message. But after about 100 messages it just stopped. My program was still sending them but the phone stopped receiving them. I’m not sure if this was done by the phone itself or something on the carrier’s end.

I am releasing the source of this program in case others find it interesting. I claim no responsibility for any damage done by this program. Use at your own risk on devices you own!

Source Code at GitHub

SMS DOS requires PyQt4 for the GUI, it can be installed HERE.


LDAP Authentication for Cakephp

This article is going to help you using LDAP to authenticate users rather than relying on a users table with a password column. I will be assuming you will be using cakephp 1.3 and that you have completed Auth and/or ACL setup on your application similar to the ACL tutorial on the cakephp book.

Because we want to control the logging in of the user ourselves and not leave it to the cake magic we need to override the auth component. To do this copy your auth.php from your CAKE_CORE/controllers/components/ to your APP/controllers/components/ folder. Next open it up and fine the login function. It should be around like 684. Once you find it comment out everything inside the fucntion (but leave the function intact. It should look something like this:

function login($data = null) {
    /*$this->__setDefaults();
    $this->_loggedIn = false;
    if (empty($data)) {$data = $this->data; }
    if ($user = $this->identify($data))
    { $this->Session->write($this->sessionKey, $user);
    $this->_loggedIn = true; }
return $this->_loggedIn;*/ }

Next open up your users controller and find your login function. Assuming you followed the guide or have implemented some basic auth you should have an empty login function.

I have written a LDAP helper that can easily be included as a LIB for Cakephp that will get some user data and validate the login, copy and paste it from below to APP/libs/ldap.php

<?php
class ldap{

    private $ldap = null;
    private $ldapServer = 'AD.domain.com';
    private $ldapPort = '389';
    public $suffix = '@domain.com';
    public $baseDN = 'dc=domain,dc=com';
    private $ldapUser = 'LDAPUser';
    private $ldapPassword = 'Pas5w0rd';

    public function  __construct() {
        $this->ldap = ldap_connect($this->ldapServer,$this->ldapPort);

        //these next two lines are required for windows server 03
        ldap_set_option($this->ldap, LDAP_OPT_REFERRALS, 0);
        ldap_set_option($this->ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
    }

    public function auth($user,$pass)
    {
        if (empty($user) or empty($pass))
        {
            return false;
        }
        @$good = ldap_bind($this->ldap,$user.$this->suffix,$pass);
        if( $good === true ){
            return true;
        }else{
            return false;
        }
    }

    public function __destruct(){
        ldap_unbind($this->ldap);
    }

    public function getInfo($user){
        $username = $user.$this->suffix;;
        $attributes = array('givenName','sn','mail','samaccountname','memberof');
        $filter = "(userPrincipalName=$username)";

        ldap_bind($this->ldap,$this->ldapUser.$this->suffix,$this->ldapPassword);
        $result = ldap_search($this->ldap, $this->baseDN, $filter,$attributes);
        $entries = ldap_get_entries($this->ldap, $result);

        return $this->formatInfo($entries);
    }

    private function formatInfo($array){
        $info = array();
        $info['first_name'] = $array[0]['givenname'][0];
        $info['last_name'] = $array[0]['sn'][0];
        $info['name'] = $info['first_name'] .' '. $info['last_name'];
        $info['email'] = $array[0]['mail'][0];
        $info['user'] = $array[0]['samaccountname'][0];
        $info['groups'] = $this->groups($array[0]['memberof']);

        return $info;
    }

    private function groups($array)
    {
        $groups = array();
        $tmp = array();

        foreach( $array as $entry )
        {
            $tmp = array_merge($tmp,explode(',',$entry));
        }

        foreach($tmp as $value) {
            if( substr($value,0,2) == 'CN' ){
                $groups[] = substr($value,3);
            }
        }

        return $groups;
    }
}
?>

Edit the variables at the tom of the file to reflect your setup.

Now we are going to make our Users->login function check the POST username and password against LDAP, and then if valid it will preform the login magic that auth used to do.

Fill your login function with this:

    function login() {
        App::import('Lib', 'ldap');
        if ($this->Session->read('Auth.User')) {
             $this->redirect(array('controller' => 'allocations', 'action' => 'index'));
        } elseif (!empty($this->data)) {
            $ldap = new ldap;
            if ($ldap->auth($this->Auth->data['User']['user'], $this->Auth->data['User']['password'])) {

                $userrow = $this->User->findByUsername($this->data['User']['user']);
                if (!$userrow) {
                    $ldap_info = $ldap->getInfo($this->data['User']['user']);
                    $this->data['User']['username'] = $this->data['User']['user'];
                    $this->data['User']['name'] = $ldap_info['name'];
                    $this->data['User']['group_id'] = 3; //sets the default group
                    $this->add();
                    $userrow = $this->User->findByUsername($this->data['User']['user']);
                }

                $user = $userrow['User'];

                $this->Auth->Session->write($this->Auth->sessionKey, $user);
                $this->Auth->_loggedIn = true;

                $this->Session->setFlash('You are logged in!');
                $this->redirect(array('controller' => 'allocations', 'action' => 'index'));
            } else {
                $this->Session->setFlash(__('Login Failed', true));
            }
        }
    }

To quickly summarize, it first checks to see if the user is logged in, if not, and post data is provided it will check the provided credentials with the LDAP Lib. If valid it then attempts to get the user from the users table, if the user does not exist it creates it with information provided from LDAP and defaults set in the function.

I built this to still work with a users table to allow relationships between other models and users. but it can be used without a users table, just remove the if(!$userrow) statement and the line before it.

NOTE: If you use a users table, you do not need, and should not have, a password column.

That should be it! You should now be using LDAP for user credential validation.