标签:base32编码 | base64编码 | CTF | intval() | is_numeric() | switch() | vim特性
提示:考察点: 1.burp的使用 2.base全家桶 3.编辑器备份 3.某函数的绕过
hint: 4D525757593544474D343654323D3D3D
CTF在线工具-Hex在线编码|Hex在线解码|十六进制编码转换
CTF在线工具-在线base编码|在线base解码|base16编码|base32编码|base64编码
CTF在线工具-在线base编码|在线base解码|base16编码|base32编码|base64编码
默认情况下使用Vim编程,在修改文件后系统会自动生成一个带~的备份文件,某些情况下可以对其下载进行查看;
index.php普遍意义上的首页,输入域名不一定会显示。 它的备份文件则为index.php~
vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件,如果原文件名是submit,则它的临时文件 .submit.swp。如果文件正常退出,则此文件自动删除。
访问index.php~,保存index.php~,现已改名为web11.php~ 。
<?php
header('content-type:text/html;charset=utf-8');
include './flag.php';
error_reporting(0);
if(empty($_GET['id'])){
header('location:./1ndex.php');
}else{
$id = $_GET['id'];
if (!is_numeric($id)){
$id = intval($id);
switch ($id) {
case $id>=0:
echo "快出去吧,走错路了~~~<br>";
echo "这么简单都不会么?";
break;
case $id>=10:
exit($flag);
break;
default:
echo "你走不到这一步的!";
break;
}
}
}
?>
代码解释
header('content-type:text/html;charset=utf-8');
PHP文件插入header("Content-type: text/html; charset=utf-8"); 相当于页面里面的<meta http-equiv="Content-Type" content="text/html; charset=utf-8">;
include './flag.php';
被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。如果在 include_path 下没找到该文件则 include 最后才在调用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则 include 结构会发出一条警告;这一点和 require 不同,后者会发出一个致命错误。
当一个文件被包含时,其中所包含的代码继承了 include 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。
error_reporting(0);
error_reporting — 设置应该报告何种 PHP 错误
error_reporting(0); // 关闭所有PHP错误报告
if(empty($_GET['id'])){}
当参数id的值存在,并且是一个非空非零的值时返回 FALSE 否则返回 TRUE.
所以只有GET传参id的值一个非空非零的值,才可以执行else里边的语句,否则就跳转到1ndex.php页面。
这里传参?id="",其实不是传了一个空字符串,而是传了一对双引号,而传参?id=123其实是传参字符串"123"(数值字符串)。
header('location:./1ndex.php');
header("Location:")作为php的转向语句。
但是很多时候在header前我们已经输出了好多东西了,此时如果再次header的话,显然是出错的,在这里我们启用了一个ob的概念,ob的意思是在服务器端先存储有关输出,等待适当的时机再输出,而不是像现在这样运行一句,输出一句,发现header语句就只能报错了。具体的语句有: ob_start(); ob_end_clean();ob_flush();.........
2、在header("Location:")后要及时exit
否则他是会继续执行的,虽然在浏览器端你看不到相应的数据出现,但是如果你进行抓包分析的话,你就会看到下面的语句也是在执行的。而且被输送到了浏览器客户端,只不过是没有被浏览器执行为html而已(浏览器执行了header进行了转向操作)。
$id = $_GET['id'];
is_numeric() 函数用于检测变量是否为数字或数字字符串。如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE。
为了满足!is_numeric(),所以传参不能为数字或数字字符串。
这里传参?id="",其实不是传了一个空字符串,而是传了一对双引号,而传参?id=123其实是传参字符串"123"(数值字符串)。
$id = intval($id);
intval() 函数通过使用指定的进制 base 转换(默认是十进制)
如果参数是字符串,则返回字符串中第一个不是数字的字符之前的数字串所代表的整数值。比如:123a456,返回的字符串就是123;-123a456则返回的字符串为-123。
当var是一个array时候,var为空则返回0,不为空则返回1
如果出现无法转换的字符串,intval()不会报错而是返回0。
如果参数第一位为非数字的时候(字母或其他符号 )时,返回0。
switch ($id) {
把intval()函数处理过的参数值当做switch()循环的执行case。
switch 语句类似于具有同一个表达式的一系列 if 语句。很多场合下需要把同一个变量(或表达式)与很多不同的值比较,并根据它等于哪个值来执行不同的代码。这正是 switch 语句的用途。
如果是用不同类型的参数进行比较,会把case 条件以及参数进行类型转换,转成布尔类型,再进行下一步的比较。
而$id=12转成布尔类型为true,和case true:相符合,也就是执行case $id >=0的语句。
2. intval()函数处理过的参数值等于0
如果是用不同类型的参数进行比较,会把case 条件以及参数进行类型转换,转成布尔类型,再进行下一步的比较。
而$id=0转成布尔类型为false,和case true:不相符,那就按顺序继续判断。
而$id=0转成布尔类型为false,和case false:相符合,也就是执行case $id >= 10的语句,也就是输出flag。
参考资料:比较php中switch与if..elseif以及记录switch中的坑 - MrBear - 博客园
想要最后经过intval()函数处理过的值为0,且不能是数字或数字字符串(123q只是字符串,不是数字字符串)。所以只要传非数字字符串或者不以数字开头的字符串就可以了。
这里不能传数组,传数组,最后要么是0,要么是1。是0的前提是值为空,这样就过不了empty()函数的检测了。
Payload:index.php?id=q1
Flag:flag{1s_gfEDR_O0O0IOKoo0}
打赏我,让我更有动力~
© 2016 - 2023 掌控者 All Rights Reserved.