Skip to content

Commit 80e5f64

Browse files
committed
1 parent 08e93b5 commit 80e5f64

10 files changed

Lines changed: 560 additions & 0 deletions

File tree

Makefile

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
all: build
3+
#
4+
#
5+
6+
build: copy libinjection/libinjection_wrap.c
7+
rm -f libinjection.py libinjection.pyc
8+
python setup.py --verbose build --force
9+
10+
install: build
11+
sudo python setup.py --verbose install
12+
13+
test-unit: build words.py
14+
python setup.py build_ext --inplace
15+
PYTHON_PATH='.' nosetests -v --with-xunit test_driver.py
16+
17+
.PHONY: test
18+
test: test-unit
19+
20+
.PHONY: speed
21+
speed:
22+
./speedtest.py
23+
24+
25+
words.py: Makefile json2python.py ../src/sqlparse_data.json
26+
./json2python.py < ../src/sqlparse_data.json > words.py
27+
28+
29+
libinjection/libinjection_wrap.c: libinjection/libinjection.i libinjection/libinjection.h libinjection/libinjection_sqli.h
30+
swig -version
31+
swig -python -builtin -Wall -Wextra libinjection/libinjection.i
32+
33+
34+
copy:
35+
cp ../src/libinjection*.h ../src/libinjection*.c libinjection/
36+
37+
.PHONY: copy
38+
39+
libinjection.so: copy
40+
gcc -std=c99 -Wall -Werror -fpic -c libinjection/libinjection_sqli.c
41+
gcc -std=c99 -Wall -Werror -fpic -c libinjection/libinjection_xss.c
42+
gcc -std=c99 -Wall -Werror -fpic -c libinjection/libinjection_html5.c
43+
gcc -dynamiclib -shared -o libinjection.so libinjection_sqli.o libinjection_xss.o libinjection_html5.o
44+
45+
clean:
46+
@rm -rf build dist
47+
@rm -f *.pyc *~ *.so *.o
48+
@rm -f nosetests.xml
49+
@rm -f words.py
50+
@rm -f libinjection/*~ libinjection/*.pyc
51+
@rm -f libinjection/libinjection.h libinjection/libinjection_sqli.h libinjection/libinjection_sqli.c libinjection/libinjection_sqli_data.h
52+
@rm -f libinjection/libinjection_wrap.c libinjection/libinjection.py

apitest.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/python
2+
3+
"""
4+
Work-in-progress
5+
"""
6+
7+
from libinjection import *
8+
from words import words
9+
10+
print dir(libinjection)
11+
12+
def print_token_string(tok):
13+
"""
14+
returns the value of token, handling opening and closing quote characters
15+
"""
16+
out = ''
17+
if tok.str_open != "\0":
18+
out += tok.str_open
19+
out += tok.val
20+
if tok.str_close != "\0":
21+
out += tok.str_close
22+
return out
23+
24+
def print_token(tok):
25+
"""
26+
prints a token for use in unit testing
27+
"""
28+
out = ''
29+
out += tok.type
30+
out += ' '
31+
if tok.type == 's':
32+
out += print_token_string(tok)
33+
elif tok.type == 'v':
34+
vc = tok.count;
35+
if vc == 1:
36+
out += '@'
37+
elif vc == 2:
38+
out += '@@'
39+
out += print_token_string(tok)
40+
else:
41+
out += tok.val
42+
return out
43+
44+
def lookup(state, stype, keyword):
45+
keyword = keyword.upper()
46+
if stype == 'v':
47+
keyword = '0' + keyword
48+
ch = words.get(keyword, '')
49+
return ch
50+
51+
sqli = '1 union all select 1 --'
52+
53+
s = sqli_state()
54+
sqli_init(s, sqli, libinjection.FLAG_QUOTE_NONE | libinjection.FLAG_SQL_ANSI)
55+
sqli_callback(s, lookup)
56+
57+
while sqli_tokenize(s):
58+
print print_token(s.current)

json2python.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2012, 2013 Nick Galbreath
4+
# nickg@client9.com
5+
# BSD License -- see COPYING.txt for details
6+
#
7+
8+
"""
9+
Converts a libinjection JSON data file to python dict
10+
"""
11+
12+
def toc(obj):
13+
""" main routine """
14+
15+
print """
16+
import libinjection
17+
18+
def lookup(state, stype, keyword):
19+
keyword = keyword.upper()
20+
if stype == libinjection.LOOKUP_FINGERPRINT:
21+
if keyword in fingerprints and libinjection.sqli_not_whitelist(state):
22+
return 'F'
23+
else:
24+
return chr(0)
25+
return words.get(keyword, chr(0))
26+
27+
"""
28+
29+
words = {}
30+
keywords = obj['keywords']
31+
for k,v in keywords.iteritems():
32+
words[str(k)] = str(v)
33+
34+
print 'words = {'
35+
for k in sorted(words.keys()):
36+
print "'{0}': '{1}',".format(k, words[k])
37+
print '}\n'
38+
39+
40+
keywords = obj['fingerprints']
41+
print 'fingerprints = set(['
42+
for k in sorted(keywords):
43+
print "'{0}',".format(k.upper())
44+
print '])'
45+
46+
return 0
47+
48+
if __name__ == '__main__':
49+
import sys
50+
import json
51+
sys.exit(toc(json.load(sys.stdin)))
52+

libinjection/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from libinjection import *

libinjection/libinjection.i

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/* libinjection.i SWIG interface file */
2+
%module libinjection
3+
%{
4+
#include "libinjection.h"
5+
#include "libinjection_sqli.h"
6+
#include <stddef.h>
7+
8+
/* This is the callback function that runs a python function
9+
*
10+
*/
11+
static char libinjection_python_check_fingerprint(sfilter* sf, int lookuptype, const char* word, size_t len)
12+
{
13+
PyObject *fp;
14+
PyObject *arglist;
15+
PyObject *result;
16+
const char* strtype;
17+
char ch;
18+
19+
// get sfilter->pattern
20+
// convert to python string
21+
fp = SWIG_InternalNewPointerObj((void*)sf, SWIGTYPE_p_libinjection_sqli_state,0);
22+
23+
arglist = Py_BuildValue("(Nis#)", fp, lookuptype, word, len);
24+
// call pyfunct with string arg
25+
result = PyObject_CallObject((PyObject*) sf->userdata, arglist);
26+
Py_DECREF(arglist);
27+
if (result == NULL) {
28+
printf("GOT NULL\n");
29+
// python call has an exception
30+
// pass it back
31+
ch = '\0';
32+
} else {
33+
// convert value of python call to a char
34+
strtype = PyString_AsString(result);
35+
ch = strtype[0];
36+
Py_DECREF(result);
37+
}
38+
return ch;
39+
}
40+
41+
%}
42+
%include "typemaps.i"
43+
44+
// The C functions all start with 'libinjection_' as a namespace
45+
// We don't need this since it's in the libinjection python package
46+
// i.e. libinjection.libinjection_is_sqli --> libinjection.is_sqli
47+
//
48+
%rename("%(strip:[libinjection_])s") "";
49+
50+
// SWIG doesn't natively support fixed sized arrays.
51+
// this typemap converts the fixed size array sfilter.tokevec
52+
// into a list of pointers to stoken_t types. In otherword this code makes this example work
53+
// s = sfilter()
54+
// libinjection_is_sqli(s, "a string",...)
55+
// for i in len(s.pat):
56+
// print s.tokevec[i].val
57+
//
58+
59+
%typemap(out) stoken_t [ANY] {
60+
int i;
61+
$result = PyList_New($1_dim0);
62+
for (i = 0; i < $1_dim0; i++) {
63+
PyObject *o = SWIG_NewPointerObj((void*)(& $1[i]), SWIGTYPE_p_stoken_t,0);
64+
PyList_SetItem($result,i,o);
65+
}
66+
}
67+
68+
// automatically append string length into arg array
69+
%apply (char *STRING, size_t LENGTH) { (const char *s, size_t slen) };
70+
71+
%typemap(in) (ptr_lookup_fn fn, void* userdata) {
72+
if ($input == Py_None) {
73+
$1 = NULL;
74+
$2 = NULL;
75+
} else {
76+
$1 = libinjection_python_check_fingerprint;
77+
$2 = $input;
78+
}
79+
}
80+
%include "libinjection.h"
81+
%include "libinjection_sqli.h"

