Category Archives: Hacking Etico

Just enough cryptography for better securing your apps

I’m not a cryptographer myself but I have always admired their work because literally they make the Internet a better place by creating technology that allows us our right to privacy and cybersecurity plus I enjoy playing basic crypto CTF challenges. At my current job I’m a weird mixture between Software developer and Information Security guy (finally the best of two worlds) that means I work a lot with security and crypto related matters and I’m also very fortunate for  being able to work very close to a real cryptographer, so a couple months ago we were talking about security and I asked him if he could share some resources about cryptography but focusing on Software Engineers, meaning people without a heavy background in mathematics, this is what I learned.

If you are a Software Engineer curious about Information Security chances are you have crossed paths with a task that involves adding some kind of security mechanisms to protect data in your application, my friend explained me that in practice, cryptography is about choosing the right tool for the job and as a Security Software Engineer the most common tasks you will face are:

  • Encrypt a data blob or data stream
  • Exchange a secret key with a peer
  • Verify that some data blob or data stream is not modified
  • Verify that some data blob or data stream has been produced by someone specific.
  • Generate a secret key from another secret key
  • Generate a secret key from a (low-entropy) value – e.g. password

There are out there many cryptographic mechanisms that will make our lives easier when it comes to software engineering and we need to learn how to pick the right tool for the job

I’m not saying you should completely ignore the theory and jump directly into the practice, theory is important and you should learn it or at least be aware of the different types of cryptographic primitives, the most important classes/types are:

  • Pseudo-Random Permutation (PRP) – e.g. AES
  • Pseudo-Random Function (PRF) – e.g. ChaCha
  • Random Oracle (RO) – e.g. SHA-256

Modern cryptographic algorithms usually follow a more theory-based approach when it comes to achieve its goals and test its security, they usually do that by reducing the security relative to the primitives they use, it’s very common to read things like: 

The scheme X achieves the security goals A, B and C if the underlying primitive Y is in-fact a K.

Primitives usually have a condition in the form of a mathematical proof or very hard problems to solve e.g. prime-factor representation for RSA asymmetric primitive or the discrete logarithm problem for the Diffie-Hellman key exchange algorithm, therefore If you want to break a cryptographic scheme you will first need to break the assumptions used by its primitives, if no one can do that then it’s safe to assume the cryptographic scheme is secure.

My point here is you need to understand what are the goals you want to achieve first, what is your requirement, that’s the only way you can pick the right cryptographic scheme based on the primitives that will solve your problem.

Key Derivation

Let’s say you have an application that calculates the hmac-sha256 signature of a message using the password provided by a user as a key:

This works but there’s a problem with this approach, calculate hmac-sha256 signatures its trivial, with the help of a good dictionary an attacker can easily brute force the user password and if he succeed on obtaining the original secret he can impersonate the user in your application

Therefore, in order to make the job of the attacker more expensive in terms of time, computation and memory resources, the recommended approach is to use a Key-derivation function (KDF) or password-based key derivation function (PBKDF) when deriving a key from a password 

When I learned this concept from my friend it was mind-blowing, In general you have to distinguish between deriving a secret key from a high-entropy source, like a cryptographic key, or from a low-entropy source, like a password. PBKDF usage is about trade-offs, try to hit a parameter such that the PBKDF is relatively cheap to compute for you in your scenario but expensive for the attacker that tries to brute-force the secret password.

func deriveKey(key []byte, salt []byte) string {
	derivedKey := pbkdf2.Key(key, salt, 4096, 32, sha1.New)
	return base64.StdEncoding.EncodeToString(derivedKey)
}

func main() {
	message := []byte("hello world")
	key := []byte("super secret key")
	fmt.Println(string(key), deriveKey(key, message))
	// super secret key UJS9n/48gSEHyVK8UZPcC6vKGpsyI6mNrWexmvdtCB4=
}

Data Integrity

Preserving data integrity is a crucial part when working with information, the easiest way to achieve data integrity is by encrypting the data, however sometimes you don’t want to do that because encrypting and decrypting data it’s an expensive operation and you only want to preserve data integrity, then the most straightforward solution is HMAC with a RO – like SHA-256.

