Jump to content

Search the Community

Showing results for tags 'allowing'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Informatii generale
    • Anunturi importante
    • Bine ai venit
    • Proiecte RST
  • Sectiunea tehnica
    • Exploituri
    • Challenges (CTF)
    • Bug Bounty
    • Programare
    • Securitate web
    • Reverse engineering & exploit development
    • Mobile security
    • Sisteme de operare si discutii hardware
    • Electronica
    • Wireless Pentesting
    • Black SEO & monetizare
  • Tutoriale
    • Tutoriale in romana
    • Tutoriale in engleza
    • Tutoriale video
  • Programe
    • Programe hacking
    • Programe securitate
    • Programe utile
    • Free stuff
  • Discutii generale
    • RST Market
    • Off-topic
    • Discutii incepatori
    • Stiri securitate
    • Linkuri
    • Cosul de gunoi
  • Club Test's Topics
  • Clubul saraciei absolute's Topics
  • Chernobyl Hackers's Topics
  • Programming & Fun's Jokes / Funny pictures (programming related!)
  • Programming & Fun's Programming
  • Programming & Fun's Programming challenges
  • Bani pă net's Topics
  • Cumparaturi online's Topics
  • Web Development's Forum
  • 3D Print's Topics

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Website URL


Yahoo


Jabber


Skype


Location


Interests


Biography


Location


Interests


Occupation

