def serve(path: str): """ Start the server @param path is the base path of the software """ global ROUTES global ROOT ROOT = path template = config.getConfigurationValue("http", "template") if template is None: raise Exception("No template is configured") routesFiles = join(config.ROOT, "templates", template, "routes.json") if isfile(routesFiles) is False: raise FileNotFoundError("Routes configuration was not found") downloadDir = config.getConfigurationValue("honeypot", "downloadDir") # if the download dir is not absolute, create a proper absolute path to avoid cwd issues if not isabs(downloadDir): downloadDir = join(config.ROOT, downloadDir) if not isdir(downloadDir): Path(downloadDir).mkdir(parents=True, exist_ok=True) logging.log(logging.EVENT_ID_DOWNLOAD_FOLDER_CREATE, datetime.now(), "Created download folder", not isdir(downloadDir), None) ROUTES = parseRoutes(routesFiles) app.run( debug=config.getConfigurationValue("honeypot", "debug"), host=config.getConfigurationValue("http", "host"), port=int(config.getConfigurationValue("http", "port")) )
def branding(): """ Prints the logo/ information about the software at startup """ if config.getConfigurationValue("honeypot", "branding"): print("Camera Obscura [{0}, Python {1}]".format( termcolor.colored(getVersion(), 'yellow'), version)) print("Hans, get ze {0}".format( termcolor.colored("Flammenwerfer", 'red', 'on_white'))) debugModeEnabled = config.getConfigurationValue("honeypot", "debug") if debugModeEnabled is True: print( termcolor.colored("For god's sake, disable the debug mode!", 'red'))
def log(eventId: str, timestamp: datetime, message: str, isError: bool, src_ip: str, **kwargs) -> bool: """ Logs an event """ sensor = config.getConfigurationValue("honeypot", "sensor") entry = LogEntry(eventId, timestamp, message, isError, src_ip, sensor, **kwargs) selectedLogMethod = config.getConfigurationValue("log", "method") # allow only whitelisted method calls if selectedLogMethod is not None and selectedLogMethod in [ "json", "stdout", "text" ]: return globals()[selectedLogMethod](entry) return False
def run(app, selectedPath: str, route: object, requestObj, sessionId: str): """ Executes the catchfile action """ if requestObj.method == 'POST': for key in requestObj.files: file = requestObj.files.get(key) if file.filename != "": workdir = config.getConfigurationValue("honeypot", "workdir") tmpFile = join(workdir, file.filename) file.save(tmpFile) hashcode = util.getChecksum(tmpFile) dlPath = join(app.config['UPLOAD_FOLDER'], hashcode) if path.isfile(dlPath) is False: move(tmpFile, dlPath) logging.log( logging.EVENT_ID_UPLOAD, datetime.now(), "File {0} uploaded to dl/{1}".format( file.filename, hashcode), "http", False, requestObj.remote_addr, 0.0, sessionId) else: remove(tmpFile) logging.log( logging.EVENT_ID_UPLOAD, datetime.now(), "Not storing duplicate content {1}".format( file.filename), "http", False, requestObj.remote_addr, 0.0, sessionId) return None
def tryToFindPassword(haystack: dict) -> (str, str): """ Tries to harvest credentials, e. g. out of HTTP GET """ userNameRegex = config.getConfigurationValue("http", "usernameregex") passwordRegex = config.getConfigurationValue("http", "passwordregex") userName = "" password = "" for key in haystack: value = haystack.get(key) if userName == "" and re.match(userNameRegex, key) is not None: userName = value if password == "" and re.match(passwordRegex, key) is not None: password = value if password != "" and userName != "": break return (userName, password)
def serve(path: str): """ Start the server @param path is the base path of the software """ global ROUTES global ROOT ROOT = path util.branding() template = config.getConfigurationValue("http", "template") if template is None: raise Exception("No template is configured") routesFiles = join(config.ROOT, "templates", template, "routes.json") if isfile(routesFiles) is False: raise FileNotFoundError("Routes configuration was not found") ROUTES = parseRoutes(routesFiles) app.run(debug=config.getConfigurationValue("honeypot", "debug"), host=config.getConfigurationValue("http", "host"), port=int(config.getConfigurationValue("http", "port")))
def getRotatedLogFilename() -> str: """ gets the rotated filename, e. g. obscura.log.1 """ path = config.getConfigurationValue("log", "path") completePath = getLogPath(path) now = int(time.time()) if isfile(completePath): modification = int(stat(completePath).st_mtime) else: modification = now - 1 # to trigger creation timespan = int(config.getConfigurationValue("log", "timespan")) if modification + timespan < now: files = ([ name for name in listdir('.') if isfile(name) and path in name ]) suffix = len(files) move(completePath, completePath + "." + str(suffix)) return completePath
def run(app: Flask, selectedPath: str, route: object, request: request): file = route["servefile"]["file"] if "(" in selectedPath: match = re.search(selectedPath, request.path) if match is not None: groups = match.groups() index = 1 for group in groups: file = file.replace("$" + str(index), group) index = index + 1 if isinstance(file, list): random.seed(datetime.now().time().microsecond) fileToServe = join(config.ROOT, file[random.randint(0, len(file) - 1)]) else: fileToServe = join(config.ROOT, file) pathInfo = pathlib.Path(fileToServe) if "render_template" in route["servefile"] and route["servefile"][ "render_template"] == True: getValues = http.getString(request) return render_template(route["servefile"]["file"], config=config, getValues=getValues, ip=request.remote_addr) if ".txt" in pathInfo.suffix: content = "" with open(fileToServe, 'r') as handle: content = handle.read() matches = re.findall(r"(\$[a-z\.]+)", content) if matches is not None: for match in matches: name = match.replace("$", "") value = "" if "." in name: parts = name.split(".") value = config.getConfigurationValue( parts[0], parts[1]) else: variables = { "day": datetime.now().day, "hour": datetime.now().hour, "minute": datetime.now().minute, "month": datetime.now().month, "second": datetime.now().second, "year": datetime.now().year } if name in variables: value = str(variables[name]) if value is not None: content = content.replace(match, value) return content return send_file(fileToServe, as_attachment=False)
def run(app, selectedPath: str, route: object, requestObj): """ Executes the catchfile action """ if requestObj.method == 'POST': for key in requestObj.files: file_object = requestObj.files.get(key) # shasum = hashlib.sha224(copy.copy(file_object).read()).hexdigest() filename = str(datetime.now().timestamp()) downloadDir = config.getConfigurationValue("honeypot", "downloadDir") if not isabs(downloadDir): downloadDir = join(config.ROOT, downloadDir) if not isdir(downloadDir): raise Exception("Download dir not existing") file_path = join(downloadDir, filename) file_object.save(file_path) shasum = hashlib.sha256() with open(file_path, 'rb') as f: while True: data = f.read(65536) if not data: break shasum.update(data) hashed_filepath = join(downloadDir, shasum.hexdigest()) os.rename(file_path, hashed_filepath) logging.log(logging.EVENT_ID_UPLOAD, datetime.now(), "Uploaded {0}".format(shasum.hexdigest()), not isfile(file_path), requestObj.remote_addr, shasum=shasum.hexdigest())
def run(app: Flask, selectedPath: str, route: object, request: request, sessionId: str): file = route["servefile"]["file"] if "(" in selectedPath: match = re.search(selectedPath, request.path) if match is not None: groups = match.groups() index = 1 for group in groups: file = file.replace("$" + str(index), group) index = index + 1 if isinstance(file, list): random.seed(datetime.now().time().microsecond) fileToServe = join(config.ROOT, file[random.randint(0, len(file) - 1)]) else: fileToServe = join(config.ROOT, file) pathInfo = pathlib.Path(fileToServe) if "watermark" in route["servefile"] and route["servefile"]["watermark"] and pathInfo.suffix.replace( ".", "") in config.getConfigurationValue("image", "images").replace(r"\s", "").split(","): tmpPath = join( config.getConfigurationValue( "image", "workdir"), pathInfo.name + pathInfo.suffix) now = datetime.now().isoformat() original = Image.open(fileToServe) watermark = Image.new("RGBA", original.size) waterdraw = ImageDraw.ImageDraw(watermark, "RGBA") waterdraw.text( (4, 2), "%s %s" % (config.getConfigurationValue( "image", "watermark"), now)) original.paste(watermark, None, watermark) original.save(tmpPath) return send_file(tmpPath, as_attachment=False) if "render_template" in route["servefile"] and route["servefile"]["render_template"] == True: getValues = http.getString(request) return render_template( route["servefile"]["file"], config=config, getValues=getValues, ip=request.remote_addr) if ".txt" in pathInfo.suffix: content = "" with open(fileToServe, 'r') as handle: content = handle.read() matches = re.findall(r"(\$[a-z\.]+)", content) if matches is not None: for match in matches: name = match.replace("$", "") value = "" if "." in name: parts = name.split(".") value = config.getConfigurationValue( parts[0], parts[1]) else: variables = { "day": datetime.now().day, "hour": datetime.now().hour, "minute": datetime.now().minute, "month": datetime.now().month, "second": datetime.now().second, "year": datetime.now().year } if name in variables: value = str(variables[name]) if value is not None: content = content.replace(match, value) return content return send_file(fileToServe, as_attachment=False)