Merge pull request #141 from client9/remotes/trunk

libinjection sync to v3.6.0
This commit is contained in:
Breno Silva 2013-09-16 10:06:25 -07:00
commit 9a630eea23
3 changed files with 608 additions and 831 deletions

View File

@ -19,7 +19,7 @@ extern "C" {
* See python's normalized version * See python's normalized version
* http://www.python.org/dev/peps/pep-0386/#normalizedversion * http://www.python.org/dev/peps/pep-0386/#normalizedversion
*/ */
#define LIBINJECTION_VERSION "3.5.3" #define LIBINJECTION_VERSION "3.6.0"
/** /**
* Libinjection's sqli module makes a "normalized" * Libinjection's sqli module makes a "normalized"
@ -59,7 +59,7 @@ enum lookup_type {
LOOKUP_FINGERPRINT LOOKUP_FINGERPRINT
}; };
typedef struct { struct libinjection_sqli_token {
#ifdef SWIG #ifdef SWIG
%immutable; %immutable;
#endif #endif
@ -81,8 +81,9 @@ typedef struct {
int count; int count;
char val[LIBINJECTION_SQLI_TOKEN_SIZE]; char val[LIBINJECTION_SQLI_TOKEN_SIZE];
} stoken_t; };
typedef struct libinjection_sqli_token stoken_t;
/** /**
* Pointer to function, takes cstr input, * Pointer to function, takes cstr input,
@ -91,7 +92,7 @@ typedef struct {
struct libinjection_sqli_state; struct libinjection_sqli_state;
typedef char (*ptr_lookup_fn)(struct libinjection_sqli_state*, int lookuptype, const char* word, size_t len); typedef char (*ptr_lookup_fn)(struct libinjection_sqli_state*, int lookuptype, const char* word, size_t len);
typedef struct libinjection_sqli_state { struct libinjection_sqli_state {
#ifdef SWIG #ifdef SWIG
%immutable; %immutable;
#endif #endif
@ -123,15 +124,19 @@ typedef struct libinjection_sqli_state {
*/ */
size_t pos; size_t pos;
#ifndef SWIG
/* for SWIG.. don't use this.. use functional API instead */
/* MAX TOKENS + 1 since we use one extra token /* MAX TOKENS + 1 since we use one extra token
* to determine the type of the previous token * to determine the type of the previous token
*/ */
stoken_t tokenvec[LIBINJECTION_SQLI_BUFFER_SZ]; struct libinjection_sqli_token tokenvec[LIBINJECTION_SQLI_BUFFER_SZ];
#endif
/* /*
* Pointer to token position in tokenvec, above * Pointer to token position in tokenvec, above
*/ */
stoken_t *current; struct libinjection_sqli_token *current;
/* /*
* fingerprint pattern c-string * fingerprint pattern c-string
@ -189,12 +194,18 @@ typedef struct libinjection_sqli_state {
*/ */
int stats_tokens; int stats_tokens;
} sfilter; };
struct libinjection_sqli_token* libinjection_sqli_get_token(
struct libinjection_sqli_state* sqlistate, int i);
typedef struct libinjection_sqli_state sfilter;
/** /**
* *
*/ */
void libinjection_sqli_init(sfilter* sql_state, void libinjection_sqli_init(struct libinjection_sqli_state* sql_state,
const char* s, size_t slen, const char* s, size_t slen,
int flags); int flags);
@ -212,18 +223,21 @@ void libinjection_sqli_init(sfilter* sql_state,
* *
* \return 1 (true) if SQLi, 0 (false) if benign * \return 1 (true) if SQLi, 0 (false) if benign
*/ */
int libinjection_is_sqli(sfilter * sql_state); int libinjection_is_sqli(struct libinjection_sqli_state* sql_state);
/* FOR H@CKERS ONLY /* FOR H@CKERS ONLY
* *
*/ */
void libinjection_sqli_callback(sfilter* sql_state, ptr_lookup_fn fn, void* userdata); void libinjection_sqli_callback(struct libinjection_sqli_state* sql_state,
ptr_lookup_fn fn,
void* userdata);
/* /*
* Resets state, but keeps initial string and callbacks * Resets state, but keeps initial string and callbacks
*/ */
void libinjection_sqli_reset(sfilter* sql_state, int flags); void libinjection_sqli_reset(struct libinjection_sqli_state* sql_state,
int flags);
/** /**
* *
@ -239,14 +253,17 @@ void libinjection_sqli_reset(sfilter* sql_state, int flags);
* do not free! * do not free!
* *
*/ */
const char* libinjection_sqli_fingerprint(sfilter * sql_state, int flags); const char* libinjection_sqli_fingerprint(struct libinjection_sqli_state* sql_state,
int flags);
/** /**
* The default "word" to token-type or fingerprint function. This * The default "word" to token-type or fingerprint function. This
* uses a ASCII case-insensitive binary tree. * uses a ASCII case-insensitive binary tree.
*/ */
char libinjection_sqli_lookup_word(sfilter *sql_state, int lookup_type, char libinjection_sqli_lookup_word(struct libinjection_sqli_state* sql_state,
const char* s, size_t slen); int lookup_type,
const char* s,
size_t slen);
/* Streaming tokenization interface. /* Streaming tokenization interface.
* *
@ -255,13 +272,13 @@ char libinjection_sqli_lookup_word(sfilter *sql_state, int lookup_type,
* \returns 1, has a token, keep going, or 0 no tokens * \returns 1, has a token, keep going, or 0 no tokens
* *
*/ */
int libinjection_sqli_tokenize(sfilter * sql_state); int libinjection_sqli_tokenize(struct libinjection_sqli_state * sql_state);
/** /**
* parses and folds input, up to 5 tokens * parses and folds input, up to 5 tokens
* *
*/ */
int libinjection_sqli_fold(sfilter * sql_state); int libinjection_sqli_fold(struct libinjection_sqli_state * sql_state);
/** The built-in default function to match fingerprints /** The built-in default function to match fingerprints
* and do false negative/positive analysis. This calls the following * and do false negative/positive analysis. This calls the following
@ -272,20 +289,20 @@ int libinjection_sqli_fold(sfilter * sql_state);
* *
* \param sql_state should be filled out after libinjection_sqli_fingerprint is called * \param sql_state should be filled out after libinjection_sqli_fingerprint is called
*/ */
int libinjection_sqli_check_fingerprint(sfilter *sql_state); int libinjection_sqli_check_fingerprint(struct libinjection_sqli_state * sql_state);
/* Given a pattern determine if it's a SQLi pattern. /* Given a pattern determine if it's a SQLi pattern.
* *
* \return TRUE if sqli, false otherwise * \return TRUE if sqli, false otherwise
*/ */
int libinjection_sqli_blacklist(sfilter* sql_state); int libinjection_sqli_blacklist(struct libinjection_sqli_state* sql_state);
/* Given a positive match for a pattern (i.e. pattern is SQLi), this function /* Given a positive match for a pattern (i.e. pattern is SQLi), this function
* does additional analysis to reduce false positives. * does additional analysis to reduce false positives.
* *
* \return TRUE if sqli, false otherwise * \return TRUE if sqli, false otherwise
*/ */
int libinjection_sqli_not_whitelist(sfilter* sql_state); int libinjection_sqli_not_whitelist(struct libinjection_sqli_state * sql_state);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -342,12 +342,12 @@ static int st_is_unary_op(const stoken_t * st)
* *
*/ */
static size_t parse_white(sfilter * sf) static size_t parse_white(struct libinjection_sqli_state * sf)
{ {
return sf->pos + 1; return sf->pos + 1;
} }
static size_t parse_operator1(sfilter * sf) static size_t parse_operator1(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
size_t pos = sf->pos; size_t pos = sf->pos;
@ -356,7 +356,7 @@ static size_t parse_operator1(sfilter * sf)
return pos + 1; return pos + 1;
} }
static size_t parse_other(sfilter * sf) static size_t parse_other(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
size_t pos = sf->pos; size_t pos = sf->pos;
@ -365,7 +365,7 @@ static size_t parse_other(sfilter * sf)
return pos + 1; return pos + 1;
} }
static size_t parse_char(sfilter * sf) static size_t parse_char(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
size_t pos = sf->pos; size_t pos = sf->pos;
@ -374,7 +374,7 @@ static size_t parse_char(sfilter * sf)
return pos + 1; return pos + 1;
} }
static size_t parse_eol_comment(sfilter * sf) static size_t parse_eol_comment(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
const size_t slen = sf->slen; const size_t slen = sf->slen;
@ -394,7 +394,7 @@ static size_t parse_eol_comment(sfilter * sf)
/** In Ansi mode, hash is an operator /** In Ansi mode, hash is an operator
* In MYSQL mode, it's a EOL comment like '--' * In MYSQL mode, it's a EOL comment like '--'
*/ */
static size_t parse_hash(sfilter * sf) static size_t parse_hash(struct libinjection_sqli_state * sf)
{ {
sf->stats_comment_hash += 1; sf->stats_comment_hash += 1;
if (sf->flags & FLAG_SQL_MYSQL) { if (sf->flags & FLAG_SQL_MYSQL) {
@ -406,7 +406,7 @@ static size_t parse_hash(sfilter * sf)
} }
} }
static size_t parse_dash(sfilter * sf) static size_t parse_dash(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
const size_t slen = sf->slen; const size_t slen = sf->slen;
@ -478,7 +478,7 @@ static size_t is_mysql_comment(const char *cs, const size_t len, size_t pos)
return 1; return 1;
} }
static size_t parse_slash(sfilter * sf) static size_t parse_slash(struct libinjection_sqli_state * sf)
{ {
size_t clen; size_t clen;
const char *cs = sf->s; const char *cs = sf->s;
@ -528,7 +528,7 @@ static size_t parse_slash(sfilter * sf)
} }
static size_t parse_backslash(sfilter * sf) static size_t parse_backslash(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
const size_t slen = sf->slen; const size_t slen = sf->slen;
@ -546,7 +546,7 @@ static size_t parse_backslash(sfilter * sf)
} }
} }
static size_t parse_operator2(sfilter * sf) static size_t parse_operator2(struct libinjection_sqli_state * sf)
{ {
char ch; char ch;
const char *cs = sf->s; const char *cs = sf->s;
@ -681,7 +681,7 @@ static size_t parse_string_core(const char *cs, const size_t len, size_t pos,
/** /**
* Used when first char is a ' or " * Used when first char is a ' or "
*/ */
static size_t parse_string(sfilter * sf) static size_t parse_string(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
const size_t slen = sf->slen; const size_t slen = sf->slen;
@ -698,7 +698,7 @@ static size_t parse_string(sfilter * sf)
* N or n: mysql "National Character set" * N or n: mysql "National Character set"
* E : psql "Escaped String" * E : psql "Escaped String"
*/ */
static size_t parse_estring(sfilter * sf) static size_t parse_estring(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
const size_t slen = sf->slen; const size_t slen = sf->slen;
@ -710,7 +710,7 @@ static size_t parse_estring(sfilter * sf)
return parse_string_core(cs, slen, pos, sf->current, CHAR_SINGLE, 2); return parse_string_core(cs, slen, pos, sf->current, CHAR_SINGLE, 2);
} }
static size_t parse_ustring(sfilter * sf) static size_t parse_ustring(struct libinjection_sqli_state * sf)
{ {
const char *cs = sf->s; const char *cs = sf->s;
size_t slen = sf->slen; size_t slen = sf->slen;
@ -729,7 +729,7 @@ static size_t parse_ustring(sfilter * sf)
} }
} }
static size_t parse_qstring_core(sfilter * sf, int offset) static size_t parse_qstring_core(struct libinjection_sqli_state * sf, int offset)
{ {
char ch; char ch;
const char *strend; const char *strend;
@ -782,7 +782,7 @@ static size_t parse_qstring_core(sfilter * sf, int offset)
/* /*
* Oracle's q string * Oracle's q string
*/ */
static size_t parse_qstring(sfilter * sf) static size_t parse_qstring(struct libinjection_sqli_state * sf)
{ {
return parse_qstring_core(sf, 0); return parse_qstring_core(sf, 0);
} }
@ -791,7 +791,7 @@ static size_t parse_qstring(sfilter * sf)
* mysql's N'STRING' or * mysql's N'STRING' or
* ... Oracle's nq string * ... Oracle's nq string
*/ */
static size_t parse_nqstring(sfilter * sf) static size_t parse_nqstring(struct libinjection_sqli_state * sf)
{ {
size_t slen = sf->slen; size_t slen = sf->slen;
size_t pos = sf->pos; size_t pos = sf->pos;
@ -805,7 +805,7 @@ static size_t parse_nqstring(sfilter * sf)
* binary literal string * binary literal string
* re: [bB]'[01]*' * re: [bB]'[01]*'
*/ */
static size_t parse_bstring(sfilter *sf) static size_t parse_bstring(struct libinjection_sqli_state *sf)
{ {
size_t wlen; size_t wlen;
const char *cs = sf->s; const char *cs = sf->s;
@ -834,7 +834,7 @@ static size_t parse_bstring(sfilter *sf)
* mysql has requirement of having EVEN number of chars, * mysql has requirement of having EVEN number of chars,
* but pgsql does not * but pgsql does not
*/ */
static size_t parse_xstring(sfilter *sf) static size_t parse_xstring(struct libinjection_sqli_state *sf)
{ {
size_t wlen; size_t wlen;
const char *cs = sf->s; const char *cs = sf->s;
@ -857,7 +857,7 @@ static size_t parse_xstring(sfilter *sf)
return pos + 2 + wlen + 1; return pos + 2 + wlen + 1;
} }
static size_t parse_word(sfilter * sf) static size_t parse_word(struct libinjection_sqli_state * sf)
{ {
char ch; char ch;
char delim; char delim;
@ -907,7 +907,7 @@ static size_t parse_word(sfilter * sf)
* and a bare word. * and a bare word.
* *
*/ */
static size_t parse_tick(sfilter* sf) static size_t parse_tick(struct libinjection_sqli_state* sf)
{ {
size_t pos = parse_string_core(sf->s, sf->slen, sf->pos, sf->current, CHAR_TICK, 1); size_t pos = parse_string_core(sf->s, sf->slen, sf->pos, sf->current, CHAR_TICK, 1);
@ -933,7 +933,7 @@ static size_t parse_tick(sfilter* sf)
return pos; return pos;
} }
static size_t parse_var(sfilter * sf) static size_t parse_var(struct libinjection_sqli_state * sf)
{ {
size_t xlen; size_t xlen;
const char *cs = sf->s; const char *cs = sf->s;
@ -985,7 +985,7 @@ static size_t parse_var(sfilter * sf)
} }
} }
static size_t parse_money(sfilter *sf) static size_t parse_money(struct libinjection_sqli_state *sf)
{ {
size_t xlen; size_t xlen;
const char* strend; const char* strend;
@ -1063,7 +1063,7 @@ static size_t parse_money(sfilter *sf)
} }
} }
static size_t parse_number(sfilter * sf) static size_t parse_number(struct libinjection_sqli_state * sf)
{ {
size_t xlen; size_t xlen;
size_t start; size_t start;
@ -1165,7 +1165,7 @@ static size_t parse_number(sfilter * sf)
return pos; return pos;
} }
int libinjection_sqli_tokenize(sfilter * sf) int libinjection_sqli_tokenize(struct libinjection_sqli_state * sf)
{ {
pt2Function fnptr; pt2Function fnptr;
size_t *pos = &sf->pos; size_t *pos = &sf->pos;
@ -1228,13 +1228,13 @@ int libinjection_sqli_tokenize(sfilter * sf)
return FALSE; return FALSE;
} }
void libinjection_sqli_init(sfilter * sf, const char *s, size_t len, int flags) void libinjection_sqli_init(struct libinjection_sqli_state * sf, const char *s, size_t len, int flags)
{ {
if (flags == 0) { if (flags == 0) {
flags = FLAG_QUOTE_NONE | FLAG_SQL_ANSI; flags = FLAG_QUOTE_NONE | FLAG_SQL_ANSI;
} }
memset(sf, 0, sizeof(sfilter)); memset(sf, 0, sizeof(struct libinjection_sqli_state));
sf->s = s; sf->s = s;
sf->slen = len; sf->slen = len;
sf->lookup = libinjection_sqli_lookup_word; sf->lookup = libinjection_sqli_lookup_word;
@ -1243,7 +1243,7 @@ void libinjection_sqli_init(sfilter * sf, const char *s, size_t len, int flags)
sf->current = &(sf->tokenvec[0]); sf->current = &(sf->tokenvec[0]);
} }
void libinjection_sqli_reset(sfilter * sf, int flags) void libinjection_sqli_reset(struct libinjection_sqli_state * sf, int flags)
{ {
ptr_lookup_fn lookup = sf->lookup;; ptr_lookup_fn lookup = sf->lookup;;
void *userdata = sf->userdata; void *userdata = sf->userdata;
@ -1256,7 +1256,7 @@ void libinjection_sqli_reset(sfilter * sf, int flags)
sf->userdata = userdata; sf->userdata = userdata;
} }
void libinjection_sqli_callback(sfilter * sf, ptr_lookup_fn fn, void* userdata) void libinjection_sqli_callback(struct libinjection_sqli_state * sf, ptr_lookup_fn fn, void* userdata)
{ {
if (fn == NULL) { if (fn == NULL) {
sf->lookup = libinjection_sqli_lookup_word; sf->lookup = libinjection_sqli_lookup_word;
@ -1283,7 +1283,7 @@ void libinjection_sqli_callback(sfilter * sf, ptr_lookup_fn fn, void* userdata)
* This is just: multikeywords[token.value + ' ' + token2.value] * This is just: multikeywords[token.value + ' ' + token2.value]
* *
*/ */
static int syntax_merge_words(sfilter * sf,stoken_t * a, stoken_t * b) static int syntax_merge_words(struct libinjection_sqli_state * sf,stoken_t * a, stoken_t * b)
{ {
size_t sz1; size_t sz1;
size_t sz2; size_t sz2;
@ -1335,7 +1335,7 @@ static int syntax_merge_words(sfilter * sf,stoken_t * a, stoken_t * b)
} }
} }
int libinjection_sqli_fold(sfilter * sf) int libinjection_sqli_fold(struct libinjection_sqli_state * sf)
{ {
stoken_t last_comment; stoken_t last_comment;
@ -1547,6 +1547,7 @@ int libinjection_sqli_fold(sfilter * sf)
} else if (sf->tokenvec[left].type == TYPE_SQLTYPE && } else if (sf->tokenvec[left].type == TYPE_SQLTYPE &&
(sf->tokenvec[left+1].type == TYPE_BAREWORD || (sf->tokenvec[left+1].type == TYPE_BAREWORD ||
sf->tokenvec[left+1].type == TYPE_NUMBER || sf->tokenvec[left+1].type == TYPE_NUMBER ||
sf->tokenvec[left+1].type == TYPE_FUNCTION ||
sf->tokenvec[left+1].type == TYPE_VARIABLE || sf->tokenvec[left+1].type == TYPE_VARIABLE ||
sf->tokenvec[left+1].type == TYPE_STRING)) { sf->tokenvec[left+1].type == TYPE_STRING)) {
st_copy(&sf->tokenvec[left], &sf->tokenvec[left+1]); st_copy(&sf->tokenvec[left], &sf->tokenvec[left+1]);
@ -1585,6 +1586,11 @@ int libinjection_sqli_fold(sfilter * sf)
pos -= 1; pos -= 1;
sf->stats_folds += 1; sf->stats_folds += 1;
continue; continue;
} else if (sf->tokenvec[left].type == TYPE_SQLTYPE &&
sf->tokenvec[left+1].type == TYPE_SQLTYPE) {
pos -= 1;
sf->stats_folds += 1;
continue;
} else if (sf->tokenvec[left].type == TYPE_LEFTBRACE && } else if (sf->tokenvec[left].type == TYPE_LEFTBRACE &&
sf->tokenvec[left+1].type == TYPE_BAREWORD) { sf->tokenvec[left+1].type == TYPE_BAREWORD) {
/* weird ODBC / MYSQL {foo expr} --> expr /* weird ODBC / MYSQL {foo expr} --> expr
@ -1786,7 +1792,7 @@ int libinjection_sqli_fold(sfilter * sf)
* double quote. * double quote.
* *
*/ */
const char* libinjection_sqli_fingerprint(sfilter * sql_state, int flags) const char* libinjection_sqli_fingerprint(struct libinjection_sqli_state * sql_state, int flags)
{ {
int i; int i;
int tlen = 0; int tlen = 0;
@ -1851,13 +1857,13 @@ const char* libinjection_sqli_fingerprint(sfilter * sql_state, int flags)
*/ */
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
int libinjection_sqli_check_fingerprint(sfilter* sql_state) int libinjection_sqli_check_fingerprint(struct libinjection_sqli_state* sql_state)
{ {
return libinjection_sqli_blacklist(sql_state) && return libinjection_sqli_blacklist(sql_state) &&
libinjection_sqli_not_whitelist(sql_state); libinjection_sqli_not_whitelist(sql_state);
} }
char libinjection_sqli_lookup_word(sfilter *sql_state, int lookup_type, char libinjection_sqli_lookup_word(struct libinjection_sqli_state *sql_state, int lookup_type,
const char* str, size_t len) const char* str, size_t len)
{ {
if (lookup_type == LOOKUP_FINGERPRINT) { if (lookup_type == LOOKUP_FINGERPRINT) {
@ -1867,7 +1873,7 @@ char libinjection_sqli_lookup_word(sfilter *sql_state, int lookup_type,
} }
} }
int libinjection_sqli_blacklist(sfilter* sql_state) int libinjection_sqli_blacklist(struct libinjection_sqli_state* sql_state)
{ {
/* /*
* use minimum of 8 bytes to make sure gcc -fstack-protector * use minimum of 8 bytes to make sure gcc -fstack-protector
@ -1919,7 +1925,7 @@ int libinjection_sqli_blacklist(sfilter* sql_state)
/* /*
* return TRUE if sqli, false is benign * return TRUE if sqli, false is benign
*/ */
int libinjection_sqli_not_whitelist(sfilter* sql_state) int libinjection_sqli_not_whitelist(struct libinjection_sqli_state* sql_state)
{ {
/* /*
* We assume we got a SQLi match * We assume we got a SQLi match
@ -2117,13 +2123,25 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state)
* *
* *
*/ */
static int reparse_as_mysql(sfilter * sql_state) static int reparse_as_mysql(struct libinjection_sqli_state * sql_state)
{ {
return sql_state->stats_comment_ddx || return sql_state->stats_comment_ddx ||
sql_state->stats_comment_hash; sql_state->stats_comment_hash;
} }
int libinjection_is_sqli(sfilter * sql_state) /*
* This function is mostly use with SWIG
*/
struct libinjection_sqli_token* libinjection_sqli_get_token(struct libinjection_sqli_state * sql_state,
int i)
{
if (i < 0 || i > (int) strlen(sql_state->fingerprint)) {
return NULL;
}
return &(sql_state->tokenvec[i]);
}
int libinjection_is_sqli(struct libinjection_sqli_state * sql_state)
{ {
const char *s = sql_state->s; const char *s = sql_state->s;
size_t slen = sql_state->slen; size_t slen = sql_state->slen;

File diff suppressed because it is too large Load Diff