#!/usr/bin/python3 from werkzeug.serving import WSGIRequestHandler from flask import Flask,request,send_from_directory,redirect,abort from flask.logging import default_handler from datetime import datetime from platform import system import logging import time import ssl import os import pwnpass import threading import re app = Flask(__name__) cfg = None pwn = None logStore = threading.local() logLock = threading.RLock() def logmsg(request,type,message,args): is_dst = time.daylight and time.localtime().tm_isdst > 0 tz = - (time.altzone if is_dst else time.timezone) / 36 if tz>=0: tz="+%04d"%tz else: tz="%05d"%tz datestr = '%d/%b/%Y %H:%M:%S' user = getattr(logStore,'user','') isValid = getattr(logStore,'isValid','') code = getattr(logStore,'code','') args = getLogDateTime(args) log = '%s %s,%s,%s,%s,%s,%s' % (datetime.now().strftime(datestr),tz,request.address_string(),user,isValid,code, message % args) with logLock: with open(cfg.logpath,'a') as fw: fw.write(log+os.linesep) return log def getLogDateTime(args): if not cfg.debug: try: if len(args) == 3: args = (re.sub(r'p=.* HTTP',r'p=<redacted> HTTP',args[0]),args[1],args[2]) elif len(args) == 2: args = (re.sub(r'p=.* HTTP',r'p=<redacted> HTTP',args[0]),args[1]) except TypeError as e: print("arg0: %s"%type(args[0])) print("arg1: %s"%type(args[1])) if len(args) == 3: print("arg2: %s"%type(args[2])) print(args) raise e # args = (re.sub(r'p=.* HTTP',r'p=<redacted> HTTP',args[0]),args[1],args[2]) return args #"/" "GET" -> form.html @app.route('/', methods = ['GET']) def v1form(): return open('%s/form.html'%(cfg.staticdir)).read() @app.route('/checkpwd', methods = ['GET','POST']) def v1CheckPassword(): username = '' password = '' if request.method == 'GET': username = request.args.get('u','') password = request.args.get('p','') reserve = True elif request.method == 'POST': username = request.form.get('u','') password = request.form.get('p','') reserve = False (isGood,code,reason) = pwn.verifyPasswordGood(username, password, reserve=reserve, always_true=cfg.yesman) logStore.code = code logStore.isValid = isGood logStore.user = username message = u','.join(map(str,[isGood,code,reason])) return message @app.route("/test", methods = [ "GET" ] ) def v1Test(): return "" @app.route("/styles.css") @app.route("/script.js") @app.route("/image.svg") def StaticRequests(): reqfile = request.path[1:] sp = os.path.join(app.root_path,cfg.staticdir) mimetype=None if reqfile == 'image.svg': mimetype = 'image/svg+xml' return send_from_directory(sp,reqfile,mimetype=mimetype) @app.route("/favicon.ico") def NoSuchFile(): abort(404) #ELSE 301 to 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' @app.route('/<path:path>') def catch_all(path): return redirect('https://www.youtube.com/watch?v=dQw4w9WgXcQ' ,code=301) ########################################################### ##################### MAIN ################################ ########################################################### if __name__ == "__main__": werkzeug_logger = logging.getLogger('werkzeug') WSGIRequestHandler.log = lambda self, type, message, *args: getattr(werkzeug_logger, type)(logmsg(self,type,message,args)) args = pwnpass.pwnargparse() args.add_argument('-c','--sslcert',help='SSL Public Certificate for the HTTPS Web Server') args.add_argument('-k','--sslkey',help='SSL Private Key for the HTTPS Web Server') args.add_argument('--sslkeypass',help='Passphrase to decrypt the SSL Private Key', default=None) if system() == 'Windows': args.add_argument('-l','--logpath',help='Path to the logfile',default=None) else: args.add_argument('-l','--logpath',help='Path to the logfile',default='/var/log/pwnedpass-access.log') args.add_argument('-p','--port',help='TCP Port to for web server to listen on', default=443, type=int) args.add_argument('-i','--interface',help='TCP Bind interface for web server to listen on', default='0.0.0.0') args.add_argument('-s','--staticdir',help='Path to the static files supporting the web UI', default='static') cfg = args.parse_args() pwn = pwnpass.PwnPass(cfg) pwn.debug = cfg.debug ssl_context = 'adhoc' if cfg.sslcert and cfg.sslkey: ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ssl_context.load_cert_chain(certfile=cfg.sslcert, keyfile=cfg.sslkey, password=cfg.sslkeypass) app.run(host=cfg.interface, port=cfg.port, ssl_context=ssl_context,debug=cfg.debug)