4747import multiprocessing
4848import os
4949import queue
50+ import re
5051import shutil
5152import subprocess
5253import sys
5657
5758import rarfile
5859import requests
59- from flask import Flask , abort , jsonify , make_response , request
60+ from flask import Flask , abort , jsonify , make_response , request , safe_join
6061from flask .json import JSONEncoder
6162from flask_cors import CORS
6263from jinja2 import Markup
@@ -541,7 +542,7 @@ def create_task():
541542 )
542543
543544
544- @app .route ('/api/v1/tasks/<task_id>/report' , methods = ['GET' ])
545+ @app .route ('/api/v1/tasks/<int: task_id>/report' , methods = ['GET' ])
545546def get_report (task_id ):
546547 '''
547548 Return a JSON dictionary corresponding
@@ -572,7 +573,7 @@ def _pre_process(report_dict={}):
572573 executed on report_dict.
573574 '''
574575
575- # pop unecessary keys
576+ # pop unnecessary keys
576577 if report_dict .get ('Report' , {}).get ('ssdeep' , {}):
577578 for k in ['chunksize' , 'chunk' , 'double_chunk' ]:
578579 try :
@@ -628,7 +629,7 @@ def _linkify(s, url, new_tab=True):
628629 s = s )
629630
630631
631- @app .route ('/api/v1/tasks/<task_id>/file' , methods = ['GET' ])
632+ @app .route ('/api/v1/tasks/<int: task_id>/file' , methods = ['GET' ])
632633def files_get_task (task_id ):
633634 # try to get report dict
634635 report_dict , success = get_report_dict (task_id )
@@ -645,7 +646,7 @@ def files_get_task(task_id):
645646 return jsonify ({'Error' : 'sha256 not in report!' })
646647
647648
648- @app .route ('/api/v1/tasks/<task_id>/maec' , methods = ['GET' ])
649+ @app .route ('/api/v1/tasks/<int: task_id>/maec' , methods = ['GET' ])
649650def get_maec_report (task_id ):
650651 # try to get report dict
651652 report_dict , success = get_report_dict (task_id )
@@ -695,7 +696,7 @@ def taglist():
695696 return jsonify ({'Tags' : response })
696697
697698
698- @app .route ('/api/v1/tasks/<task_id>/tags' , methods = ['POST' , 'DELETE' ])
699+ @app .route ('/api/v1/tasks/<int: task_id>/tags' , methods = ['POST' , 'DELETE' ])
699700def tags (task_id ):
700701 '''
701702 Add/Remove the specified tag to the specified task.
@@ -719,7 +720,7 @@ def tags(task_id):
719720 return jsonify ({'Message' : 'Tag Removed' })
720721
721722
722- @app .route ('/api/v1/tasks/<task_id>/notes' , methods = ['GET' ])
723+ @app .route ('/api/v1/tasks/<int: task_id>/notes' , methods = ['GET' ])
723724def get_notes (task_id ):
724725 '''
725726 Get one or more analyst notes/comments associated with the specified task.
@@ -749,7 +750,7 @@ def get_notes(task_id):
749750 return jsonify (response )
750751
751752
752- @app .route ('/api/v1/tasks/<task_id>/notes' , methods = ['POST' ])
753+ @app .route ('/api/v1/tasks/<int: task_id>/notes' , methods = ['POST' ])
753754def add_note (task_id ):
754755 '''
755756 Add an analyst note/comment to the specified task.
@@ -764,7 +765,7 @@ def add_note(task_id):
764765 return jsonify (response )
765766
766767
767- @app .route ('/api/v1/tasks/<task_id>/notes/<note_id>' , methods = ['PUT' , 'DELETE' ])
768+ @app .route ('/api/v1/tasks/<int: task_id>/notes/<int: note_id>' , methods = ['PUT' , 'DELETE' ])
768769def edit_note (task_id , note_id ):
769770 '''
770771 Modify/remove the specified analyst note/comment.
@@ -784,7 +785,7 @@ def edit_note(task_id, note_id):
784785 return jsonify (response )
785786
786787
787- @app .route ('/api/v1/files/<sha256>' , methods = ['GET' ])
788+ @app .route ('/api/v1/files/<string: sha256>' , methods = ['GET' ])
788789# get raw file - /api/v1/files/get/<sha256>?raw=true
789790def files_get_sha256 (sha256 ):
790791 '''
@@ -793,18 +794,21 @@ def files_get_sha256(sha256):
793794 # is there a robust way to just get this as a bool?
794795 raw = request .args .get ('raw' , default = 'False' , type = str )
795796
796- return files_get_sha256_helper (sha256 , raw )
797+ if re .match (r'^[a-fA-F0-9]{64}$' , sha256 ):
798+ return files_get_sha256_helper (sha256 , raw )
799+ else :
800+ return abort (HTTP_BAD_REQUEST )
797801
798802
799803def files_get_sha256_helper (sha256 , raw = None ):
800804 '''
801805 Returns binary from storage. Defaults to password protected zipfile.
802806 '''
803- file_path = os . path . join (api_config ['api' ]['upload_folder' ], sha256 )
807+ file_path = safe_join (api_config ['api' ]['upload_folder' ], sha256 )
804808 if not os .path .exists (file_path ):
805809 abort (HTTP_NOT_FOUND )
806810
807- with open (file_path , "rb" ) as fh :
811+ with open (file_path , 'rb' ) as fh :
808812 fh_content = fh .read ()
809813
810814 raw = raw [0 ].lower ()
@@ -816,13 +820,13 @@ def files_get_sha256_helper(sha256, raw=None):
816820 else :
817821 # ref: https://github.com/crits/crits/crits/core/data_tools.py#L122
818822 rawname = sha256 + '.bin'
819- with open (os . path . join ('/tmp/' , rawname ), 'wb' ) as raw_fh :
823+ with open (safe_join ('/tmp/' , rawname ), 'wb' ) as raw_fh :
820824 raw_fh .write (fh_content )
821825
822826 zipname = sha256 + '.zip'
823827 args = ['/usr/bin/zip' , '-j' ,
824- os . path . join ('/tmp' , zipname ),
825- os . path . join ('/tmp' , rawname ),
828+ safe_join ('/tmp' , zipname ),
829+ safe_join ('/tmp' , rawname ),
826830 '-P' , 'infected' ]
827831 proc = subprocess .Popen (args )
828832 wait_seconds = 30
@@ -836,7 +840,7 @@ def files_get_sha256_helper(sha256, raw=None):
836840 proc .terminate ()
837841 return make_response (jsonify ({'Error' : 'Process timed out' }))
838842 else :
839- with open (os . path . join ('/tmp' , zipname ), 'rb' ) as zip_fh :
843+ with open (safe_join ('/tmp' , zipname ), 'rb' ) as zip_fh :
840844 zip_data = zip_fh .read ()
841845 if len (zip_data ) == 0 :
842846 return make_response (jsonify ({'Error' : 'Zip file empty' }))
@@ -881,7 +885,7 @@ def run_ssdeep_group():
881885 HTTP_BAD_REQUEST )
882886
883887
884- @app .route ('/api/v1/tasks/<task_id>/pdf' , methods = ['GET' ])
888+ @app .route ('/api/v1/tasks/<int: task_id>/pdf' , methods = ['GET' ])
885889def get_pdf_report (task_id ):
886890 '''
887891 Generates a PDF version of a JSON report.
@@ -898,7 +902,7 @@ def get_pdf_report(task_id):
898902 return response
899903
900904
901- @app .route ('/api/v1/tasks/<task_id>/stix2' , methods = ['GET' ])
905+ @app .route ('/api/v1/tasks/<int: task_id>/stix2' , methods = ['GET' ])
902906def get_stix2_bundle_from_report (task_id ):
903907 '''
904908 Generates a STIX2 Bundle with indicators generated of a JSON report.
0 commit comments