libinjection/sqli_fingerprints.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
sqli_fingerprints = set([
3+
'1234'
4+
])

pytest.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python
2+
3+
from libinjection import *
4+
5+
sqli= "1 UNION ALL SELECT * FROM FOO"
6+
7+
if False:
8+
s = sfilter()
9+
print sqli_fingerprint(s, sqli, CHAR_NULL, COMMENTS_ANSI)
10+
print "----"
11+
12+
if False:
13+
s = sfilter()
14+
current = stoken_t()
15+
sqli_init(s, sqli, CHAR_NULL, COMMENTS_ANSI)
16+
while sqli_tokenize(s, current):
17+
print current.type, current.val
18+
print "----"
19+
20+
def is_pattern(state):
21+
return sqli_blacklist(state) and sqli_not_whitelist(state)
22+
23+
s = sfilter()
24+
25+
if is_sqli(s, sqli, None):
26+
print "IS SQLI"
27+
print len(s.pat)
28+
print s.current.val
29+
print s.current.type
30+
vec = s.tokenvec
31+
for i in range(len(s.pat)):
32+
atoken = vec[i]
33+
print atoken.type, atoken.val
34+
else:
35+
print "IS NOT SQLI"

setup.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""
2+
libinjection module for python
3+
4+
Copyright 2012, 2013, 2014 Nick Galbreath
5+
nickg@client9.com
6+
BSD License -- see COPYING.txt for details
7+
"""
8+
try:
9+
from setuptools import setup, Extension
10+
except ImportError:
11+
from distutils.core import setup, Extension
12+
13+
MODULE = Extension(
14+
'_libinjection', [
15+
'libinjection/libinjection_wrap.c',
16+
'libinjection/libinjection_sqli.c',
17+
'libinjection/libinjection_html5.c',
18+
'libinjection/libinjection_xss.c'
19+
],
20+
swig_opts=['-Wextra', '-builtin'],
21+
define_macros = [],
22+
include_dirs = [],
23+
libraries = [],
24+
library_dirs = [],
25+
)
26+
27+
setup (
28+
name = 'libinjection',
29+
version = '3.9.1',
30+
description = 'Wrapper around libinjection c-code to detect sqli',
31+
author = 'Nick Galbreath',
32+
author_email = 'nickg@client9.com',
33+
url = 'https://libinjection.client9.com/',
34+
ext_modules = [MODULE],
35+
packages = ['libinjection'],
36+
long_description = '''
37+
wrapper around libinjection
38+
''',
39+
classifiers = [
40+
'Intended Audience :: Developers',
41+
'License :: OSI Approved :: BSD License',
42+
'Topic :: Database',
43+
'Topic :: Security',
44+
'Operating System :: OS Independent',
45+
'Development Status :: 3 - Alpha',
46+
'Topic :: Internet :: Log Analysis',
47+
'Topic :: Internet :: WWW/HTTP'
48+
]
49+
)

0 commit comments

Comments
 (0)