func computeHmac256(message []byte, key []byte) string {
	h := hmac.New(sha256.New, key)
	h.Write(message)
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

func main() {
	message := []byte("hello world")
	key := []byte("super secret key")
	messageHmac := computeHmac256(message, key)
	fmt.Println(string(message), messageHmac)
	// hello world yFgx2zBmFCpq9N6JuGAMRnTBN5cUwTkHBtqcAyGR2bw=
}

Encryption

Symmetric cryptographic schemes are better for encrypting a data blob or data stream vs asymmetric schemes due to performance advantages, the recommendation is to use Authenticated Encryption (AE) or Authenticated Encryption with Associated Data (AEAD). There are two main AEAD schemes used in practice: AES-GCM and ChaCha20-Poly1305. Both belong to the same class of cryptographic objects: AEAD.

func encryptAES_GCM(key []byte, message []byte) string {
	block, _ := aes.NewCipher(key)
	nonce := make([]byte, 12)
	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		panic(err.Error())
	}
	aesgcm, err := cipher.NewGCM(block)
	if err != nil {
		panic(err.Error())
	}
	ciphertext := aesgcm.Seal(nil, nonce, message, nil)
	return base64.StdEncoding.EncodeToString(ciphertext)
}

func main() {
	message := []byte("hello world")
	key := []byte("super secret key")
	fmt.Println(string(message), encryptAES_GCM(key, message))
	// hello world gBoJuHdAm5PjNGFdr+B/8Eq58IFZKcrzz6JQ
}

Github example: https://gist.github.com/Alevsk/0c296f230279bd399a244d4f7d1d7b84

Happy hacking 🙂

CTF OverTheWire: Natas10

Continuing with the CTF Natas series, now is the turn for natas10

Natas Level 9 → Level 10
Username: natas10
URL:      http://natas10.natas.labs.overthewire.org

Using the flag obtained in the previous challenge, we go to the URL showed in the description and we will see the following screen.

It’s a simple web page with a basic input form, very similar to the previous one but they have added a character filter, we proceed to click the View sourcecode and we are redirected to index-source.html

This is supposed to be the backend code of the html form.

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    if(preg_match('/[;|&]/',$key)) {
        print "Input contains an illegal character!";
    } else {
        passthru("grep -i $key dictionary.txt");
    }
}
?>

The preg_match(‘/[;|&]/’,$key) function will make sure to drop any search request that contains the ; or & characters so we cannot execute additional commands like we did on the previous level, but instead of trying to bypass this filter there is an easier way to solve this level, the grep command supports search for a pattern in multiple files so we are going to exploit that, the goal is to execute something like this:

grep -i '' /etc/natas_webpass/natas11 dictionary.txt 

Since ” /etc/natas_webpass/natas11 doesn’t contains any of the filtered characters we can just send this payload through the form.

The flag for the next level, natas11, is: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK

In this challenge we exploit a command injection vulnerability that essentially allow us to execute arbitrary commands on the server, this time there was a security mechanism in place but the fundamental problem was still there. Depending on the privileges of the user running the web server we might read, write or delete files.

Happy hacking 🙂

CTF OverTheWire: Natas9

Continuing with the CTF Natas series, now is the turn for natas9

Natas Level 8 → Level 9
Username: natas9
URL:      http://natas9.natas.labs.overthewire.org

Using the flag obtained in the previous challenge, we go to the URL showed in the description and we will see the following screen.

It’s just a simple web page with a basic input form, if we type nonsense nothing happens, we proceed to click the View sourcecode and we are redirected to index-source.html

This is supposed to be the backend code of the html form.

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    passthru("grep -i $key dictionary.txt");
}
?>

The vulnerability in this code happens when calling the passthru function, we are reading user input directly from the needle request parameter, then saving it into the $key variable and using it without any kind of sanitization when calling the function, that’s essentially command injection. We are going to try to execute commands in the web server by exploiting this vulnerability.

Sending ;ls -la;

Results in all files on the current directory to be listed

I was a little bit lost at this point but then I remember the CTF instructions.

Each level has access to the password of the next level. Your job is to somehow obtain that next password and level up. All passwords are also stored in /etc/natas_webpass/. E.g. the password for natas5 is stored in the file /etc/natas_webpass/natas5 and only readable by natas4 and natas5.

So we do ;cat /etc/natas_webpass/natas10;

The flag for the next level, natas10, is: nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu

As mentioned before, this challenge we exploit a command injection vulnerability that essentially allow us to execute arbitrary commands on the server, depending on the privileges of the user running the web server we might read, write or delete files.

Happy hacking 🙂

Commands and Code Snippets I usually forget

Some commands and code snippets I use rarely during CTFs or my daily work, but still I need them from time to time and I’m very lazy to remember them. This note may grow over time.

