sql注入
基础
1 | select * from users where username = 'admin' |
or 的意义在于前面的语句执行不成功,也可以进行,最终语句的判别是true
单引号和双引号可以都尝试,因为不一定是单引号还是双引号
- 获取的变量id 为整形
当获取的变量id为整形时,则不需要考虑闭合的问题
- 联合查询:union
联合查询的后面不能跟着星号1,2,3的作用是为了方便看显示的位置1
select * from news where id = '1' union select 1,2,3
union select 后面可以接三种格式:1,2,3;null;
有要求:后面字段的数量必须和前面字段的数量保持一致
为了方便显示,有些网页只能显示指定数量的东西,所以需要将后面的东西显示到前面,共有两种方式:
- 前面给一个假值;
- 或者使用limit进行切片:
可以看到下面输出的两行
输出第一行(0,1):
1 | select * from news where id = '1' union select 1,2,3,4 limit 0,1; |
输出第二行(1,1):
1 | select * from news where id = '1' union select 1,2,3,4 limit 1,1; |
order by
排序:order by
一般有两种方式:
- 具体的字段:
...order by id
- 根据第几列来排序如
...order by 2
就是根据第二列来进行排序- 可以通过这种方式来猜一共几列
单引号:%27
井号:%23
1,2,3,4显示位可以用于显示如:
1 | select * from news where id = '1' union select 1,version(),user(),database() limit 1,1; |
则可以在输出的界面于相应的位置显示:版本、用户、数据库名称,如:
一般采取的步骤:
- 第一步加’单引号 (判断页面有没有报错,或者有没有明显变化)
- 第二步and 1=1 (判断语句闭合是否成功)
- 第三步and 1=2 (判断语句闭合是否成功)
通过页面有没有反馈去判断有没有注入,避免有可能是双引号的情况,因为前面的都有可能被当成字符串
还有一种方式直接加转义符:\'
直接将单引号转义掉
information_schema
在databases下的,可以存放表结构
表的名称:存放在information_schema下面的schemata表格中,把所有的数据库的名称得到,可以采用下面的语句:
1 | union select 1,schema_name,3,4 from information_schema.schemata |
逐个表名称输出:
1 | union select 1,schema_name,3,4 from information_schema.schemata limit 0,1 |
也可以采用拼接函数:
1 | union select 1,group_concat(schema_name),3,4 from information_schema.schemata |
如图:
注:可以在phpmyadmin中打开数据库的图形化界面
table
1 | union select 1,group_concat(table_name),3,4 from information_schema.tables=database() |
获取表中的字段:
1 | union select 1,group_concat(colimns_name),3,4 from information_schema.columns where table_schema=database() and table_name='user' |
‘user’部分不推荐采用单引号,可以将这一串转换成十六进制:
str转hex十六进制
获得表的列的字段,就可以得到数据库里面的内容:
1 | union select 1,username,password,4 from users |
流程
- 先判断输入是什么类型
- 再输入的地方id=1之后加一个and 1=2,如果页面空白没有出现报错,则说明id是字符串类型
- 如果出现报错,则证明id是整数类型
- 用
order by
来判断列数,采用尝试的方式- 先给一个很大的数,判断语句有没有问题,因为一般没有这么大的数的列;
- 再一点点尝试:由不出错到出错,则找到了那个列的数值
- 则可以用
union select
采用上面的方式进行一步步的读取,得到数据库里面的·数据
order by 小问题
1 | union select 1,2,3,4 from a |
如果表a的列数小于4也是可以执行的,1,2,3,4只要和前面的表保持一致就可以,
updatexml
这个是通过报错的方式显示信息,报错信息不输出,就不管用了,上面的方式都是正常的输出,报错就算不输出,也可以进行语句的结果输出,通过其界面上显示的东西。
1 | updatexml(a,b,c) |
b:输出的路径
0x7e:波浪号,为了好看
正常应该是一个路径,但是这里会执行这个sql语句,因为这里并不是一个他所想要的路径,但是会执行,于是我们就可以得出如下:
1 | updatexml(1,concat(0x7e,....,0x7e),1) |
…:中间可以填写sql语句,完整的sql语句
中间只能显示32个,长度会受限
用substr(str,1,x)
,substring(str,1,x)
如: