def test_delete(self): # Add a sample sha256 = '03b0b693f76b22e54eea716997b98b9a105c82b031439f72663d7b0209bd1f7d' db.session.add(Sample(sha256, 'c99.php', 'db3121cd98c49ef6114cc60f2fea32a1', 'c33ba376c53f33bf11bd607206c43eed7c7e2430', '3072:7x1qKo1wcNyg1dxiGbkYdMH4qDZLFh7C8We8Y9377:7x1qKdcNB1dxiGbkYdMH4qDZLFh7C8W0', '5.68514757275382', ' 2016-04-21 13:41:37.960251 UTC', ' 2016-04-21 13:41:37.960251 UTC', 0, 0, ' text/x-php')) db.session.commit() # Acces the page with no authentication rv = self.app.get('/admin/delete/{sha256}'.format(sha256=sha256)).data.decode('utf-8') self.assertIn('You should be redirected automatically to target URL: <a href="/login">/login</a>', rv) # Log in self.login() # Access the page with no sha256 rv = self.app.get('/admin/delete/').status_code self.assertEqual(rv, 404) # Access the page with wrong sha256 rv = self.app.get('/admin/delete/WHATTHEFUCKYOUSUCKAHAHAHAHAHA').status_code self.assertEqual(rv, 404) # Delete the sample self.app.get('/admin/delete/{sha256}'.format(sha256=sha256)) self.assertIsNone(Sample.get(sha256))
def test_vote(self): # Vote for the file we just uploaded rv = self.app.get('/vote/{sha256}/clean'.format( sha256=global_sha256)).data.decode('utf-8') samp = Sample.get(global_sha256) self.assertEqual(rv, 'OK') self.assertEqual(samp.vote_clean, 1) self.assertEqual(samp.vote_malicious, 0) # Vote for the same file rv = self.app.get('/vote/{sha256}/clean'.format( sha256=global_sha256)).data.decode('utf-8') samp = Sample.get(global_sha256) self.assertEqual(rv, 'NOK') self.assertEqual(samp.vote_clean, 1) self.assertEqual(samp.vote_malicious, 0) # Upload a new file self.app.post('/upload', data=dict(file=(StringIO(file_content), file_name), filename=file_name, type='PHP')) # Vote for this file rv = self.app.get('/vote/{sha256}/malicious'.format( sha256=file_sha256)).data.decode('utf-8') samp = Sample.get(file_sha256) self.assertEqual(rv, 'OK') self.assertEqual(samp.vote_clean, 0) self.assertEqual(samp.vote_malicious, 1)
def test_index(self): """ Test admin index """ # Add a sample in the database sample = Sample( sha256='6ffef45e178b189c9eb486457dc6ae71a2e62be5724adc598d25585a6c0c6c1a', sha1='6a6f0260611dcd60d502d308f74ff3c1ad590cfe', md5='149b8ae3ca1cf126af05bd8c58ebde90', ssdeep='3072:7Q6vU3oUXNiDarHituutTxmakBIRDzGoiTzj7c5hH5D8:7Q6vMXNQarHituutTxmakBcDzGoiTzjF', entropy='5.65471943656401', mime='text/x-php', first_analysis='2000-01-01 10:00:00.00000', last_analysis='2000-01-01 10:00:00.00000' ) sample.analyzes.append(Analysis( type='PHP', soft='PMF', sample_sha256='6ffef45e178b189c9eb486457dc6ae71a2e62be5724adc598d25585a6c0c6c1a', analysis_time='0.004575014114379883' )) db.session.add(sample) db.session.commit() # Access without being logged in rv = self.app.get('/admin/').data.decode('utf-8') self.assertIn('You should be redirected automatically to target URL: <a href="/login">/login</a>', rv) # Log in and access it self.login() rv = self.app.get('/admin/').data.decode('utf-8') dates = [datetime.date.today() - datetime.timedelta(days=x) for x in range(7)] dates = [date.isoformat() for date in reversed(dates)] self.assertIn("labels: " + str(dates) + ",", rv)
def test_submit_tag(self): # Submit shitty tag rv = self.app.get('/tag/submit/{sha256}/SHITTY').data.decode('utf-8') self.assertEqual(rv, 'NOK') # Submit a correct tag with invalid sha256 rv = self.app.get('/tag/submit/{sha256}/Tag').data.decode('utf-8') self.assertEqual(rv, 'NOK') # Add a tag to the db tag = Tag('Tag', 'info') db.session.add(tag) db.session.commit() # Submit a correct tag with valid sha256 rv = self.app.get('/tag/submit/{sha256}/Tag'.format( sha256=global_sha256)).data.decode('utf-8') self.assertEqual(rv, 'OK') tags = [tag.name for tag in Sample.get(global_sha256).tags] self.assertIn('Tag', tags) # Submit the same tag with the same sha256 rv = self.app.get('/tag/submit/{sha256}/Tag'.format( sha256=global_sha256)).data.decode('utf-8') self.assertEqual(rv, 'NOK')
def test_edit(self): # Add a sample sha256 = '03b0b693f76b22e54eea716997b98b9a105c82b031439f72663d7b0209bd1f7d' db.session.add(Sample(sha256, 'c99.php', 'db3121cd98c49ef6114cc60f2fea32a1', 'c33ba376c53f33bf11bd607206c43eed7c7e2430', '3072:7x1qKo1wcNyg1dxiGbkYdMH4qDZLFh7C8We8Y9377:7x1qKdcNB1dxiGbkYdMH4qDZLFh7C8W0', '5.68514757275382', ' 2016-04-21 13:41:37.960251 UTC', ' 2016-04-21 13:41:37.960251 UTC', 0, 0, ' text/x-php')) db.session.commit() # Access the page with no authentication rv = self.app.get('/admin/edit/{sha256}'.format(sha256=sha256)).data.decode('utf-8') self.assertIn('You should be redirected automatically to target URL: <a href="/login">/login</a>', rv) # Log in self.login() # Access the page with no sha256 rv = self.app.get('/admin/edit/').status_code self.assertEqual(rv, 404) # Access the page with wrong sha256 rv = self.app.get('/admin/edit/WHATTHEFUCKYOUSUCKAHAHAHAHAHA').status_code self.assertEqual(rv, 404) # Access the page rv = self.app.get('/admin/edit/{sha256}'.format(sha256=sha256)).data.decode('utf-8') self.assertIn('<h2>Edit sample : {sha256}</h2>'.format(sha256=sha256), rv) # Edit the sample rv = self.app.post('/admin/edit/{sha256}'.format(sha256=sha256), data=dict( name='c999.php', mime='text/x-php', first_analysis='2016-04-22 09:07:49.421788', last_analysis='2016-04-22 09:07:49.421788', tags='' ), follow_redirects=True).data.decode('utf-8') self.assertIn('c999.php', rv)
def sample_exists(analysis_type, sha256): """ Returns OK if the file has already been analysed """ sample = Sample.get(sha256) if sample: for analysis in sample.analyzes: if analysis.type == analysis_type: return "OK" return "NOK"
def delete(sha256): """ Delete a sample from harddrive and database """ sample = Sample.get(sha256) if not sample: abort(404) for tag in sample.tags: db.session.delete(tag) for analysis in sample.analyzes: db.session.delete(analysis) db.session.delete(sample) db.session.commit() try: os.remove(Sample.get_file_path(sha256)) except OSError: flash('Could not delete the file from the file system.', 'danger') flash('The file %s has been deleted. Are you happy now ?' % sha256, 'success') return redirect(request.referrer)
def test_search(self): rv = self.app.get('/search') self.assertEqual(200, rv.status_code) self.assertIn('<h1>Search</h1>', rv.data.decode('utf-8')) # Add a sample with his tag tag = Tag('wat', 'danger') db.session.add(tag) sample = Sample( name=['wut.php'], sha256='6ffef45e178b189c9eb486457dc6ae71a2e62be5724adc598d25585a6c0c6c1a', sha1='6a6f0260611dcd60d502d308f74ff3c1ad590cfe', md5='149b8ae3ca1cf126af05bd8c58ebde90', ssdeep='3072:7Q6vU3oUXNiDarHituutTxmakBIRDzGoiTzj7c5hH5D8:7Q6vMXNQarHituutTxmakBcDzGoiTzjF', entropy='5.65471943656401', mime='text/x-php', first_analysis='2000-01-01 10:00:00.00000', last_analysis='2000-01-01 10:00:00.00000' ) sample.tags.append(tag) sample.analyzes.append(Analysis( type='PHP', soft='PMF', sample_sha256='6ffef45e178b189c9eb486457dc6ae71a2e62be5724adc598d25585a6c0c6c1a', analysis_time='0.004575014114379883' )) db.session.add(sample) db.session.commit() result_sha256 = '<a href="/analysis/any/6ffef45e178b189c9eb486457dc6ae71a2e62be5724adc598d25585a6c0c6c1a">6ffef45e178b189c9eb486457dc6ae71a2e62be5724adc598d25585a6c0c6c1a</a>' rv = self.app.get('/search') self.assertIn(result_sha256, rv.data.decode('utf-8')) # Custom search rv = search(self.app, '6ffe') self.assertIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, '6ffe123') self.assertNotIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'md5:126') self.assertIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'md5:wat') self.assertNotIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'name:php') self.assertIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'name:qweqwe') self.assertNotIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'fist_analysis:2000-01-01') self.assertIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'last_analysis:2000-01-03') self.assertNotIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'tags:wat') self.assertIn(result_sha256, rv.data.decode('utf-8')) rv = search(self.app, 'tags:watt') self.assertNotIn(result_sha256, rv.data.decode('utf-8'))
def analyse(self): # New sample ? New analysis ? sample = Sample.get(self.sha256) if sample is None: # New sample, let's add it ! sample = Sample(sha256=self.sha256, name=self.name) sample.compute_hashes() else: # Too recent do not analyse it if (sample.last_analysis < (sample.last_analysis + datetime.timedelta(days=3)) and len(sample.analyzes) == len(current_app.config.get('ENABLED_ANALYZERS'))): return True # Update last analysis date sample.last_analysis = datetime.date.today() self.do_analyzes(sample) db.session.add(sample) # Commit database try: db.session.commit() except DataError: flash('There was an error while analysing your file.', 'danger') return False # Allow the user to vote for his sample session['can_vote'] = self.sha256 return True
def add_name(sha256, name): """ Add a name to the specified sample :param sha256: str :param name: str """ if name is None: return sample = Sample.get(sha256=sha256) if name not in sample.name: # Since name is an ARRAY (postgresql) we cannot use append() sample.name = sample.name + [name] db.session.add(sample) db.session.commit()
def submit_tag(sha256, tag, format): tags = Tag.get_all() tag_names = [t.name for t in tags] if tag is None or tag not in tag_names: return "NOK" sample = Sample.get(sha256) sample_tag_names = [t.name for t in sample.tags] if sample is None or tag in sample_tag_names: return "NOK" _tag = tags[tag_names.index(tag)] sample.tags.append(_tag) # postgre doesn't like str as objects. db.session.commit() return str(_tag) if format else 'OK'
def analyse(self): """ Analyse the file with PMF """ start = time.time() rule_file = os.path.join(current_app.config.get('BASE_DIR'), self.path, self.type.lower() + '.yar') rules = yara.compile(rule_file) try: with open(Sample.get_file_path(self.filename), 'rb') as f: matches = rules.match(data=f.read()) except OSError: flash('Error while reanalysing the file.', 'danger') return False self.analysis_time = time.time() - start self.result = ' '.join(map(str, matches)) return True
def analyse(self): if not zipfile.is_zipfile(self.path): flash('The file you sent is not a valid zip file.', 'danger') return False archive = zipfile.ZipFile(self.path) size = 0 for compressed_file in archive.infolist(): size += compressed_file.file_size if size > MAX_SIZE: flash('The size of the archive\'s content is too big !', 'danger') return False elif compressed_file.filename.lower().endswith('.' + self.analysis.lower()): path = archive.extract(compressed_file, current_app.config.get('UPLOAD_FOLDER')) with open(path, 'rb') as f: buf = f.read() sha256 = hashlib.sha256(buf).hexdigest() new_path = Sample.get_file_path(sha256) directory = os.path.dirname(new_path) try: # Make sure the directory is writeable if not os.access(directory, os.W_OK): try: os.mkdir(directory) except OSError: flash('There was an error while saving you archive.', 'danger') shutil.move(path, new_path) except Exception as err: flash('There was an error while extracting your archive', 'danger') logging.error(err) return False # Chmod the file to prevent it from being executed os.chmod(new_path, 0o400) Analyser(sha256=sha256, name=compressed_file.filename, analysis_type=self.analysis, analyse=True) return True
def edit(sha256): """ Edit a sample metadata """ sample = Sample.get(sha256) if sample: all_tags = Tag.get_all() if request.method == 'POST': all_tags_id = [tag.id for tag in all_tags] tag_list = [] for value in request.form: if value.startswith('tag_'): id = int(value[4:]) if id in all_tags_id: tag_list.append(Tag.get(id)) sample.name = request.form.get('name', '').replace(' ', '').split(',') sample.mime = request.form.get('mime', '') sample.first_analysis = request.form.get('first_analysis', '') sample.last_analysis = request.form.get('last_analysis', '') sample.tags = tag_list db.session.add(sample) db.session.commit() return redirect(url_for('admin.samples')) return render_template('admin/edit.html', sample=sample, names=[tag.name for tag in sample.tags], tags=all_tags) abort(404)