Found 1 result

  1. As many of you know, last weekend was Ghost in the Shellcode 2015! There were plenty of fun challenges, and as always I had a great time competing! This will be my first of four writeups, and will be pretty simple (since it simply required me to use a tool that already exists (and that I wrote) The level was called "knockers". It's a simple python script that listens on an IPv6 UDP port and, if it gets an appropriately signed request, opens one or more other ports. The specific challenge gave you a signed token to open port 80, and challenged you to open up port 7175. The service itself listened on port 8008 ("BOOB", to go with the "knockers" name). You can download the original level here (Python). # python2 pleaseimport sys import struct import hashlib import os from binascii import hexlify, unhexlify import SocketServer import socket try: from fw import allow except ImportError: def allow(ip,port): print 'allowing host ' + ip + ' on port ' + str(port) PORT = 8008 g_h = hashlib.sha512 g_key = None def generate_token(h, k, *pl): m = struct.pack('!'+'H'*len(pl), *pl) mac = h(k+m).digest() return mac + m def parse_and_verify(h, k, m): ds = h().digest_size if len(m) < ds: return None mac = m[:ds] msg = m[ds:] if h(k+msg).digest() != mac: return None port_list = [] for i in range(0,len(msg),2): if i+1 >= len(msg): break port_list.append(struct.unpack_from('!H', msg, i)[0]) return port_list class KnockersRequestHandler(SocketServer.BaseRequestHandler): def handle(self): global g_key data, s = self.request print 'Client: {} len {}'.format(self.client_address[0],len(data)) l = parse_and_verify(g_h, g_key, data) if l is None: print 'bad message' else: for p in l: allow(self.client_address[0], p) class KnockersServer(SocketServer.UDPServer): address_family = socket.AF_INET6 def load_key(): global g_key f=open('secret.txt','rb') g_key = unhexlify(f.read()) f.close() def main(): global g_h global g_key g_h = hashlib.sha512 if len(sys.argv) < 2: print '''Usage: --- Server --- knockers.py setup Generates a new secret.txt knockers.py newtoken port [port [port ...]] Generates a client token for the given ports knockers.py serve Runs the service --- Client --- knockers.py knock <host> <token> Tells the server to unlock ports allowed by the given token ''' elif sys.argv[1]=='serve': load_key() server = KnockersServer(('', PORT), KnockersRequestHandler) server.serve_forever(); elif sys.argv[1]=='setup': f = open('secret.txt','wb') f.write(hexlify(os.urandom(16))) f.close() print 'wrote new secret.txt' elif sys.argv[1]=='newtoken': load_key() ports = map(int,sys.argv[2:]) print hexlify(generate_token(g_h, g_key, *ports)) elif sys.argv[1]=='knock': ai = socket.getaddrinfo(sys.argv[2],PORT,socket.AF_INET6,socket.SOCK_DGRAM) if len(ai) < 1: print 'could not find address: ' + sys.argv[2] return family, socktype, proto, canonname, sockaddr = ai[0] s = socket.socket(family, socktype, proto) s.sendto(unhexlify(sys.argv[3]), sockaddr) else: print 'unrecognized command' if __name__ == '__main__': main() The vulnerability To track down the vulnerability, let's have a look at the signature algorithm: def generate_token(h, k, *pl): m = struct.pack('!'+'H'*len(pl), *pl) mac = h(k+m).digest() return mac + m In that function, h is a hash function (sha-512, specifically), k is a random 16-byte token, randomly generated, and m is an array of 16-bit representation of the ports that the user wishes to open. So if the user wanted to open port 1 and 2, they'd send "\x00\x01\x00\x02", along with the appropriate token (which the server administrator would have to create/send, see below). Hmm... it's generating a mac-protected token and string by concatenating strings and hashing them? If you've followed my blog, this might sound very familiar! This is a pure hash extension vulnerability! I'm not going to re-iterate what a hash extension vulnerability is in great detail—if you're interested, check out the blog I just linked—but the general idea is that if you generate a message in the form of msg + H(secret + msg), the user can arbitrarily extend the message and generate a new signature! That means if we have access to any port, we have access to every port! Let's see how! Generating a legit token To use the python script linked above, first run 'setup': $ python ./knockers.py setup wrote new secret.txt Which generates a new secret. The secret is just a 16-byte random string that's stored on the server. We don't really need to know what the secret is, but for the curious, if you want to follow along and verify your numbers against mine, it's: $ cat secret.txt 2b396fb91a76307ce31ef7236e7fd3df Now we use the tool (on the same host as the secret.txt file) to generate a token that allows access on port 80: $ python ./knockers.py newtoken 80 83a98996f0acb4ad74708447b303c081c86d0dc26822f4014abbf4adcbc4d009fbd8397aad82618a6d45de8d944d384542072d7a0f0cdb76b51e512d88de3eb20050 Notice the first 512 bits (64 bytes) is the signature—which is logical, since it's sha512—and the last 16 bits (2 bytes) are 0050, which is the hex representation of 80. We'll split those apart later, when we run hash_extender, but for now let's make sure the token actually works first! We start the server: $ python ./knockers.py serve And in another window, or on another host if you prefer, send the generated token: $ python ./knockers.py knock localhost 83a98996f0acb4ad74708447b303c081c86d0dc26822f4014abbf4adcbc4d009fbd8397aad82618a6d45de8d944d384542072d7a0f0cdb76b51e512d88de3eb20050 In the original window, you'll see that it was successful: $ python ./knockers.py serve Client: ::1 len 66 allowing host ::1 on port 80 Now, let's figure out how to create a token for port 7175! Generating an illegit (non-legit?) token So this is actually the easiest part. It turns out that the awesome guy who wrote hash_extender (just kidding, he's not awesome) built in everything you needed for this attack! Download and compile hash_extender if needed (definitely works on Linux, but I haven't tested on any other platforms—testers are welcome!), and run it with no arguments to get the help dump. You need to pass in the original data (that's "\x00\x80"), the data you want to append (7175 => "\x1c\x07"), the original signature, and the length of the secret (which is 16 bytes). You also need to pass in the types for each of the parameters ("hex") in case the defaults don't match (in this case, they don't—the appended data is assumed to be raw). All said and done, here's the command: ./hash_extender --data-format hex --data 0050 \ --signature-format hex --signature 83a98996f0acb4ad74708447b303c081c86d0dc26822f4014abbf4adcbc4d009fbd8397aad82618a6d45de8d944d384542072d7a0f0cdb76b51e512d88de3eb2 \ --append "1c07" --append-format hex \ -l 16 You can pass in the algorithm and the desired output format as well, if we don't, it'll just output in every 512-bit-sized hash type. The output defaults to hex, so we're happy with that. $ ./hash_extender --data-format hex --data 0050 --signature-format hex --signature 83a98996f0acb4ad74708447b303c081c86d0dc26822f4014abbf4adcbc4d009fbd8397aad82618a6d45de8d944d384542072d7a0f0cdb76b51e512d88de3eb2 --append "1c07" --append-format hex -l 16 Type: sha512 Secret length: 16 New signature: 4bda887c0fc43636f39ff38be6d592c2830723197b93174b04d0115d28f0d5e4df650f7c48d64f7ca26ef94c3387f0ca3bf606184c4524600557c7de36f1d894 New string: 005080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000901c07 [strike] Type: whirlpool Secret length: 16 New signature: f4440caa0da933ed497b3af8088cb78c49374853773435321c7f03730386513912fb7b165121c9d5fb0cb2b8a5958176c4abec35034c2041315bf064de26a659 New string: 0050800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000901c07[/strike] Ignoring the whirlpool token, since that's the wrong algorithm, we now have a new signature and a new string. We can just concatenate them together and use the built-in client to use them: $ python ./knockers.py knock localhost 4bda887c0fc43636f39ff38be6d592c2830723197b93174b04d0115d28f0d5e4df650f7c48d64f7ca26ef94c3387f0ca3bf606184c4524600557c7de36f1d894005080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000901c07 And checking our server, we see a ton of output, including successfully opening port 7175: $ python ./knockers.py serve Client: ::1 len 66 allowing host ::1 on port 80 Client: ::1 len 178 allowing host ::1 on port 80 allowing host ::1 on port 32768 allowing host ::1 on port 0 allowing host ::1 on port 0 [...repeated like 100 times...] allowing host ::1 on port 0 allowing host ::1 on port 0 allowing host ::1 on port 144 allowing host ::1 on port 7175 And that's it! At that point, you can visit http://knockers.2015.ghostintheshellcode.com:7175 and get the key. Source skullsecurity
×
×
  • Create New...