def resource_content_api_get(): """ GET Parameters for API: *mandatory* - hashes = list of hashes --> returns true/false values for if each hash is already present & stored on disk. *optional* - content = True - -> causes API to return full content of resources - beautify = True --> causes API to return beautified JS content """ hash_list = request.args.get('hashes').split(',') if request.args.get('beautify') == 'true': beautify = True else: beautify = False if request.args.get('content') == 'true': return_content = True else: return_content = False response = {} for sha256 in hash_list: if not is_valid_sha256(sha256): # TODO: auto-report these? return 'invalid hash' _, filename = get_resource_content_location(sha256) content = 'false' if os.path.isfile(filename): if return_content: with gzip.open(filename, 'rb') as f: content = f.read().decode('utf-8') if not beautify: content = html.escape(content) else: content = 'true' yara_scan_file.delay(filename) # adding this .delay() call here # is not ideal, but works for now. # we want to re-scan hashes when # they're observed for the 2nd, 3rd, etc # time, but the POST requests will # not be sent for repeat observations! # adding this here, for now. response[sha256] = content if beautify: template_content = [] for sha256 in response.keys(): c = response[sha256] if beautify: c = external.jsbeautifier.beautify(c, opts) template_content.append({'hash': sha256, 'content': c}) return render_template('resource-content/view_script_content.html', scriptcontent=template_content, beautified=beautify) else: return jsonify(response)
def resource_content_api_post(): """ POST API takes objects like: {"upload": [{"sha256": "abcd01234abcd01234abcd01234abcd01234", "content": "... content goes here ..."}, {"sha256": "5678efab5678efab5678efab5678efab5678", "content": "... 2nd content here ..."}, . . . . . . . . . . . etc . . . . ]} Misc Notes: - SHA256 hashes are verified server-side - Request source IP must be on the whitelist """ # check to see if it's coming from an authorized IP address: verify_ip_is_authorized() # first we check to see if the file exists for the hash the client provides # (let's avoid spending the effort to hash the user's data in the 99% case # where the user isn't lying. we'll eventually check their hash later...) req = json.loads(str(request.data, 'utf-8')) upload_list = req.get('upload') response = {} for data in upload_list: sha256_c = data.get('sha256') filedir, filename = get_resource_content_location(sha256_c) if os.path.isfile(filename): response[sha256_c] = 'false' break # we double check that the hash we've calculated matches the hash # provided by the client and then write the file to disk content = data.get('content') sha256 = hashlib.sha256(content.encode('utf-8')).hexdigest() if sha256_c != sha256: # TODO: auto-report cases where this check fails? return 'content / hash mismatch' os.makedirs(filedir, exist_ok=True) with gzip.open(filename, 'wb') as f: f.write(content.encode('utf-8')) yara_scan_file.delay(filename) response[sha256_c] = 'true' return jsonify(response)