Detailed explanation of the principle of SQL injection without column name injection

Why is column-less injection needed?

Our commonly used SQL injection method is information_schemaimplemented through this default database, but have you ever thought that if the database is filtered, we cannot use this library to find out the table names and column names. However, we can find out the table name in two ways:

  1. InnoDb engine

    Starting from MYSQL5.5.8, InnoDB becomes its default storage engine. In versions above MYSQL 5.6, inndb adds two tables, innodb_index_stats and innodb_table_stats ( mysql.innodb_table_stats). Both tables store information about the database and its data tables, but do not store column names. In higher versions of mysql, table structures are recorded in INNODB_TABLES and INNODB_COLUMNS.

  2. sys database

    In MYSQL 5.7 and above, the sys database is added. The basic data of this database comes from information_schema and performance_chema, and it does not store data itself. The table name can be obtained through schema_auto_increment_columns( sys.schema_auto_increment_columns).

However, the above two methods can only find the table name, but not the column name. In this case, we will use column-less injection. Column-less injection, as the name suggests, is an injection that can inject data without column names.

No column name injection usage conditions

Injection without column names is mainly suitable for situations where the data table has been obtained but the columns cannot be queried. In most CTF questions, the information_schema library is filtered, and this method is used to obtain column names.

No column name injection principle

The principle of column-less injection is actually very simple, that is, joint query creates virtual data. It can be seen as aliasing the column names we don't know, and performing data query while taking the alias, so the number of query fields must be the same. If the fields we query are more than the columns in the data table, an error will occur. Report an error.

Practical demonstration:

The data in the normal query user table isselect * from user;

image-20230917145304914

Use a joint query to check the data in the table select 1,2,3 union select * from user;. It is obvious that dummy data (virtual field value 123 and virtual table) is created, and the column name in the virtual table becomes 123.

image-20230917145419828

If we only check the field value of one column, we can use:
To explain, xxx is the table name of the virtual table named by yourself, which can be customized. This sql statement creates virtual table xxx and virtual columns 1, 2, and 3 in a joint query and simultaneously queries the data in the second column of the virtual table.

select `2` from (select 1,2,3 union select * from user)xxx;

image-20230917145701326

Check multiple columns at the same time

select concat(`2`,`3`) from (select 1,2,3 union select * from user)xxx;

image-20230917150452258

However, sometimes ` will also be filtered. At this time, we have to use the alias (as) operation again and change the column names, so that the column names do not need backticks when querying the data.

select 1 as a,2 as b,3 as c union select * from user;

image-20230917150229489

select b from (select 1 as a,2 as b,3 as c union select * from user)xxx;

image-20230917150304333


Another method is to use JOINinjection without column names to establish an inner connection between two tables through JOIN. That is to say, adding up the column names of the two tables may reveal the same column names. We use It is this feature that makes the list pop up.

select * from (select * from user as a join user as b)xxx;

image-20230917152950066

After getting the first column name id, the following payload will echo us the data of the second column.

select * from (select * from user as a join user as b using(id))xxx;

image-20230917153008543

And so on for the rest.

select * from (select * from user as a join user as b using(id,username))xxx;

image-20230917153055650

The actual payload of the first level of sqli-labs:

?id=-1' union all select * from (select * from users as a join users as b)as c--+

Guess you like

Origin blog.csdn.net/Jayjay___/article/details/132956870