--- /dev/null
+#!/usr/bin/env python2
+# Insecure Shell 2 - Hackover 2016
+
+import socket
+import os
+from binascii import hexlify, crc32
+from subprocess import Popen, PIPE, STDOUT
+from Crypto.Cipher import AES
+from multiprocessing import Process
+import hashlib
+import struct
+import time
+import random
+
+#change this in production
+password = "This is the s3cr37 key"
+flag = "hackover16{REMOVED}"
+
+
+def encrypt(message, key):
+ iv = hashlib.md5(struct.pack('>i', crc32(message))).digest()
+ aes = AES.new(key, AES.MODE_CBC, iv)
+ padlen = 15 - (len(message) % 16)
+ padding = "X"*padlen + chr(padlen+1)
+ return iv + aes.encrypt(message + padding)
+
+
+def decrypt(cipher, key):
+ iv = cipher[:16]
+ aes = AES.new(key, AES.MODE_CBC, iv)
+ plain = aes.decrypt(cipher[16:])
+ return plain[:-ord(plain[-1])]
+
+
+nonce_len = len("Nonce:") + 32
+def get_random(n):
+ with open("/dev/urandom", "r") as f:
+ data = f.read(n)
+ return data
+
+
+def challenge(s, key):
+ nonce = "Nonce:" + hexlify(get_random(16))
+ print "challenge: %s" % nonce
+ send(s, nonce)
+
+ cipher = recv(s)
+ nonce_recv = decrypt(cipher, key)
+ print "response: %s" % nonce_recv
+
+ if nonce != nonce_recv:
+ print "got different Nonce"
+ send(s, "invalid nonce!")
+ s.close()
+ return False
+
+ send(s, "ok")
+ return nonce
+
+
+def response(s, key):
+ nonce = recv(s)
+ if nonce[:len("Nonce:")] != "Nonce:" or len(nonce) != nonce_len:
+ print "invalid nonce"
+ return False
+
+ send(s, encrypt(nonce, key))
+
+ if recv(s) != "ok":
+ print "failed authenticating"
+ s.close()
+ return False
+ print "authenticated"
+
+ return nonce
+
+
+def client(s):
+ plain = password + time.strftime("%b %d %Y %H:%M", time.gmtime())
+ key = hashlib.md5(plain).digest()
+
+ srv_nonce = challenge(s, key)
+ if not srv_nonce:
+ return
+ print "server authenticated"
+
+ clt_nonce = response(s, key)
+ if not clt_nonce:
+ return
+ print "client authenticated"
+
+ cmd = "echo edit me!"
+ cipher = encrypt(cmd, key)
+ send(s, cipher)
+ s.close()
+
+
+def server(s):
+ random.seed(time.time())
+ plain = password + time.strftime("%b %d %Y %H:%M", time.gmtime())
+ key = hashlib.md5(plain).digest()
+
+
+ srv_nonce = response(s, key)
+ if not srv_nonce:
+ return
+ print "server authenticated"
+
+ clt_nonce = challenge(s, key)
+ if not clt_nonce:
+ return
+ print "client authenticated"
+
+ while True:
+ cmd = recv(s)
+ ret = cmd_handler(cmd)
+ send(s, ret)
+
+
+def cmd_handler(cmd):
+ print "executing command: %s" % cmd
+
+ ret = ""
+ for c in cmd.split(";"):
+ c = c.split(" ")
+ if c[0] == "get-flag":
+ ret += flag
+ elif c[0] == "time":
+ time.strftime("%b %d %Y %H:%M:%S")
+ elif c[0] == "echo":
+ ret += " ".join(c[1:])
+ elif c[0] == "rand":
+ ret += "%d" % random.randrange(2**32)
+ else:
+ ret += "unknown command"
+
+ ret += "\n"
+ return ret
+
+
+def send(s, data):
+ try:
+ s.send(struct.pack('!h', len(data)))
+ s.send(data)
+ except:
+ os.kill(os.getpid(), 9)
+
+
+def recv(s):
+ try:
+ l = struct.unpack('!h', s.recv(2))[0]
+ data = s.recv(l)
+ except:
+ os.kill(os.getpid(), 9)
+ return data
+
+
+def accept(callback, port):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(("0.0.0.0", port))
+ s.listen(1)
+ s.setblocking(1)
+
+ print "listening..."
+ while True:
+ conn, addr = s.accept()
+ print ">>>client connected<<<"
+ conn.settimeout(10)
+ Process(target=callback, args=(conn,)).start()
+
+if __name__ == "__main__":
+ import sys
+ print "server"
+ accept(server, 40804)
--- /dev/null
+#!/usr/bin/env python2
+# Insecure Shell 2 - Hackover 2016
+
+import socket
+import os
+from binascii import hexlify, crc32
+from subprocess import Popen, PIPE, STDOUT
+from Crypto.Cipher import AES
+from multiprocessing import Process
+import hashlib
+import struct
+import time
+import random
+
+#change this in production
+password = "This is the s3cr37 key"
+flag = "hackover16{REMOVED}"
+
+
+def encrypt(message, key):
+ iv = hashlib.md5(struct.pack('>i', crc32(message))).digest()
+ aes = AES.new(key, AES.MODE_CBC, iv)
+ padlen = 15 - (len(message) % 16)
+ padding = "X"*padlen + chr(padlen+1)
+ return iv + aes.encrypt(message + padding)
+
+
+def decrypt(cipher, key):
+ iv = cipher[:16]
+ aes = AES.new(key, AES.MODE_CBC, iv)
+ plain = aes.decrypt(cipher[16:])
+ return plain[:-ord(plain[-1])]
+
+
+nonce_len = len("Nonce:") + 32
+def get_random(n):
+ with open("/dev/urandom", "r") as f:
+ data = f.read(n)
+ return data
+
+
+def challenge(s, key):
+ nonce = "Nonce:" + hexlify(get_random(16))
+ print "challenge: %s" % nonce
+ send(s, nonce)
+
+ cipher = recv(s)
+ nonce_recv = decrypt(cipher, key)
+ print "response: %s" % nonce_recv
+
+ if nonce != nonce_recv:
+ print "got different Nonce"
+ send(s, "invalid nonce!")
+ s.close()
+ return False
+
+ send(s, "ok")
+ return nonce
+
+
+def response(s, key):
+ nonce = recv(s)
+ if nonce[:len("Nonce:")] != "Nonce:" or len(nonce) != nonce_len:
+ print "invalid nonce"
+ return False
+
+ send(s, encrypt(nonce, key))
+
+ if recv(s) != "ok":
+ print "failed authenticating"
+ s.close()
+ return False
+ print "authenticated"
+
+ return nonce
+
+
+def client(s):
+ plain = password + time.strftime("%b %d %Y %H:%M", time.gmtime())
+ key = hashlib.md5(plain).digest()
+
+ srv_nonce = challenge(s, key)
+ if not srv_nonce:
+ return
+ print "server authenticated"
+
+ clt_nonce = response(s, key)
+ if not clt_nonce:
+ return
+ print "client authenticated"
+
+ cmd = "echo edit me!"
+ cipher = encrypt(cmd, key)
+ send(s, cipher)
+ s.close()
+
+
+def server(s):
+ random.seed(time.time())
+ plain = password + time.strftime("%b %d %Y %H:%M", time.gmtime())
+ key = hashlib.md5(plain).digest()
+
+ srv_nonce = response(s, key)
+ if not srv_nonce:
+ return
+ print "server authenticated"
+
+ clt_nonce = challenge(s, key)
+ if not clt_nonce:
+ return
+ print "client authenticated"
+
+ while True:
+ cmd = decrypt(recv(s), key)
+ ret = cmd_handler(cmd)
+ send(s, encrypt(ret, key))
+
+
+def cmd_handler(cmd):
+ print "executing command: %s" % cmd
+
+ ret = ""
+ for c in cmd.split(";"):
+ c = c.split(" ")
+ if c[0] == "get-flag":
+ ret += flag
+ elif c[0] == "time":
+ time.strftime("%b %d %Y %H:%M:%S")
+ elif c[0] == "echo":
+ ret += " ".join(c[1:])
+ elif c[0] == "rand":
+ ret += "%d" % random.randrange(2**32)
+ else:
+ ret += "unknown command"
+
+ ret += "\n"
+ return ret
+
+
+def send(s, data):
+ try:
+ s.send(struct.pack('!h', len(data)))
+ s.send(data)
+ except:
+ os.kill(os.getpid(), 9)
+
+
+def recv(s):
+ try:
+ l = struct.unpack('!h', s.recv(2))[0]
+ data = s.recv(l)
+ except:
+ os.kill(os.getpid(), 9)
+ return data
+
+
+def accept(callback, port):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(("0.0.0.0", port))
+ s.listen(1)
+ s.setblocking(1)
+
+ #accept
+ print "listening..."
+ while True:
+ conn, addr = s.accept()
+ print ">>>client connected<<<"
+ conn.settimeout(10)
+ Process(target=callback, args=(conn,)).start()
+
+if __name__ == "__main__":
+ accept(server, 15351)