![](https://hackmd.io/_uploads/S1u6weDO3.png) ![](https://hackmd.io/_uploads/SJQxOgwdh.png) Victim machine : 10.0.2.6 Benign machine : 10.0.2.15 ![](https://hackmd.io/_uploads/BJTzdlPdn.png) ![](https://hackmd.io/_uploads/HJ6aueDu3.png) ![](https://hackmd.io/_uploads/HyxlJteDd2.png) ![](https://hackmd.io/_uploads/r1dB9gwd3.png) ![](https://hackmd.io/_uploads/HJpgFgwOh.png) ![](https://hackmd.io/_uploads/B1wGFev_2.png) We can see the username and password in plain text username : `guest` password : `password` CentOS restart ![](https://hackmd.io/_uploads/SJP8iew_3.png) This is the attacker machine: ![](https://hackmd.io/_uploads/HkPf5ev_3.png) ![](https://hackmd.io/_uploads/H1CPqgPu2.png) ![](https://hackmd.io/_uploads/Hkl9ilvO2.png) ![](https://hackmd.io/_uploads/Sk2WnevO2.png) ![](https://hackmd.io/_uploads/HyRQ2xv_n.png) Once the attack is started ![](https://hackmd.io/_uploads/BJxZpePun.png) ![](https://hackmd.io/_uploads/BJiv0eDO3.png) ![](https://hackmd.io/_uploads/r1V_eZv_n.png) HTTP Packet is sent from benign to victim. We can see the credentials on the attacker machine. ![](https://hackmd.io/_uploads/H1OGXbw_2.png) While the ARP Posioning is not running, the MAC Addresses are different ![](https://hackmd.io/_uploads/SyZz-Zv_n.png) While the ARP poisoning is running, both MAC addresses of victim and the malicious attacker machine are the same. # 4 ![](https://hackmd.io/_uploads/H1XbV-Puh.png) Created cert with password : `mssd` ![](https://hackmd.io/_uploads/HJPggGwd2.png) `cert.pem` and `key.pem` are sent over using scp and saved in `/data/5` Added the changed lines: ```python= import ssl context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain('cert.pem' , 'key.pem') ... if __name__ == '__main__': app.run(debug=False,host='0.0.0.0',port = 443, ssl_context = context, threaded = True) ``` ![](https://hackmd.io/_uploads/BJtBbfP_n.png) ![](https://hackmd.io/_uploads/B1pcbMDu3.png) ![](https://hackmd.io/_uploads/r1HUffvdn.png) ![](https://hackmd.io/_uploads/BJd3MzPd3.png) ![](https://hackmd.io/_uploads/HyHHmMvd2.png) ![](https://hackmd.io/_uploads/r1bRfGv_n.png) Wireshark does not show the creds in plain text # 5 ![](https://hackmd.io/_uploads/r1iGqGwdn.png) Hash ``` QeweCH5vn4AimWd39XzI0wJY4VibhVkfik3cUiKH5jI= ``` The file is saved as : `server_hpkp.py` ```python from flask import Flask, url_for, request, jsonify from flask_secure_headers.core import Secure_Headers from functools import wraps import json import ssl import socket import os import ssl if socket.gethostname() == "mssd-labs": os.chdir("/data/5/") sh = Secure_Headers() sh.update(({'HPKP':{'pins':[{'sha256':'QeweCH5vn4AimWd39XzI0wJY4VibhVkfik3cUiKH5jI='}],'max-age': 2592000}}) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain('cert.pem' , 'key.pem') app = Flask(__name__) user='' shadow={'admin':'l4sT_L4b', 'guest':'password'} def check_auth(username, password): if username in shadow and shadow[username]==password: global user user=username return username else: return False def authenticate(): message = {'message': "Authenticate."} resp = jsonify(message) resp.status_code = 401 resp.headers['WWW-Authenticate'] = 'Basic realm="Example"' return resp def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth: return authenticate() user=check_auth(auth.username, auth.password) if not user: return authenticate() return f(*args, **kwargs) return decorated mdb={} @app.route('/messages') @requires_auth @sh.wrapper() def api_messages(): if user in mdb: return jsonify(messages=mdb[user]) else: return jsonify(messages="") @app.route('/message/<userid>', methods=['POST']) @requires_auth @sh.wrapper() def api_message(userid): if not userid in mdb: mdb[userid]=[] mdb[userid].append("From %s: %s"%(user,request.json['message'])) print ("Message received from user %s for user %s: %s"%(userid,user,request.json['message'])) return "Thank you for your message\n" if __name__ == '__main__': app.run(debug=False,host='0.0.0.0',port = 443, ssl_context = context, threaded = True) ``` ![](https://hackmd.io/_uploads/ryCZrO2_h.png) ![](https://hackmd.io/_uploads/SkkXHOhd2.png) ![](https://hackmd.io/_uploads/BkzrHunu2.png) ![](https://hackmd.io/_uploads/Skt3BOh_3.png) With HPKP, we can see the public key ``` Public-Key-Pins pin-sha256=QeweCH5vn4AimWd39XzI0wJY4VibhVkfik3cUiKH5jI=; includeSubDomains; report-uri=/hpkp_report; max-age=2592000 ``` # 6 Editting for `sslify`. The file is saved as `server_sslify_HTTPS.py`: ```python from flask import Flask, url_for, request, jsonify from flask_secure_headers.core import Secure_Headers from functools import wraps import json import ssl import socket import os from flask_sslify import SSLify if socket.gethostname() == "mssd-labs": os.chdir("/data/5/") sh = Secure_Headers() app = Flask(__name__) sslify = SSLify(app) # Just add this to redirect to https user='' shadow={'admin':'l4sT_L4b', 'guest':'password'} def check_auth(username, password): if username in shadow and shadow[username]==password: global user user=username return username else: return False def authenticate(): message = {'message': "Authenticate."} resp = jsonify(message) resp.status_code = 401 resp.headers['WWW-Authenticate'] = 'Basic realm="Example"' return resp def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth: return authenticate() user=check_auth(auth.username, auth.password) if not user: return authenticate() return f(*args, **kwargs) return decorated mdb={} @app.route('/messages') @requires_auth def api_messages(): if user in mdb: return jsonify(messages=mdb[user]) else: return jsonify(messages="") @app.route('/message/<userid>', methods=['POST']) @requires_auth def api_message(userid): if not userid in mdb: mdb[userid]=[] mdb[userid].append("From %s: %s"%(user,request.json['message'])) print ("Message received from user %s for user %s: %s"%(userid,user,request.json['message'])) return "Thank you for your message\n" if __name__ == '__main__': app.run(debug=False,host='0.0.0.0',port=80) ``` ![](https://hackmd.io/_uploads/HkeIKu2_2.png) ![](https://hackmd.io/_uploads/HJn1id2dh.png) Since flask-sslify is not installed, the following is run to install the package: `pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org pip flask-sslify` This is done to circumvent the failing ssl certificate. ![](https://hackmd.io/_uploads/HJz33d2O2.png) This is the commented hpkp server file (it's essentially the same as `server_https.py`) ```python= from flask import Flask, url_for, request, jsonify from flask_secure_headers.core import Secure_Headers from functools import wraps import json import ssl import socket import os import ssl if socket.gethostname() == "mssd-labs": os.chdir("/data/5/") sh = Secure_Headers() #sh.update({'HPKP':{'pins':[{'sha256':'QeweCH5vn4AimWd39XzI0wJY4VibhVkfik3cUiKH5jI='}],'max-age':2592000}}) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain('cert.pem' , 'key.pem') app = Flask(__name__) user='' shadow={'admin':'l4sT_L4b', 'guest':'password'} def check_auth(username, password): if username in shadow and shadow[username]==password: global user user=username return username else: return False def authenticate(): message = {'message': "Authenticate."} resp = jsonify(message) resp.status_code = 401 resp.headers['WWW-Authenticate'] = 'Basic realm="Example"' return resp def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth: return authenticate() user=check_auth(auth.username, auth.password) if not user: return authenticate() return f(*args, **kwargs) return decorated mdb={} @app.route('/messages') @requires_auth #@sh.wrapper() def api_messages(): if user in mdb: return jsonify(messages=mdb[user]) else: return jsonify(messages="") @app.route('/message/<userid>', methods=['POST']) @requires_auth #@sh.wrapper() def api_message(userid): if not userid in mdb: mdb[userid]=[] mdb[userid].append("From %s: %s"%(user,request.json['message'])) print ("Message received from user %s for user %s: %s"%(userid,user,request.json['message'])) return "Thank you for your message\n" if __name__ == '__main__': app.run(debug=False,host='0.0.0.0',port = 443, ssl_context = context, threaded = True) ``` ![](https://hackmd.io/_uploads/r1x161K3u3.png) Going for `http://10.0.2.6/messages` ![](https://hackmd.io/_uploads/rJ_feY3_2.png) ![](https://hackmd.io/_uploads/ByQ8lt3d3.png) ![](https://hackmd.io/_uploads/BJ6wxt3_h.png) ![](https://hackmd.io/_uploads/BJOclKh_h.png) # 6a Executing MiTM Attack : ARP Poisoning + `sslstrip -a -l 8080` Routing: `iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080` ![](https://hackmd.io/_uploads/SJ9WcK2d3.png) ![](https://hackmd.io/_uploads/SyU4cthO2.png) ![](https://hackmd.io/_uploads/rkSH9Fn_h.png) ![](https://hackmd.io/_uploads/HkXi9Fn_h.png) ![](https://hackmd.io/_uploads/BydKoF3O3.png) I can see victim (10.0.2.6) and sender (10.0.2.15) in wireshark, and also seeing port 80. # 6b After stopping the ARP Spoof: ![](https://hackmd.io/_uploads/HkhW4Q6u2.png) ```python from flask import Flask, url_for, request, jsonify from flask_secure_headers.core import Secure_Headers from functools import wraps import json import ssl import socket import os import ssl if socket.gethostname() == "mssd-labs": os.chdir("/data/5/") sh = Secure_Headers() sh.update({'HPKP':{'pins':[{'sha256':'QeweCH5vn4AimWd39XzI0wJY4VibhVkfik3cUiKH5jI='}],'max-age':2592000}}) sh.update({'HSTS':{'max-age': 2592000, 'includeSubDomains': True, 'preload': False}}) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain('cert.pem' , 'key.pem') app = Flask(__name__) user='' shadow={'admin':'l4sT_L4b', 'guest':'password'} def check_auth(username, password): if username in shadow and shadow[username]==password: global user user=username return username else: return False def authenticate(): message = {'message': "Authenticate."} resp = jsonify(message) resp.status_code = 401 resp.headers['WWW-Authenticate'] = 'Basic realm="Example"' return resp def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth: return authenticate() user=check_auth(auth.username, auth.password) if not user: return authenticate() return f(*args, **kwargs) return decorated mdb={} @app.route('/messages') @requires_auth @sh.wrapper() def api_messages(): if user in mdb: return jsonify(messages=mdb[user]) else: return jsonify(messages="") @app.route('/message/<userid>', methods=['POST']) @requires_auth @sh.wrapper() def api_message(userid): if not userid in mdb: mdb[userid]=[] mdb[userid].append("From %s: %s"%(user,request.json['message'])) print ("Message received from user %s for user %s: %s"%(userid,user,request.json['message'])) return "Thank you for your message\n" if __name__ == '__main__': app.run(debug=False,host='0.0.0.0',port = 443, ssl_context = context, threaded = True) ``` Create new cert and replaced the old one: ![](https://hackmd.io/_uploads/HJj1OQTOh.png) Benign ![](https://hackmd.io/_uploads/rkVAN7aO2.png) Attacker: ![](https://hackmd.io/_uploads/Sy61Y76dn.png) Running `wget --ca-certificate cert.pem --user guest --password password https://mssd-labs.com/messages`: ![](https://hackmd.io/_uploads/SkBLq7ad3.png) ![](https://hackmd.io/_uploads/r1U1cXauh.png) Content of `.wget-hsts`: ![](https://hackmd.io/_uploads/BJS797adh.png) Turning on ARP Spoof: ![](https://hackmd.io/_uploads/rJlriQTun.png) Running `wget --ca-certificate cert.pem --user guest --password password https://mssd-labs.com/messages` again to observe in the wireshark: ![](https://hackmd.io/_uploads/rJSosQTuh.png) ![](https://hackmd.io/_uploads/H15xhQpOn.png) ![](https://hackmd.io/_uploads/SyhW2mau2.png) We don't see any http traffic at all.