Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Commit

Permalink
Merge pull request #163 from ANSSI-FR/fix-skelenox-auth
Browse files Browse the repository at this point in the history
Fix skelenox auth
  • Loading branch information
tpo-anssi authored Feb 12, 2018
2 parents 8a3d7ca + 6541dbc commit 0754894
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 43 deletions.
66 changes: 39 additions & 27 deletions poli/controllers/idaactions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""
This file is part of Polichombr.
(c) 2017 ANSSI-FR
(c) 2018 ANSSI-FR
Description:
Managers for all the actions associated with IDAPro models
Expand All @@ -26,6 +25,9 @@ class IDAActionsController(object):
"""
@staticmethod
def get_all(sid=None, timestamp=None):
"""
Return all the actions for a sample from a timestamp
"""
if sid is None:
return False
query = IDAAction.query
Expand All @@ -37,16 +39,25 @@ def get_all(sid=None, timestamp=None):
return schema.dump(query.all()).data

@staticmethod
def add_comment(address, data):
def setup_generic_action(action, address, data, user_id=None):
"""
Setup and commit the common parts of an IDA action
"""
action.address = address
action.data = data
action.timestamp = datetime.datetime.now()
action.user_id = user_id
db.session.add(action)
db.session.commit()
return action

@classmethod
def add_comment(cls, address, data, user_id=None):
"""
Creates a new comment action
"""
comment = IDACommentAction()
comment.address = address
comment.data = data
comment.timestamp = datetime.datetime.now()
db.session.add(comment)
db.session.commit()
comment = cls.setup_generic_action(comment, address, data, user_id)
return comment.id

@staticmethod
Expand Down Expand Up @@ -78,17 +89,13 @@ def get_comments(cls, sid=None, addr=None, timestamp=None):
data = schema.dump(data).data
return data

@staticmethod
def add_name(address=None, data=None):
@classmethod
def add_name(cls, address=None, data=None, user_id=None):
"""
Creates a new name action
"""
name = IDANameAction()
name.address = address
name.data = data
name.timestamp = datetime.datetime.now()
db.session.add(name)
db.session.commit()
name = cls.setup_generic_action(name, address, data, user_id)
return name.id

@classmethod
Expand All @@ -102,22 +109,28 @@ def get_names(cls, sid, addr=None, timestamp=None):
schema = IDAActionSchema(many=True)
return schema.dump(data).data

@staticmethod
def create_struct(name=None):
@classmethod
def create_struct(cls, name=None, user_id=None):
"""
Create a new struct.
"""
if name is None:
app.logger.error("Cannot create anonymous struct")
return False
mstruct = IDAStruct()
mstruct = cls.setup_generic_action(mstruct, 0, name, user_id)

mstruct.name = name
mstruct.data = name
mstruct.timestamp = datetime.datetime.now()
mstruct.size = 0
db.session.add(mstruct)
db.session.commit()
return mstruct.id

@staticmethod
def get_structs(sid, timestamp=None):
"""
List all structs from a given timestamp
"""
query = IDAStruct.query
query = query.filter(IDAStruct.samples.any(Sample.id == sid))

Expand Down Expand Up @@ -166,7 +179,7 @@ def rename_struct(struct_id, name):
@staticmethod
def delete_struct(struct_id):
"""
Delete a struct, but not it's members
"""
mstruct = IDAStruct.query.get(struct_id)
app.logger.debug("Deleting struct %s", mstruct.name)
Expand All @@ -176,6 +189,9 @@ def delete_struct(struct_id):

@staticmethod
def create_struct_member(name=None, size=None, offset=None):
"""
Create a struct member, but don't affect it to the struct yet
"""
member = IDAStructMember()
if member is None:
return False
Expand Down Expand Up @@ -241,17 +257,13 @@ def change_struct_member_size(cls, struct_id, mid, new_size):

return True

@staticmethod
def add_typedef(address, typedef):
@classmethod
def add_typedef(cls, address, typedef, user_id):
"""
Creates a new type definition
"""
mtype = IDATypeAction()
mtype.address = address
mtype.data = typedef
mtype.timestamp = datetime.datetime.now()
db.session.add(mtype)
db.session.commit()
mtype = cls.setup_generic_action(mtype, address, typedef, user_id)
return mtype.id

@classmethod
Expand Down
8 changes: 4 additions & 4 deletions poli/controllers/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def create_sample_from_file(self, file_data, orig_filename="", user=None,
# If not, we will just update some information
if Sample.query.filter_by(sha256=sha_256).count() != 0:
sample = Sample.query.filter_by(sha256=sha_256).first()
if sample.storage_file is not None and sample.storage_file != "" and os.path.exists(
if sample.storage_file is not None and os.path.exists(
sample.storage_file):
return sample

Expand Down Expand Up @@ -637,12 +637,12 @@ def add_metadata(sample, metadata_type, metadata_value):
metadata_value = hex(metadata_value)
else:
try:
metadata_value = str(metadata_value)
metadata_value = str(metadata_value).replace("\x00", "")
except Exception as e:
app.logger.exception(e)
return False
for s_metadata in sample.s_metadata:
if s_metadata.type_id == metadata_type and s_metadata.value == metadata_value:
for meta in sample.s_metadata:
if meta.type_id == metadata_type and meta.value == metadata_value:
return True
s_metadata = SampleMetadata()
s_metadata.value = metadata_value
Expand Down
2 changes: 1 addition & 1 deletion poli/templates/sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ <h3 class="panel-title">IDA PRO commands <a class="btn btn-xs btn-default" style
<td>{{"0x%x"|format((act.address|int))}}</td>
<td>{{act.type}}</td>
<td>{{act.data}}</td>
<td>Analyst</td>
<td>{{act.user_id}}</td>
<td><button type="button" class="warning" aria-label="Close">Delete</span></button> </td>
</tr>
{% endfor %}
Expand Down
14 changes: 9 additions & 5 deletions poli/views/api_idaactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import datetime

from flask import jsonify, request, abort, current_app
from flask_security import login_required
from flask_security import login_required, current_user

from poli import api
from poli.views.apiview import apiview
Expand Down Expand Up @@ -105,12 +105,13 @@ def api_post_sample_comments(sid):
abort(400, "Missing comment or address arguments")
address = data['address']
comment = data['comment']
user_id = current_user.id
current_app.logger.debug(
"Getting a new comment for sample %d : %s@0x%x",
sid,
comment,
address)
action_id = api.idacontrol.add_comment(address, comment)
action_id = api.idacontrol.add_comment(address, comment, user_id)
result = api.samplecontrol.add_idaaction(sid, action_id)
return jsonify({'result': result})

Expand Down Expand Up @@ -141,12 +142,13 @@ def api_post_sample_names(sid):
data = request.json
addr = data['address']
name = data['name']
user_id = current_user.id
current_app.logger.debug(
"Getting a new name for sample %d : %s@0x%x",
sid,
name,
addr)
action_id = api.idacontrol.add_name(addr, name)
action_id = api.idacontrol.add_name(addr, name, user_id)
result = api.samplecontrol.add_idaaction(sid, action_id)
if result is True:
api.samplecontrol.rename_func_from_action(sid, addr, name)
Expand All @@ -164,8 +166,9 @@ def api_post_sample_types(sid):
data = request.json
addr = data['address']
typedef = data['typedef']
user_id = current_user.id

action_id = api.idacontrol.add_typedef(addr, typedef)
action_id = api.idacontrol.add_typedef(addr, typedef, user_id)
result = api.samplecontrol.add_idaaction(sid, action_id)
return jsonify(dict(result=result))

Expand Down Expand Up @@ -194,7 +197,8 @@ def api_create_struct(sid):
result = False
name = data['name']
current_app.logger.debug("Creating structure %s" % name)
mstruct = api.idacontrol.create_struct(name=name)
user_id = current_user.id
mstruct = api.idacontrol.create_struct(name=name, user_id=user_id)
if mstruct is not False:
result = api.samplecontrol.add_idaaction(sid, mstruct)
return jsonify({'result': result, 'structs': [{'id': mstruct}]})
Expand Down
5 changes: 3 additions & 2 deletions poli/views/apiview.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from poli.models.user import User

from flask import jsonify, request, abort, make_response
from flask import Blueprint
from flask import Blueprint, current_app

apiview = Blueprint('apiview', __name__,
url_prefix=app.config['API_PATH'])
Expand Down Expand Up @@ -106,7 +106,8 @@ def generate_token():
key = data['api_key']
user = User.query.filter_by(api_key=key).first()
if not user:
abort(400, "Invalid user")
current_app.logger.error("Invalid user trying to login")
abort(401, "Invalid user")
return jsonify({'token': user.get_auth_token()})


Expand Down
11 changes: 11 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
#!/usr/bin/env python
"""
This file is part of Polichombr.
(c) 2018 ANSSI-FR
Description:
Wrapper for running the application
"""

from poli import app

if __name__ == "__main__":

app.run(app.config['SERVER_ADDR'],
port=app.config['SERVER_PORT'],
debug=app.config['DEBUG'])
30 changes: 27 additions & 3 deletions skelenox.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ def __init__(self, skel_config=None):
self.poli_port = skel_config.poli_port

self.h_conn = None
self.auth_token = None
self.is_online = False
self.sample_id = None

Expand All @@ -156,6 +157,7 @@ def __do_init(self):

self.h_conn = httplib.HTTPConnection(self.poli_server, self.poli_port)
self.h_conn.connect()
self.login()
self.is_online = True
self.init_sample_id()

Expand All @@ -169,6 +171,24 @@ def close_connection(self):
self.is_online = False
self.sample_id = None

def login(self):
data = json.dumps({'api_key': self.api_key})
headers = {"Accept-encoding": "gzip, deflate",
"Content-type": "application/json",
"Accept": "*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5"}

self.h_conn.request("POST",
"/api/1.0/auth_token/",
data,
headers)
res = self.h_conn.getresponse()
if res.status != 200:
idc.warning("Error, cannot login to Polichombr!")
raise IOError
token = json.loads(res.read())["token"]
self.auth_token = token

def poli_request(self, endpoint, data, method="POST"):
"""
@arg : endpoint The API target endpoint
Expand All @@ -183,7 +203,7 @@ def poli_request(self, endpoint, data, method="POST"):
"Accept": "*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Connection": "Keep-Alive",
"X-API-Key": self.api_key}
"X-Api-Key": self.auth_token}
json_data = json.dumps(data)
try:
self.h_conn.request(method, endpoint, json_data, headers)
Expand All @@ -194,7 +214,11 @@ def poli_request(self, endpoint, data, method="POST"):
self.h_conn.request(method, endpoint, json_data, headers)
res = self.h_conn.getresponse()

if res.status != 200:
if res.status == 401:
g_logger.error("Token is invalid, trying to login again")
self.login()
return None
elif res.status != 200:
g_logger.error("The %s request didn't go as expected", method)
g_logger.debug("Status code was %d and content was %s",
res.status, res.read())
Expand Down Expand Up @@ -283,7 +307,7 @@ def send_sample(self, filedata):
"""
endpoint = "/api/1.0/samples/"
headers = {"Accept-encoding": "gzip, deflate",
"X-API-Key": self.api_key}
"X-Api-Key": self.auth_token}

method = "POST"
boundary = "70f6e331562f4b8f98e5f9590e0ffb8e"
Expand Down
2 changes: 1 addition & 1 deletion tests/tests_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ def test_get_all(self):
self.assertIn(actions["idaactions"][3]["data"], "TESTCOMMENT2")

self.assertIn(actions["idaactions"][4]["type"], "idastructs")
self.assertEqual(actions["idaactions"][4]["address"], None)
self.assertEqual(actions["idaactions"][4]["address"], 0)
self.assertIn(actions["idaactions"][4]["data"], "ThisIsAStruct")

def test_push_comments(self):
Expand Down

0 comments on commit 0754894

Please sign in to comment.