Skip to content

Commit

Permalink
Added Tornado Async
Browse files Browse the repository at this point in the history
  • Loading branch information
zeyadkhaled committed Dec 1, 2019
1 parent 4dc31ef commit 1b765b6
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 0 deletions.
126 changes: 126 additions & 0 deletions api_endpoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
from tornado.web import RequestHandler
import json
from time import time
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
from urllib.parse import urlparse
from requests import post


cred = credentials.Certificate('ids-hackathor-636a3e9f4e4c.json')
firebase_admin.initialize_app(cred, {
'databaseURL': 'https://ids-hackathor.firebaseio.com/'
})
ref = db.reference('')

with open('payloads.json', encoding="utf8") as f:
loaded = json.load(f)
XSS = loaded['XSS']
TRAVERS = loaded['TRAVERS']

VIRUSTOTAL = '66a5fb757b258c33502762d5b0f494111d7cc70032cfcf115336ad837a13b9ea'
DOMAIN = "bilkent.com"


def send_ref(ip, param, val, type):
ref.push({
"ip": ip,
"type": type,
"query_key": param,
"query_val": val,
"timestamp": time()
})


def not_same_domain(url):
url = urlparse(url).netloc
index = url.find("@")
if index != -1:
url = url[index + 1:]
return url != DOMAIN


class AnalyzeQuery(RequestHandler):
def initialize(self):
pass


async def get(self):
result = db.reference('').get()
self.write(result)

async def post(self):
params = json.loads(self.request.body)
ip = self.request.remote_addr
for param, val in params.items():
# XSS
for pload in XSS:
if pload in val:
send_ref(ip, param, val, 'XSS')
break
# SQLi
if "'" in val and ('and' in val.lower() or 'or' in val.lower()) or '--' in val:
send_ref(ip, param, val, 'SQLi')
# CRLF
if '%0d' in val.lower() or '%0a' in val.lower():
send_ref(ip, param, val, 'CRLF')
# OPEN Redirect
if len([i for i in ['url', 'redirect', 'next'] if i in param.lower()]) > 0 \
and not_same_domain(val):
send_ref(ip, param, val, 'Open Redirect')
# Path Traversal
for pload in TRAVERS:
if pload in val:
send_ref(ip, param, val, 'Path Traversal')
break

return params


class ViralUrls(RequestHandler):
def initialize(self):
pass

async def post(self):
params = json.loads(self.request.body)
malicious = []
for url in params:
post("https://www.virustotal.com/vtapi/v2/url/scan", data={'apikey': VIRUSTOTAL, 'url': url})
res = post("https://www.virustotal.com/vtapi/v2/url/report", data={'apikey': VIRUSTOTAL, 'resource': url})
for i in res.json()['scans'].values():
if i['detected']:
malicious.append(url)
break

return self.write(malicious)


class CSRF(RequestHandler):

def initialize(self,handlers):
self.report = handlers["report"]

async def post(self):
params = json.loads(self.request.body)
self.report(params)
pass
# TODO: send websocket req like:
# The form params['formName'] at params['location'] can be CSRF vulnerable!



class IntrusionDetection(RequestHandler):


def initialize(self):
pass

async def get(self):
params = json.loads(self.request.body)
# TODO
#Get endpoint from params
#increment visit times
#check query params for fuzzy search or intrusion
#send alert in case found

5 changes: 5 additions & 0 deletions application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from ids_service import *


if __name__ == '__main__':
service = IDSService()
81 changes: 81 additions & 0 deletions ids_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import asyncio
from api_endpoints import *
from tornado.ioloop import IOLoop
from tornado.platform.asyncio import AsyncIOMainLoop
from tornado.web import Application
from tornado.httpclient import AsyncHTTPClient
from SangomaUtils.sangoma_authenticators import *
import json
from time import time
from urllib.parse import urlparse
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
from requests import post
from SangomaUtils.sangoma_authenticators import *
import asyncio

WEBSOCKETS_PORT = 6666
TORNADO_PORT = 5555
TORNADO_DEBUG = True

G = {} # Global Dictionary

class IDSService:
def __init__(self):
global G
import SangomaUtils.sangoma_authenticators
SangomaUtils.sangoma_authenticators.setG(G)
self.start_websocket_server(WEBSOCKETS_PORT)
self.application = self.start_tornado()


def start_websocket_server(self,port):
global G
import SangomaUtils.sangoma_authenticators
SangomaUtils.sangoma_authenticators.setG(G)
"""accepts connections from incoming lambda function requests"""
services_authenticator = MonitoringServiceAuthenticator()
services_message_manager = MessageManagerWebsocketFromServices()
G['lambda_connection_handler'] = ConnectionHandler(authenticator=services_authenticator,
message_manager=services_message_manager)
G['lambda_connection_handler'].accept_connections(port=port)


def start_tornado(self):
"""
Starts a Tornado server with specific endpoints specified in the dictionary endpoints.
Each endpoint should have a respective Handler Class implemented in tge tornado_endpoints module.
To initialize the members of the Handler Classes you pass a dictionary after the Class Argument.
:return: Tornado application that was created
"""


urls = [
("/api/query", AnalyzeQuery),
("/api/csrf" , CSRF, dict(
handlers={"report": MessageManagerWebsocketFromServices.report_to_connections})),
('/api/viralurls', ViralUrls)
]

print("Started Tornado")
AsyncIOMainLoop().install() # Allows to use Asyncio main event loop ; https://www.tornadoweb.org/en/branch4.5/asyncio.html
app = Application(urls, debug=TORNADO_DEBUG)
app.listen(TORNADO_PORT)
IOLoop.current().start()
return app


class MessageManagerWebsocketFromServices:

async def process_message(self, connection_and_msg):
'''look at the incoming event (message/command), determine its priority and add it to the eventQ saved
in the global obejct G.'''

@staticmethod
def report_to_connections(event):
global G
print(G['lambda_connection_handler'].connections)
for connection in G['lambda_connection_handler'].connections:
asyncio.ensure_future(G['lambda_connection_handler'].connections[connection].send(event))

0 comments on commit 1b765b6

Please sign in to comment.