예제 #1
0
static
ib_status_t sqli_op_execute(
    ib_tx_t *tx,
    void *instance_data,
    const ib_field_t *field,
    ib_field_t *capture,
    ib_num_t *result,
    void *cbdata
)
{
    assert(tx            != NULL);
    assert(field         != NULL);
    assert(result        != NULL);

    sfilter sf;
    ib_bytestr_t *bs;
    ib_status_t rc;
    const sqli_pattern_set_t *ps = (const sqli_pattern_set_t *)instance_data;

    *result = 0;

    /* Currently only bytestring types are supported.
     * Other types will just get passed through. */
    if (field->type != IB_FTYPE_BYTESTR) {
        return IB_OK;
    }

    rc = ib_field_value(field, ib_ftype_bytestr_mutable_out(&bs));
    if (rc != IB_OK) {
        return rc;
    }

    /* Run through libinjection. */
    libinjection_sqli_init(
        &sf,
        (const char *)ib_bytestr_const_ptr(bs),
        ib_bytestr_length(bs),
        FLAG_NONE
    );
    if (ps != NULL ) {
        libinjection_sqli_callback(&sf, sqli_lookup_word, (void *)ps);
    }
    if ( libinjection_is_sqli(&sf) ) {
        ib_log_debug_tx(tx, "Matched SQLi fingerprint: %s", sf.fingerprint);
        *result = 1;
    }

    return IB_OK;
}
예제 #2
0
int read_file(const char* fname, int flags, int testtype)
{
    int count = 0;
    FILE *fp = NULL;
    char linebuf[4096];
    char g_actual[4096];
    char* bufptr = NULL;
    sfilter sf;
    int ok = 1;
    int num_tokens;
    int issqli;
    int i;

    g_test[0] = '\0';
    g_input[0] = '\0';
    g_expected[0] = '\0';

    fp = fopen(fname, "r");
    while(fgets(linebuf, sizeof(linebuf), fp) != NULL) {
        if (count == 0 && strcmp(linebuf, "--TEST--\n") == 0) {
            bufptr = g_test;
            count = 1;
        } else if (count == 1 && strcmp(linebuf, "--INPUT--\n") == 0) {
            bufptr = g_input;
            count = 2;
        } else if (count == 2 && strcmp(linebuf, "--EXPECTED--\n") == 0) {
            bufptr = g_expected;
            count = 3;
        } else {
            strcat(bufptr, linebuf);
        }
    }
    fclose(fp);
    if (count != 3) {
        return 1;
    }

    g_expected[modp_rtrim(g_expected, strlen(g_expected))] = '\0';
    g_input[modp_rtrim(g_input, strlen(g_input))] = '\0';


    size_t slen = strlen(g_input);
    char* copy = (char* ) malloc(slen);
    memcpy(copy, g_input, slen);
    libinjection_sqli_init(&sf, copy, slen, flags);

    /* just here for code coverage and cppcheck */
    libinjection_sqli_callback(&sf, NULL, NULL);

    slen = 0;
    g_actual[0] = '\0';
    if (testtype == 1) {
        issqli = libinjection_is_sqli(&sf);
        if (issqli) {
            sprintf(g_actual, "%s", sf.fingerprint);
        }
    } else if (testtype == 2) {
        num_tokens = libinjection_sqli_fold(&sf);
        for (i = 0; i < num_tokens; ++i) {
            slen = print_token(g_actual, slen, &(sf.tokenvec[i]));
        }
    } else {
        while (libinjection_sqli_tokenize(&sf) == 1) {
            slen = print_token(g_actual, slen, sf.current);
        }
    }

    g_actual[modp_rtrim(g_actual, strlen(g_actual))] = '\0';

    if (strcmp(g_expected, g_actual) != 0) {
        printf("INPUT: \n%s\n==\n", g_input);
        printf("EXPECTED: \n%s\n==\n", g_expected);
        printf("GOT: \n%s\n==\n", g_actual);
        ok = 0;
    }

    free(copy);
    return ok;
}
예제 #3
0
static
ib_status_t sqli_normalize_tfn(ib_mpool_t *mp,
                               const ib_field_t *field_in,
                               const ib_field_t **field_out,
                               void *tfn_data)
{
    assert(mp != NULL);
    assert(field_in != NULL);
    assert(field_out != NULL);

    const sqli_pattern_set_t *ps = (const sqli_pattern_set_t *)tfn_data;
    sfilter sf;
    ib_bytestr_t *bs_in;
    ib_bytestr_t *bs_out;
    const char *buf_in;
    char *buf_in_start;
    size_t buf_in_len;
    char *buf_out;
    char *buf_out_end;
    size_t buf_out_len;
    size_t lead_len = 0;
    char prev_token_type;
    ib_field_t *field_new;
    ib_status_t rc;
    size_t fingerprint_len;

    /* Currently only bytestring types are supported.
     * Other types will just get passed through. */
    if (field_in->type != IB_FTYPE_BYTESTR) {
        *field_out = field_in;
        return IB_OK;
    }

    /* Extract the underlying incoming value. */
    rc = ib_field_value(field_in, ib_ftype_bytestr_mutable_out(&bs_in));
    if (rc != IB_OK) {
        return rc;
    }

    /* Create a buffer big enough (double) to allow for normalization. */
    buf_in = (const char *)ib_bytestr_const_ptr(bs_in);
    buf_out = buf_out_end = (char *)ib_mpool_calloc(mp, 2, ib_bytestr_length(bs_in));
    if (buf_out == NULL) {
        return IB_EALLOC;
    }

/* TODO: With the latest libinjection, we will need to do something like the
 * following, but more robust, instead of just calling is_sqli. This seems
 * to be because folding is now called, which removes some tokens.
 */
#if 0
    /* As SQL can be injected into a string, the normalization
     * needs to start after the first quote character if one
     * exists.
     *
     * First try single quote, then double, then none.
     *
     * TODO: Handle returning multiple transformations:
     *       1) Straight normalization
     *       2) Normalization as if with single quotes (starting point
     *          should be based on straight normalization)
     *       3) Normalization as if with double quotes (starting point
     *          should be based on straight normalization)
     */
    buf_in_start = memchr(buf_in, CHAR_SINGLE, ib_bytestr_length(bs_in));
    if (buf_in_start == NULL) {
        buf_in_start = memchr(buf_in, CHAR_DOUBLE, ib_bytestr_length(bs_in));
    }
    if (buf_in_start == NULL) {
        buf_in_start = (char *)buf_in;
        buf_in_len = ib_bytestr_length(bs_in);
    }
    else {
        ++buf_in_start; /* After the quote. */
        buf_in_len = ib_bytestr_length(bs_in) - (buf_in_start - buf_in);
    }

    /* Copy the leading string if one exists. */
    if (buf_in_start != buf_in) {
        lead_len = buf_in_start - buf_in;
        memcpy(buf_out, buf_in, lead_len);
        buf_out_end += lead_len;
    }
#endif
    buf_in_start = (char *)buf_in;
    buf_in_len = ib_bytestr_length(bs_in);

    /* Copy the normalized tokens as a space separated list. Since
     * the tokenizer does not backtrack, and the normalized values
     * are always equal to or less than the original length, the
     * tokens are written back to the beginning of the original
     * buffer.
     */
    libinjection_sqli_init(&sf,buf_in_start, buf_in_len, FLAG_NONE);
    libinjection_sqli_callback(&sf, sqli_lookup_word, (void *)ps);

    /* NOTE: We do not care if it is sqli, but just want the tokens. */
    libinjection_is_sqli(&sf);

    if (strlen(sf.fingerprint) == 0) {
        *field_out = field_in;
        return IB_OK;
    }

    buf_out_len = 0;
    prev_token_type = 0;
    fingerprint_len = strlen(sf.fingerprint);
    for (size_t i = 0; i < fingerprint_len; ++i) {
        stoken_t current = sf.tokenvec[i];
        size_t token_len = strlen(current.val);

        /* Add in the space if required. */
        if ((buf_out_end != buf_out) &&
            (current.type != 'o') &&
            (prev_token_type != 'o') &&
            (current.type != ',') &&
            (*(buf_out_end - 1) != ','))
        {
            *buf_out_end = ' ';
            buf_out_end += 1;
            ++buf_out_len;
        }

        /* Copy the token value. */
        memcpy(buf_out_end, current.val, token_len);
        buf_out_end += token_len;
        buf_out_len += token_len;

        prev_token_type = current.type;
    }


    /* Create the output field wrapping bs_out. */
    buf_out_len += lead_len;
    rc = ib_bytestr_alias_mem(&bs_out, mp, (uint8_t *)buf_out, buf_out_len);
    if (rc != IB_OK) {
        return rc;
    }
    rc = ib_field_create(&field_new, mp,
                         field_in->name, field_in->nlen,
                         IB_FTYPE_BYTESTR,
                         ib_ftype_bytestr_mutable_in(bs_out));
    if (rc == IB_OK) {
        *field_out = field_new;
    }
    return rc;
}
예제 #4
0
파일: reader.c 프로젝트: fcw11/libinjection
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);
                }
            }
        }
    }
}
예제 #5
0
int main(int argc, const char* argv[])
{
    int flags = 0;
    int fold = 0;
    int detect = 0;



    int i;
    int count;
    int offset = 1;
    int issqli;

    sfilter sf;

    if (argc < 2) {
        fprintf(stderr, "need more args\n");
        return 1;
    }
    while (1) {
        if (strcmp(argv[offset], "-m") == 0) {
            flags |= FLAG_SQL_MYSQL;
            offset += 1;
        }
        else if (strcmp(argv[offset], "-f") == 0 || strcmp(argv[offset], "--fold") == 0) {
            fold = 1;
            offset += 1;
        } else if (strcmp(argv[offset], "-d") == 0 || strcmp(argv[offset], "--detect") == 0) {
            detect = 1;
            offset += 1;
        } else if (strcmp(argv[offset], "-ca") == 0) {
            flags |= FLAG_SQL_ANSI;
            offset += 1;
        } else if (strcmp(argv[offset], "-cm") == 0) {
            flags |= FLAG_SQL_MYSQL;
            offset += 1;
        } else if (strcmp(argv[offset], "-q0") == 0) {
            flags |= FLAG_QUOTE_NONE;
            offset += 1;
        } else if (strcmp(argv[offset], "-q1") == 0) {
            flags |= FLAG_QUOTE_SINGLE;
            offset += 1;
        } else if (strcmp(argv[offset], "-q2") == 0) {
            flags |= FLAG_QUOTE_DOUBLE;
            offset += 1;
        } else {
            break;
        }
    }

    /* ATTENTION: argv is a C-string, null terminated.  We copy this
     * to it's own location, WITHOUT null byte.  This way, valgrind
     * can see if we run past the buffer.
     */

    size_t slen = strlen(argv[offset]);
    char* copy = (char* ) malloc(slen);
    memcpy(copy, argv[offset], slen);
    libinjection_sqli_init(&sf, copy, slen, flags);

    if (detect == 1) {
        issqli = libinjection_is_sqli(&sf);
        if (issqli) {
            printf("%s\n", sf.fingerprint);
        }
    } else if (fold == 1) {
        count = libinjection_sqli_fold(&sf);
        // printf("count = %d\n", count);
        for (i = 0; i < count; ++i) {
            //printf("token: %d :: ", i);
            print_token(&(sf.tokenvec[i]));
        }
    } else {
        while (libinjection_sqli_tokenize(&sf)) {
            print_token(sf.current);
        }
    }

    free(copy);

    return 0;
}
예제 #6
0
static
ib_status_t sqli_normalize_tfn(ib_engine_t *ib,
                               ib_mpool_t *mp,
                               void *tfn_data,
                               const ib_field_t *field_in,
                               const ib_field_t **field_out,
                               ib_flags_t *pflags)
{
    assert(ib != NULL);
    assert(mp != NULL);
    assert(field_in != NULL);
    assert(field_out != NULL);
    assert(pflags != NULL);

    sfilter sf;
    ib_bytestr_t *bs_in;
    ib_bytestr_t *bs_out;
    const char *buf_in;
    char *buf_in_start;
    size_t buf_in_len;
    char *buf_out;
    char *buf_out_end;
    size_t buf_out_len;
    size_t lead_len = 0;
    char prev_token_type;
    ib_field_t *field_new;
    ib_status_t rc;
    size_t pat_len;

    /* Currently only bytestring types are supported.
     * Other types will just get passed through. */
    if (field_in->type != IB_FTYPE_BYTESTR) {
        *field_out = field_in;
        return IB_OK;
    }

    /* Extract the underlying incoming value. */
    rc = ib_field_value(field_in, ib_ftype_bytestr_mutable_out(&bs_in));
    if (rc != IB_OK) {
        return rc;
    }

    /* Create a buffer big enough (double) to allow for normalization. */
    buf_in = (const char *)ib_bytestr_const_ptr(bs_in);
    buf_out = buf_out_end = (char *)ib_mpool_calloc(mp, 2, ib_bytestr_length(bs_in));
    if (buf_out == NULL) {
        return IB_EALLOC;
    }

    /* As SQL can be injected into a string, the normalization
     * needs to start after the first quote character if one
     * exists.
     *
     * First try single quote, then double, then none.
     *
     * TODO: Handle returning multiple transformations:
     *       1) Straight normalization
     *       2) Normalization as if with single quotes (starting point
     *          should be based on straight normalization)
     *       3) Normalization as if with double quotes (starting point
     *          should be based on straight normalization)
     */
    buf_in_start = memchr(buf_in, CHAR_SINGLE, ib_bytestr_length(bs_in));
    if (buf_in_start == NULL) {
        buf_in_start = memchr(buf_in, CHAR_DOUBLE, ib_bytestr_length(bs_in));
    }
    if (buf_in_start == NULL) {
        buf_in_start = (char *)buf_in;
        buf_in_len = ib_bytestr_length(bs_in);
    }
    else {
        ++buf_in_start; /* After the quote. */
        buf_in_len = ib_bytestr_length(bs_in) - (buf_in_start - buf_in);
    }

    /* Copy the leading string if one exists. */
    if (buf_in_start != buf_in) {
        lead_len = buf_in_start - buf_in;
        memcpy(buf_out, buf_in, lead_len);
        buf_out_end += lead_len;
    }

    /* Copy the normalized tokens as a space separated list. Since
     * the tokenizer does not backtrack, and the normalized values
     * are always equal to or less than the original length, the
     * tokens are written back to the beginning of the original
     * buffer.
     */
    libinjection_is_sqli(&sf, buf_in_start, buf_in_len, NULL, NULL);
    buf_out_len = 0;
    prev_token_type = 0;
    pat_len = strlen(sf.pat);
    for (size_t i = 0; i < pat_len; ++i) {
        stoken_t current = sf.tokenvec[i];
        size_t token_len = strlen(current.val);
        ib_log_debug2(ib, "SQLi TOKEN: %c \"%s\"", current.type, current.val);

        /* Add in the space if required. */
        if ((buf_out_end != buf_out) &&
            (current.type != 'o') &&
            (prev_token_type != 'o') &&
            (current.type != ',') &&
            (*(buf_out_end - 1) != ','))
        {
            *buf_out_end = ' ';
            buf_out_end += 1;
            ++buf_out_len;
        }

        /* Copy the token value. */
        memcpy(buf_out_end, current.val, token_len);
        buf_out_end += token_len;
        buf_out_len += token_len;

        prev_token_type = current.type;
    }

    /* Mark as modified. */
    *pflags = IB_TFN_FMODIFIED;

    /* Create the output field wrapping bs_out. */
    buf_out_len += lead_len;
    rc = ib_bytestr_alias_mem(&bs_out, mp, (uint8_t *)buf_out, buf_out_len);
    if (rc != IB_OK) {
        return rc;
    }
    rc = ib_field_create(&field_new, mp,
                         field_in->name, field_in->nlen,
                         IB_FTYPE_BYTESTR,
                         ib_ftype_bytestr_mutable_in(bs_out));
    if (rc == IB_OK) {
        *field_out = field_new;
    }
    return rc;
}
예제 #7
0
int main(int argc, const char* argv[])
{
    char comment_style = COMMENTS_ANSI;
    int fold = 0;
    int detect = 0;

    int i;
    int count;
    int offset = 1;

    sfilter sf;
    stoken_t current;
    if (argc < 2) {
        fprintf(stderr, "need more args\n");
        return 1;
    }
    while (1) {
        if (strcmp(argv[offset], "-m") == 0) {
            comment_style = COMMENTS_MYSQL;
            offset += 1;
        }
        else if (strcmp(argv[offset], "-f") == 0 || strcmp(argv[offset], "--fold") == 0) {
            fold = 1;
            offset += 1;
        } else if (strcmp(argv[offset], "-d") == 0 || strcmp(argv[offset], "--detect") == 0) {
            detect = 1;
            offset += 1;
        } else {
            break;
        }
    }

    /* ATTENTION: argv is a C-string, null terminated.  We copy this
     * to it's own location, WITHOUT null byte.  This way, valgrind
     * can see if we run past the buffer.
     */

    size_t slen = strlen(argv[offset]);
    char* copy = (char* ) malloc(slen);
    memcpy(copy, argv[offset], slen);

    libinjection_sqli_init(&sf, copy, slen, CHAR_NULL, comment_style);
    if (detect == 1) {
        detect = libinjection_is_sqli(&sf, copy, slen, CHAR_NULL, COMMENTS_ANSI);
        if (detect) {
            printf("%s\n", sf.pat);
        }
    } else if (fold == 1) {
        count = filter_fold(&sf);
        // printf("count = %d\n", count);
        for (i = 0; i < count; ++i) {
            //printf("token: %d :: ", i);
            print_token(&(sf.tokenvec[i]));
        }
    } else {
        while (libinjection_sqli_tokenize(&sf, &current)) {
            print_token(&current);
        }
    }

    free(copy);

    return 0;
}
예제 #8
0
static
ib_status_t sqli_op_execute(
    ib_tx_t *tx,
    const ib_field_t *field,
    ib_field_t *capture,
    ib_num_t *result,
    void *instance_data,
    void *cbdata
)
{
    assert(tx     != NULL);
    assert(field  != NULL);
    assert(result != NULL);

    const sqli_fingerprint_set_t *ps = (const sqli_fingerprint_set_t *)instance_data;
    sfilter                   sf;
    ib_bytestr_t             *bs;
    ib_status_t               rc;
    sqli_callback_data_t      callback_data;

    *result = 0;

    /* Currently only bytestring types are supported.
     * Other types will just get passed through. */
    if (field->type != IB_FTYPE_BYTESTR) {
        return IB_OK;
    }

    rc = ib_field_value(field, ib_ftype_bytestr_mutable_out(&bs));
    if (rc != IB_OK) {
        return rc;
    }

    /* Run through libinjection. */
    libinjection_sqli_init(
        &sf,
        (const char *)ib_bytestr_const_ptr(bs),
        ib_bytestr_length(bs),
        FLAG_NONE
    );
    callback_data.confidence = 0;
    callback_data.fingerprint_set = NULL;
    if (ps != NULL) {
        callback_data.fingerprint_set = ps;
        libinjection_sqli_callback(&sf, sqli_lookup_word, (void *)&callback_data);
    }
    if (libinjection_is_sqli(&sf)) {
        ib_log_debug_tx(tx, "Matched SQLi fingerprint: %s", sf.fingerprint);
        *result = 1;
    }
    if (*result == 1 && capture != NULL) {
        {
            ib_field_t *fingerprint_field;
            size_t fingerprint_length = strlen(sf.fingerprint);
            const uint8_t *fingerprint;

            fingerprint = ib_mm_memdup(
                tx->mm,
                sf.fingerprint, fingerprint_length
            );
            if (fingerprint == NULL) {
                return IB_EALLOC;
            }

            rc = ib_field_create_bytestr_alias(
                &fingerprint_field,
                tx->mm,
                IB_S2SL("fingerprint"),
                fingerprint, fingerprint_length
            );
            if (rc != IB_OK) {
                return rc;
            }

            rc = ib_field_list_add(capture, fingerprint_field);
            if (rc != IB_OK) {
                return rc;
            }
        }

        {
            ib_field_t *confidence_field;

            rc = ib_field_create(
                &confidence_field,
                tx->mm,
                IB_S2SL("confidence"),
                IB_FTYPE_NUM,
                ib_ftype_num_in(&callback_data.confidence)
            );
            if (rc != IB_OK) {
                return rc;
            }

            rc = ib_field_list_add(capture, confidence_field);
            if (rc != IB_OK) {
                return rc;
            }
        }
    }

    return IB_OK;
}