Initial Commit
This commit is contained in:
314
naxsi-0.55.3/naxsi_src/ext/libinjection/reader.c
Normal file
314
naxsi-0.55.3/naxsi_src/ext/libinjection/reader.c
Normal file
@@ -0,0 +1,314 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "libinjection.h"
|
||||
#include "libinjection_sqli.h"
|
||||
#include "libinjection_xss.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
static int g_test_ok = 0;
|
||||
static int g_test_fail = 0;
|
||||
|
||||
typedef enum {
|
||||
MODE_SQLI,
|
||||
MODE_XSS
|
||||
} detect_mode_t;
|
||||
|
||||
static void usage(const char* argv[]);
|
||||
size_t modp_rtrim(char* str, size_t len);
|
||||
void modp_toprint(char* str, size_t len);
|
||||
void test_positive(FILE * fd, const char *fname, detect_mode_t mode,
|
||||
int flag_invert, int flag_true, int flag_quiet);
|
||||
|
||||
int urlcharmap(char ch);
|
||||
size_t modp_url_decode(char* dest, const char* s, size_t len);
|
||||
|
||||
int urlcharmap(char ch) {
|
||||
switch (ch) {
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
case 'a': case 'A': return 10;
|
||||
case 'b': case 'B': return 11;
|
||||
case 'c': case 'C': return 12;
|
||||
case 'd': case 'D': return 13;
|
||||
case 'e': case 'E': return 14;
|
||||
case 'f': case 'F': return 15;
|
||||
default:
|
||||
return 256;
|
||||
}
|
||||
}
|
||||
|
||||
size_t modp_url_decode(char* dest, const char* s, size_t len)
|
||||
{
|
||||
const char* deststart = dest;
|
||||
|
||||
size_t i = 0;
|
||||
int d = 0;
|
||||
while (i < len) {
|
||||
switch (s[i]) {
|
||||
case '+':
|
||||
*dest++ = ' ';
|
||||
i += 1;
|
||||
break;
|
||||
case '%':
|
||||
if (i+2 < len) {
|
||||
d = (urlcharmap(s[i+1]) << 4) | urlcharmap(s[i+2]);
|
||||
if ( d < 256) {
|
||||
*dest = (char) d;
|
||||
dest++;
|
||||
i += 3; /* loop will increment one time */
|
||||
} else {
|
||||
*dest++ = '%';
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
*dest++ = '%';
|
||||
i += 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*dest++ = s[i];
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
*dest = '\0';
|
||||
return (size_t)(dest - deststart); /* compute "strlen" of dest */
|
||||
}
|
||||
|
||||
void modp_toprint(char* str, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (str[i] < 32 || str[i] > 126) {
|
||||
str[i] = '?';
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t modp_rtrim(char* str, size_t len)
|
||||
{
|
||||
while (len) {
|
||||
char c = str[len -1];
|
||||
if (c == ' ' || c == '\n' || c == '\t' || c == '\r') {
|
||||
str[len -1] = '\0';
|
||||
len -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void test_positive(FILE * fd, const char *fname, detect_mode_t mode,
|
||||
int flag_invert, int flag_true, int flag_quiet)
|
||||
{
|
||||
char linebuf[8192];
|
||||
int issqli;
|
||||
int linenum = 0;
|
||||
size_t len;
|
||||
sfilter sf;
|
||||
|
||||
while (fgets(linebuf, sizeof(linebuf), fd)) {
|
||||
linenum += 1;
|
||||
len = modp_rtrim(linebuf, strlen(linebuf));
|
||||
if (len == 0) {
|
||||
continue;
|
||||
}
|
||||
if (linebuf[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
len = modp_url_decode(linebuf, linebuf, len);
|
||||
issqli = 0;
|
||||
switch (mode) {
|
||||
case MODE_SQLI: {
|
||||
libinjection_sqli_init(&sf, linebuf, len, 0);
|
||||
issqli = libinjection_is_sqli(&sf);
|
||||
break;
|
||||
}
|
||||
case MODE_XSS: {
|
||||
issqli = libinjection_xss(linebuf, len);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (issqli) {
|
||||
g_test_ok += 1;
|
||||
} else {
|
||||
g_test_fail += 1;
|
||||
}
|
||||
|
||||
if (!flag_quiet) {
|
||||
if ((issqli && flag_true && ! flag_invert) ||
|
||||
(!issqli && flag_true && flag_invert) ||
|
||||
!flag_true) {
|
||||
|
||||
modp_toprint(linebuf, len);
|
||||
|
||||
switch (mode) {
|
||||
case MODE_SQLI: {
|
||||
/*
|
||||
* if we didn't find a SQLi and fingerprint from
|
||||
* sqlstats is is 'sns' or 'snsns' then redo using
|
||||
* plain context
|
||||
*/
|
||||
if (!issqli && (strcmp(sf.fingerprint, "sns") == 0 ||
|
||||
strcmp(sf.fingerprint, "snsns") == 0)) {
|
||||
libinjection_sqli_fingerprint(&sf, 0);
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s\t%d\t%s\t%s\t%s\n",
|
||||
fname, linenum,
|
||||
(issqli ? "True" : "False"), sf.fingerprint, linebuf);
|
||||
break;
|
||||
}
|
||||
case MODE_XSS: {
|
||||
fprintf(stdout, "%s\t%d\t%s\t%s\n",
|
||||
fname, linenum,
|
||||
(issqli ? "True" : "False"), linebuf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(const char* argv[])
|
||||
{
|
||||
fprintf(stdout, "usage: %s [flags] [files...]\n", argv[0]);
|
||||
fprintf(stdout, "%s\n", "");
|
||||
fprintf(stdout, "%s\n", "-q --quiet : quiet mode");
|
||||
fprintf(stdout, "%s\n", "-m --max-fails : number of failed cases need to fail entire test");
|
||||
fprintf(stdout, "%s\n", "-s INTEGER : repeat each test N time "
|
||||
"(for performance testing)");
|
||||
fprintf(stdout, "%s\n", "-t : only print positive matches");
|
||||
fprintf(stdout, "%s\n", "-x --mode-xss : test input for XSS");
|
||||
fprintf(stdout, "%s\n", "-i --invert : invert test logic "
|
||||
"(input is tested for being safe)");
|
||||
|
||||
fprintf(stdout, "%s\n", "");
|
||||
fprintf(stdout, "%s\n", "-? -h -help --help : this page");
|
||||
fprintf(stdout, "%s\n", "");
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
/*
|
||||
* invert output, by
|
||||
*/
|
||||
int flag_invert = FALSE;
|
||||
|
||||
/*
|
||||
* don't print anything.. useful for
|
||||
* performance monitors, gprof.
|
||||
*/
|
||||
int flag_quiet = FALSE;
|
||||
|
||||
/*
|
||||
* only print postive results
|
||||
* with invert, only print negative results
|
||||
*/
|
||||
int flag_true = FALSE;
|
||||
detect_mode_t mode = MODE_SQLI;
|
||||
|
||||
int flag_slow = 1;
|
||||
int count = 0;
|
||||
int max = -1;
|
||||
|
||||
int i, j;
|
||||
int offset = 1;
|
||||
|
||||
while (offset < argc) {
|
||||
if (strcmp(argv[offset], "-?") == 0 ||
|
||||
strcmp(argv[offset], "-h") == 0 ||
|
||||
strcmp(argv[offset], "-help") == 0 ||
|
||||
strcmp(argv[offset], "--help") == 0) {
|
||||
usage(argv);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (strcmp(argv[offset], "-i") == 0) {
|
||||
offset += 1;
|
||||
flag_invert = TRUE;
|
||||
} else if (strcmp(argv[offset], "-q") == 0 ||
|
||||
strcmp(argv[offset], "--quiet") == 0) {
|
||||
offset += 1;
|
||||
flag_quiet = TRUE;
|
||||
} else if (strcmp(argv[offset], "-t") == 0) {
|
||||
offset += 1;
|
||||
flag_true = TRUE;
|
||||
} else if (strcmp(argv[offset], "-s") == 0) {
|
||||
offset += 1;
|
||||
flag_slow = 100;
|
||||
} else if (strcmp(argv[offset], "-m") == 0 ||
|
||||
strcmp(argv[offset], "--max-fails") == 0) {
|
||||
offset += 1;
|
||||
max = atoi(argv[offset]);
|
||||
offset += 1;
|
||||
} else if (strcmp(argv[offset], "-x") == 0 ||
|
||||
strcmp(argv[offset], "--mode-xss") == 0) {
|
||||
mode = MODE_XSS;
|
||||
offset += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset == argc) {
|
||||
test_positive(stdin, "stdin", mode, flag_invert, flag_true, flag_quiet);
|
||||
} else {
|
||||
for (j = 0; j < flag_slow; ++j) {
|
||||
for (i = offset; i < argc; ++i) {
|
||||
FILE* fd = fopen(argv[i], "r");
|
||||
if (fd) {
|
||||
test_positive(fd, argv[i], mode, flag_invert, flag_true, flag_quiet);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag_quiet) {
|
||||
fprintf(stdout, "%s", "\n");
|
||||
fprintf(stdout, "SQLI : %d\n", g_test_ok);
|
||||
fprintf(stdout, "SAFE : %d\n", g_test_fail);
|
||||
fprintf(stdout, "TOTAL : %d\n", g_test_ok + g_test_fail);
|
||||
}
|
||||
|
||||
if (max == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = g_test_ok;
|
||||
if (flag_invert) {
|
||||
count = g_test_fail;
|
||||
}
|
||||
|
||||
if (count > max) {
|
||||
printf("\nThreshold is %d, got %d, failing.\n", max, count);
|
||||
return 1;
|
||||
} else {
|
||||
printf("\nThreshold is %d, got %d, passing.\n", max, count);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user