2016-08-02 15:43:11 +02:00
#!/usr/bin/env python2
# -*-coding:UTF-8 -*
"""
2016-08-10 09:06:37 +02:00
Sql Injection module
2016-08-02 15:43:11 +02:00
"""
import time
import string
import urllib2
import re
from pubsublogger import publisher
from Helper import Process
from packages import Paste
from pyfaup . faup import Faup
# Config Var
regex_injection = [ ]
word_injection = [ ]
2016-08-10 09:06:37 +02:00
word_injection_suspect = [ ]
2016-08-02 15:43:11 +02:00
# Classic atome injection
regex_injection1 = " ([[AND |OR ]+[ \' | \" ]?[0-9a-zA-Z]+[ \' | \" ]?=[ \' | \" ]?[0-9a-zA-Z]+[ \' | \" ]?]) "
regex_injection . append ( regex_injection1 )
# Time-based attack
regex_injection2 = [ " SLEEP \ ([0-9]+ " , " BENCHMARK \ ([0-9]+ " , " WAIT FOR DELAY " , " WAITFOR DELAY " ]
regex_injection2 = re . compile ( ' | ' . join ( regex_injection2 ) )
regex_injection . append ( regex_injection2 )
# Interesting keyword
word_injection1 = [ " IF " , " ELSE " , " CASE " , " WHEN " , " END " , " UNION " , " SELECT " , " FROM " , " ORDER BY " , " WHERE " , " DELETE " , " DROP " , " UPDATE " , " EXEC " ]
word_injection . append ( word_injection1 )
# Database special keywords
2016-08-10 09:06:37 +02:00
word_injection2 = [ " @@version " , " POW( " , " BITAND( " , " SQUARE( " ]
word_injection . append ( word_injection2 )
2016-08-02 15:43:11 +02:00
# Html keywords
2016-08-10 09:06:37 +02:00
word_injection3 = [ " <script> " ]
word_injection . append ( word_injection3 )
2016-08-02 15:43:11 +02:00
# Suspect char
2016-08-10 09:06:37 +02:00
word_injection_suspect1 = [ " \' " , " \" " , " ; " , " < " , " > " ]
2016-08-10 14:23:36 +02:00
word_injection_suspect + = word_injection_suspect1
2016-08-02 15:43:11 +02:00
2016-08-10 09:06:37 +02:00
# Comment
word_injection_suspect2 = [ " -- " , " # " , " /* " ]
2016-08-10 14:23:36 +02:00
word_injection_suspect + = word_injection_suspect2
2016-08-02 15:43:11 +02:00
def analyse ( url , path ) :
faup . decode ( url )
url_parsed = faup . get ( )
resource_path = url_parsed [ ' resource_path ' ]
query_string = url_parsed [ ' query_string ' ]
result_path = 0
result_query = 0
if resource_path is not None :
result_path = is_sql_injection ( resource_path )
if query_string is not None :
result_query = is_sql_injection ( query_string )
if ( result_path > 0 ) or ( result_query > 0 ) :
paste = Paste . Paste ( path )
if ( result_path > 1 ) or ( result_query > 1 ) :
print " Detected SQL in URL: "
2016-08-02 16:21:52 +02:00
print urllib2 . unquote ( url )
2016-10-27 11:50:24 +02:00
to_print = ' SQLInjection; {} ; {} ; {} ; {} ; {} ' . format ( paste . p_source , paste . p_date , paste . p_name , " Detected SQL in URL " , paste . p_path )
2016-08-02 15:43:11 +02:00
publisher . warning ( to_print )
2016-08-08 09:17:44 +02:00
#Send to duplicate
p . populate_set_out ( path , ' Duplicate ' )
#send to Browse_warning_paste
2016-08-09 11:59:36 +02:00
p . populate_set_out ( ' sqlinjection; {} ' . format ( path ) , ' BrowseWarningPaste ' )
2016-08-10 09:06:37 +02:00
else :
2016-08-02 15:43:11 +02:00
print " Potential SQL injection: "
2016-08-02 16:21:52 +02:00
print urllib2 . unquote ( url )
2017-02-14 11:23:34 +01:00
to_print = ' SQLInjection; {} ; {} ; {} ; {} ; {} ' . format ( paste . p_source , paste . p_date , paste . p_name , " Potential SQL injection " , paste . p_path )
2016-08-02 15:43:11 +02:00
publisher . info ( to_print )
2016-08-10 09:06:37 +02:00
# Try to detect if the url passed might be an sql injection by appliying the regex
# defined above on it.
2016-08-02 15:43:11 +02:00
def is_sql_injection ( url_parsed ) :
line = urllib2 . unquote ( url_parsed )
line = string . upper ( line )
result = [ ]
result_suspect = [ ]
for regex in regex_injection :
temp_res = re . findall ( regex , line )
if len ( temp_res ) > 0 :
result . append ( temp_res )
for word_list in word_injection :
for word in word_list :
temp_res = string . find ( line , string . upper ( word ) )
if temp_res != - 1 :
result . append ( line [ temp_res : temp_res + len ( word ) ] )
for word in word_injection_suspect :
temp_res = string . find ( line , string . upper ( word ) )
if temp_res != - 1 :
result_suspect . append ( line [ temp_res : temp_res + len ( word ) ] )
if len ( result ) > 0 :
print result
return 2
elif len ( result_suspect ) > 0 :
print result_suspect
return 1
else :
return 0
if __name__ == ' __main__ ' :
# If you wish to use an other port of channel, do not forget to run a subscriber accordingly (see launch_logs.sh)
# Port of the redis instance used by pubsublogger
publisher . port = 6380
# Script is the default channel used for the modules.
publisher . channel = ' Script '
# Section name in bin/packages/modules.cfg
config_section = ' SQLInjectionDetection '
# Setup the I/O queues
p = Process ( config_section )
# Sent to the logging a description of the module
publisher . info ( " Try to detect SQL injection " )
faup = Faup ( )
# Endless loop getting messages from the input queue
while True :
# Get one message from the input queue
message = p . get_from_set ( )
if message is None :
publisher . debug ( " {} queue is empty, waiting " . format ( config_section ) )
time . sleep ( 10 )
continue
else :
# Do something with the message from the queue
url , date , path = message . split ( )
2016-08-10 09:06:37 +02:00
analyse ( url , path )