cybersecurity · intermediate · ~12 min · safe pentest lab

Flag SQL-injection metacharacters in input

Detect specific substrings in untrusted input. Defence-in-depth on top of parameterised queries.

Challenge

Flag input that contains classic SQL-injection metacharacters — a defence-in-depth detector that sits on top of parameterised queries (it does not replace them).

Task

Implement int has_sqli_markers(const char *input) that returns 1 if input contains any of these markers, and 0 otherwise:

  • a single quote '
  • the SQL line-comment marker --
  • the SQL block-comment opener /*
  • a statement terminator ;
  • the substring UNION SELECT (case-insensitive)

Input

  • input: a fixed NUL-terminated string the grader provides (may be NULL).

Output

Returns 1 if any marker is present, 0 otherwise (NULL0).

Example

has_sqli_markers("hello world")        ->   0
has_sqli_markers("O'Brien")            ->   1   (single quote)
has_sqli_markers("admin'--")           ->   1   (quote + comment)
has_sqli_markers("DROP TABLE users;")  ->   1   (';')
has_sqli_markers("/* comment */")      ->   1   (block comment)
has_sqli_markers("Union SeLeCt 1,2")   ->   1   (case-insensitive)
has_sqli_markers("union sneak")        ->   0   ("UNION" without "SELECT")
has_sqli_markers(NULL)                 ->   0

Edge cases

  • NULL or empty input: return 0.
  • UNION SELECT is matched case-insensitively; the other tokens match exactly.

Rules

  • Pure detection — do not sanitise or escape. The real fix is prepared statements; this is one extra layer.

Why this matters

A metacharacter detector on the input layer adds defence in depth above prepared statements.

Input format

A fixed NUL-terminated string (may be NULL).

Output format

1 if any SQLi marker is present; otherwise 0.

Constraints

Pure detection; UNION SELECT case-insensitive, other tokens exact; NULL-safe.

Starter code

#include <stddef.h>

int has_sqli_markers(const char *input) {
    /* TODO */
    (void)input;
    return 0;
}

Common mistakes

Returning a count instead of a boolean. Forgetting NULL input. Case-sensitive match for UNION SELECT.

Edge cases to handle

NULL input. Empty string. Input with quotes inside legitimate text (e.g. O'Brien) — still flagged because this is a flagger, not a smart parser.

Complexity

O(n) per substring check; bounded constant number of checks.

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.