Javascript

Playing with dec, hexa and bin (not really) in JS
String.fromCharCode(0x41) // 'A'

parseInt('0xf', 16) // 15

var n = 15

n.toString(16) // 'f'
n.toString(2) // '1111'
n.toString() // '15'

var n = 'A'
n.charCodeAt() // 65
// dec to hex
n.charCodeAt().toString(16) // '41'
// dec to bin
n.charCodeAt().toString(2) // '1000001'
// dec to hex
parseInt(255).toString(16) // 'ff'
// dec to bin
parseInt(5).toString(2) // '101'
Simple HTTP GET request using nodejs
const https = require('https');

https.get('https://www.alevsk.com', (resp) => {
  let data = '';
  resp.on('data', (chunk) => {
    data += chunk;
  });
  resp.on('end', () => {
    //DO something with data
  });
}).on("error", (err) => {
  console.log("Error: " + err.message);
});
Simple HTTP POST request using nodejs
const https = require('https')

const data = JSON.stringify({
  todo: 'Buy the milk'
})

const options = {
  hostname: 'whatever.com',
  port: 443,
  path: '/todos',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': data.length
  }
}

const req = https.request(options, res => {
  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', error => {
  console.error(error)
})

req.write(data)

req.end()
Extract content between regular expression patterns using JS
const message =  data.match(/<p>([^<]+)<\/p>/)[1];
const lat =  data.match(/name="lat" value="([^<]+)" min=/)[1];
const long =  data.match(/name="lon" value="([^<]+)" min=/)[1];
const token =  data.match(/name="token" value="([^<]+)"/)[1];

Linux

Mount NTFS on Linux
mount -t ntfs [FILE] [PATH]
mount -t type device directory
Extract extended attributes from NTFS disk
getfattr --only-values [FILE] -n [ATTR-NAME] > file
Parsing file with awk and run xargs
cat [FILE] | awk '{print $1 .. $n}' | xargs

Python

Start Simple HTTP server with Python
python -m SimpleHTTPServer
Inline Python commands
python -c 'print "\x41" * 20'

PHP

Run PHP interactive mode
php -a

CTF OverTheWire: Natas8

After a break we continue with the CTF Natas series, now is the turn for natas8

Natas Level 7 → Level 8
Username: natas8
URL:      http://natas8.natas.labs.overthewire.org

Using the flag obtained in the previous challenge, we go to the URL showed in the description and we will see the following screen.

It’s just a simple web page with a basic input form, if we type nonsense we get an error message displaying Wrong secret, we proceed to click the the View sourcecode

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas8", "pass": "<censored>" };</script></head>
<body>
<h1>natas8</h1>
<div id="content">

<?

$encodedSecret = "3d3d516343746d4d6d6c315669563362";

function encodeSecret($secret) {
    return bin2hex(strrev(base64_encode($secret)));
}

if(array_key_exists("submit", $_POST)) {
    if(encodeSecret($_POST['secret']) == $encodedSecret) {
    print "Access granted. The password for natas9 is <censored>";
    } else {
    print "Wrong secret";
    }
}
?>

<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

This is supposed to be the backend code of the HTML page we just saw, the important part of this challenge is in the PHP code functions, taking a quick look the data flow looks like this:

  • Check if submit key exists on $_POST
  • Pass $_POST[‘secret’] to encodeSecret function
  • encodeSecret function will apply some transformation to the secret and return it
  • The transformed secret must be equal to 3d3d516343746d4d6d6c315669563362, otherwise we are getting the Wrong secret error we saw already

As I say before, the important part is happening inside the encodeSecret function, the code is basically doing this:

secret -> base64_encode -> strrev -> bin2hex -> 3d3d516343746d4d6d6c315669563362

So we need to perform exactly the same operations but in reverse order to obtain the original secret, ie: the old bin2hex should be hex2bin, I don’t know if we should call this reverse engineering, anyway ¯\_(ツ)_/¯

3d3d516343746d4d6d6c315669563362 -> hex2bin -> strrev -> base64_encode -> secret

We can use PHP from the command line and do this:

$ php -r "echo base64_decode(strrev(hex2bin('3d3d516343746d4d6d6c315669563362')));"
oubWYf2kBq
$

We get the secret: oubWYf2kBq, we try it on the input form.

The flag for the next level, natas9, is: W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl

In this challenge we take advantage of a security vulnerability called Source code disclosure and then we did basic reverse engineering on the PHP code.

Happy hacking 🙂