【AWDP】 AWDP 赛制详解&应对方法&赛题实践 量大管饱
字数 2260 2025-08-24 07:48:23

AWDP赛制详解与实战防御指南

一、AWDP赛制概述

AWDP(Attack With Defense Plus)是一种综合考核参赛团队攻击、防御技术能力、即时策略的攻防兼备比赛模式。每个参赛队互为攻击方和防守方,充分体现比赛的实战性、实时性和对抗性。

比赛组成

  • Break:使用自己的payload打通目标系统
  • Fix:使主办方的payload无法打通自己的系统

策略建议

  • Fix通常比Break容易,优先Fix
  • 如果是分时进行的,Break时建议同时思考Fix方案

赛前准备

  1. 离线语言手册(如utools)
  2. 安全文章库
  3. 各语言WAF(Web应用防火墙)模板

二、常见防御手段

通用防御

  • 上WAF
  • 注释漏洞语句

语言/漏洞特定防御

PHP特性

  • 基本无特殊防御意义

SQL注入

  1. WAF
  2. addslashes()函数过滤
  3. 预处理(最佳方案)

SSTI(服务器端模板注入)

  • WAF(仅过滤{不够)

原型链污染

  • 注释污染相关代码

文件上传

  1. 后缀强校验
  2. 文件内容WAF
  3. MIME头校验(建议同时实施)

Java

  1. 注释漏洞代码
  2. 上调库版本
  3. WAF

代码审计

  1. WAF
  2. 注释漏洞代码

三、WAF编写指南

通用注意事项

  • 注意语法正确性,本地测试
  • 单个语法错误可能导致全部防御失效
  • 平时积累有效的WAF规则

PHP WAF示例

基础过滤:

$str1 = "";
foreach ($_POST as $key => $value) {
    $str1.=$key;
    $str1.=$value;
}
$str2 = "";
foreach ($_GET as $key => $value) {
    $str2.=$key;
    $str2.=$value;
}
if (preg_match("/system|tail|flag|exec|base64|phpinfo|<\?|\"/i", $str1)||preg_match("/system|tail|flag|exec|base64|phpinfo|<\?|\"/i", $str2)) {
    die('no!');
}

RCE防御:

function wafrce($str){
    return !preg_match("/openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|scandir|assert|pcntl_exec|fwrite|curl|system|eval|assert|flag|passthru|exec|chroot|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore/i", $str);
}

SQL注入防御:

function wafsqli($str){
    return !preg_match("/select|and|\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\x26|\x7c|or|into|from|where|join|sleexml|extractvalue|+|regex|copy|read|file|create|grand|dir|insert|link|server|drop|i", $str);
}

XSS防御:

function wafxss($str){
    return !preg_match("/\'|http|\"|\`|cookie|<|>|script/i", $str);
}

Go WAF示例

依赖strings库版本:

import (
    "fmt"
    "strings"
)

func main() {
    var input string
    fmt.Print("请输入一个字符串:")
    fmt.Scanln(&input)
    
    maliciousStrings := []string{
        "union", "select", "delete", "insert", "update", "truncate", 
        "drop", "create", "\"", "'", " ", "{{", "}}", ".", "{", "}", "flag"}
    
    input = strings.ToLower(input)
    for _, s := range maliciousStrings {
        if strings.Contains(input, s) {
            return
        }
    }
}

不依赖库版本:

import (
    "fmt"
)

func main() {
    var input string
    fmt.Print("请输入一个字符串:")
    fmt.Scanln(&input)
    
    maliciousStrings := []string{
        "union", "select", "delete", "insert", "update", "truncate", 
        "drop", "create", "\"", "'", " ", "{{", "}}", ".", "{", "}", "flag"}
    
    if isMalicious(input, maliciousStrings) {
        return
    }
}

func isMalicious(input string, maliciousStrings []string) bool {
    input = stringToLower(input)
    for _, s := range maliciousStrings {
        if stringContains(input, s) {
            return true
        }
    }
    return false
}

func stringToLower(str string) string {
    runes := []rune(str)
    for i, r := range runes {
        if r >= 'A' && r <= 'Z' {
            runes[i] = r + ('a' - 'A')
        }
    }
    return string(runes)
}

func stringContains(str string, substr string) bool {
    strRunes := []rune(str)
    substrRunes := []rune(substr)
    for i := 0; i <= len(strRunes)-len(substrRunes); i++ {
        found := true
        for j := 0; j < len(substrRunes); j++ {
            if strRunes[i+j] != substrRunes[j] {
                found = false
                break
            }
        }
        if found {
            return true
        }
    }
    return false
}

Node.js WAF示例

const input = "awdwawdd";
const maliciousStrings = [
    "__proto__", "constructor", "prototype", "insert", "update", "truncate", 
    "drop", "create", "\"", "'", " ", "{{", "}}", "union", "select", "delete", 
    "\"", "'", " ", "{{", "}}", ".", "{", "}", "flag"
];

function isMalicious(input, maliciousStrings) {
    input = input.toLowerCase();
    for (let i = 0; i < maliciousStrings.length; i++) {
        const pattern = new RegExp(maliciousStrings[i], "i");
        if (pattern.test(input)) {
            return true;
        }
    }
    return false;
}

if (isMalicious(input, maliciousStrings)) {
    console.log("输入参数包含恶意字符串");
} else {
    console.log("输入参数安全");
}

Java WAF示例

import java.util.regex.Pattern;

public class MaliciousInputChecker {
    public static void main(String[] args) {
        String input = "SELECT * FROM users WHERE id = 1 OR 1=1";
    }
    
    public static boolean isMalicious(String input, String[] maliciousStrings) {
        input = input.toLowerCase();
        for (int i = 0; i < maliciousStrings.length; i++) {
            Pattern pattern = Pattern.compile(maliciousStrings[i], Pattern.CASE_INSENSITIVE);
            if (pattern.matcher(input).find()) {
                return true;
            }
        }
        return false;
    }
}

Python WAF示例

input_str = "awdawafaunonwdwa"
malicious_strings = [
    "__proto__", "constructor", "prototype", "insert", "update", "truncate", 
    "drop", "create", " \" ", "'", " ", "{{", "}}", "union", "select", "delete", 
    " \" ", "'", " ", "{{", "}}", ".", "{", "}", "flag"
]

for s in malicious_strings:
    if input_str.lower().find(s) != -1:
        exit()

black_list = ["{{", "}}", "'", '"', '_', '[', '.', '%', '+', '|', '(', ')', '{', '}', ' \\ ', '/']
for tmp in black_list:
    if tmp in v:
        raise ValueError("note cannot contain a special character")

四、其他防御手段

PHP防御

SQL注入防御

  1. addslashes()函数:
$username = $_GET['username'];
$password = $_GET['password'];
$username = addslashes($username);
$password = addslashes($password);
  1. 全局过滤:
foreach($_REQUEST as $key=>$value) {
    $_POST[$key] = addslashes($value);
    $_GET[$key] = addslashes($value);
    $_REQUEST[$key] = addslashes($value);
}
  1. 预处理(最佳方案):
// MySQLi预处理
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();

.htaccess防护

  1. 完全禁止访问:
<IfModule mod_rewrite.c>
    deny from all
</IfModule>
  1. 禁止访问ph开头的文件:
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule \.ph.*$ - [F]
</IfModule>
  1. 防不死马:
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^\.index\.php$ - [F]
</IfModule>

ThinkPHP框架防护

foreach($_REQUEST as $key=>$value) {
    $_POST[$key] = preg_replace("/construct|get|call_user_func|load|invokefunction|Session|phpinfo|param1|Runtime|assert|input|dump|checkcode|union|select|updatexml|@/i",'',$value);
    $_GET[$key] = preg_replace("/construct|get|call_user_func|load|invokefunction|Session|phpinfo|param1|Runtime|assert|input|dump|checkcode|union|select|updatexml|@/i",'',$value);
}

Java防御

文件上传监控

./monitor-Go

命令黑名单

String a = "123";
String[] blacklist = {"Runtime", "\\u", "exec", "\"", "+", "'", "", "(", ")", "\\", "<", ">"};
for (int i = 0; i < blacklist.length; i++){
    if (a.contains(blacklist[i])){
        throw new Exception("");
    }
}

反序列化防护

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.util.HashSet;
import java.util.Set;

public class NewObjectInputStream extends ObjectInputStream {
    private static final Set<String> BLACKLISTED_CLASSES = new HashSet();
    
    static {
        BLACKLISTED_CLASSES.add("java.lang.Runtime");
        BLACKLISTED_CLASSES.add("java.lang.ProcessBuilder");
        BLACKLISTED_CLASSES.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
        BLACKLISTED_CLASSES.add("java.security.SignedObject");
    }
    
    public NewObjectInputStream(InputStream inputStream) throws IOException {
        super(inputStream);
    }
    
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
        if (BLACKLISTED_CLASSES.contains(desc.getName())) {
            throw new SecurityException("");
        }
        return super.resolveClass(desc);
    }
}

Node.js防御

参数白名单

  • 将merge参数改为白名单,只能传入admin

黑名单过滤

const blacklist = [' exec ',' \' ',' "']
const a = " 123 "
for (const pattern of blacklist){
    if (pattern.includes(a)){
        throw new Error(``);
    }
}

Python防御

SQL注入防护

conn = sqlite3.connect('db.sqlite3')
cursor = conn.cursor()
cursor.execute("INSERT INTO sys_users (username, password, role) VALUES (?, ?, ?)", 
              (username, password, role))

黑名单过滤

content = ''
blacklist = [' \' ', 'union', ' \" ', 'select', '(', ')', ',', ' ', '%']
for i in blacklist:
    if i in content.lower():
        exit()

五、AWDP比赛实战经验

安恒AWDP比赛特点

  • 历史比赛:羊城杯2023、楚慧杯2024、CISCN2024华东南
  • 赛制特点
    • Break和Fix分开进行
    • 通过SSH连接自行修改代码
    • 每小时Check一次,统一检查修复情况
  • 题目类型
    1. 签到题
    2. 文件上传
    3. 代码审计
    4. Python漏洞
    5. 压轴题
  • 策略建议
    • 第一轮修出3个基本能拿证书
    • 签到和文件上传通常能快速解决

永信至诚AWDP比赛特点

  • 历史比赛:CISCN2023、春秋杯夏季赛
  • 赛制特点
    • Fix给15-20次机会,可随时使用
    • 上传压缩文件包(patch包)
  • 检测状态
    • exp利用成功
    • 检测/运行异常
    • 防御成功
    • 服务检测异常(可能原因):
      • 过滤了正常流量中的某些字符
      • 页面返回结果不符合逻辑

Patch包制作指南

  1. PHP示例
#!/bin/bash
cp /index.php /var/www/html/index.php
  1. Python示例
#!/bin/sh
cp /app.py /app/app.py
ps -ef | grep python | grep -v grep | awk '{print $2}' | xargs kill -9
cd /app && nohup python app.py >> /opt/app.log 2>&1 &
  1. Go示例
#!/bin/bash
kill -9 $(pidof app)
cp ezgo_patch /app
chmod +x /app/app 2>&1 >/dev/null &
  1. Node.js示例
#!/bin/sh
cp server.js /app/server.js
ps -ef | grep node | grep -v grep | awk '{print $2}' | xargs kill -9
cd /app && nohup node server.js >> /opt/aa.log 2>&1 &
  1. 文件移动
mv -f explorer.php /www/html/
# 或
mv -f explorer.php $(dirname `find / -name 'explorer.php' 2>/dev/null`)/explorer.php

打包命令

tar -zcvf patch.tar.gz main.py patch.sh

杀线程命令

# JavaScript
ps -ef|grep npm|grep -v grep |awk '{print $2}'|xargs kill -9
ps -ef|grep node|grep -v grep |awk '{print $2}'|xargs kill -9

# 根据目录杀线程
ps -ef|grep app|grep -v grep |awk '{print $2}'|xargs kill -9

权限设置

sudo chmod -R 777 /app/*

六、实战案例解析

案例1:[羊城杯-2023-决赛] ezSSTI

Break阶段:

  • 使用焚靖工具快速检测SSTI漏洞:
python -m fenjing crack --method GET --inputs name --url 'http://10.1.110.2:20000/'

Fix阶段:

  • 加强正则过滤:
if (!re.findall(r"'|_|\\x|\\u|{{|\+|attr|\.| |class|init|globals|popen|system|env|exec|shell_exec|flag|passthru|proc_popen|{|set|\[|\(|%7b|eval|1|2|3|4|5|6|7|8|9", name)):

案例2:[羊城杯-2023-决赛] easyupload

Break阶段:

  • 利用Apache解析漏洞:
    • 上传文件名:shell.php.txt
    • Payload:1=system('tac /flag.txt');

Fix阶段:

  1. 黑名单改白名单:
$deny_ext = array(".jpg", ".png", ".jpeg");
  1. 限制文件名只能有一个点:
if (in_array($file_ext, $deny_ext) && substr_count($_FILES['upload_file']['name'], '.') === 1)

案例3:[羊城杯-2023-决赛] BabyMemo

Break阶段:

  1. 利用session文件伪造:
    • 用户名设为sess
    • 文件名格式:sess_PHPSESSID
    • 写入内容:admin|b:1;username|s:4:"sess";memos|a:2:{i:0;s:3:"aaa";i:1;s:3:"aaa";}

Fix阶段:

  • 禁止用户名为sess
if ($_POST['username'] != "sess"){
    $_SESSION['username'] = $_POST['username'];
}

案例4:[羊城杯-2023-决赛] fuzee_rce

Break阶段:

  1. 绕过数字检查(科学计数法):
    • Payload:?w1key=1e9
  2. 自增RCE:
    • Payload:
      $%ff=_(%ff/%ff)[%ff];%2b%2b$%ff;$_=$%ff.$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;2b%2b$%ff.%2b%2b$%ff;
      

\[_[%ff] ``` 传参:`%ff=system&_=tac /flag` #### Fix阶段: - 加强WAF过滤: ```php if (!preg_match("/[1-9a-zA-Z! \" |`~ \\\\ _$%]/", $w1key)) ``` ### 案例5:[羊城杯-2023-决赛] Oh! My PDF #### Break阶段: 1. 伪造JWT(空密钥): - Header:`{"typ": "JWT","alg": "HS256"}` - Payload:`{"username": "admin","isadmin": true}` 2. 利用WeasyPrint漏洞: - 创建HTML文件: ```html ``` - 通过PDF生成器访问该HTML #### Fix阶段: - 加强JWT验证 - 限制PDF生成内容 - 禁止加载HTML文件 - 更换PDF库 ## 七、正则表达式参考 ### PHP正则 ```php // 校验数字 数字:^[0-9]*$ n位数字:^\d{n}$ 至少n位数字:^\d{n,}$ m-n位数字:^\d{m,n}$ // 校验字符 汉字:^[\u4e00-\u9fa5]{0,}$ 英文和数字:^[A-Za-z0-9]+$ 长度为3-20的所有字符:^.{3,20}$ 由26个英文字母组成的字符串:^[A-Za-z]+$ // 特殊需求 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? InternetURL:[a-zA-z]+://[^\s]* 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$ 身份证号:15或18位身份证:^\d{15}|\d{18}$ ``` ### Python正则 ```python import re # 检查字符串是否包含字母"a" txt = "Hello, world!" match = re.search("a", txt) print(match) # 输出:None,因为"a"没有在字符串中 ``` ### Java正则 ```java \\:将下一字符标记为特殊字符、文本、反向引用或八进制转义符 ^:匹配输入字符串开始的位置 $:匹配输入字符串结尾的位置 [abc]:表示可能是a,可能是b,也可能是c [^abc]:表示不是a,b,c中的任意一个 [a-zA-Z]:表示是英文字母 [0-9]:表示是数字 ``` ## 八、总结 AWDP比赛要求选手同时具备攻击和防御能力,关键在于: 1. **快速识别漏洞**:通过代码审计、黑盒测试等方法快速定位漏洞 2. **有效防御**:根据漏洞类型选择合适的防御方案,WAF是最通用的手段 3. **实战经验积累**:平时积累各种漏洞的利用和防御方法 4. **工具准备**:准备好各种语言的WAF模板和正则表达式库 5. **策略选择**:优先Fix,同时思考Break方案 通过系统学习和实践这些技术,可以显著提升在AWDP比赛中的表现。\]

AWDP赛制详解与实战防御指南 一、AWDP赛制概述 AWDP(Attack With Defense Plus)是一种综合考核参赛团队攻击、防御技术能力、即时策略的攻防兼备比赛模式。每个参赛队互为攻击方和防守方,充分体现比赛的实战性、实时性和对抗性。 比赛组成 Break :使用自己的payload打通目标系统 Fix :使主办方的payload无法打通自己的系统 策略建议 : Fix通常比Break容易,优先Fix 如果是分时进行的,Break时建议同时思考Fix方案 赛前准备 离线语言手册(如utools) 安全文章库 各语言WAF(Web应用防火墙)模板 二、常见防御手段 通用防御 上WAF 注释漏洞语句 语言/漏洞特定防御 PHP特性 基本无特殊防御意义 SQL注入 WAF addslashes() 函数过滤 预处理(最佳方案) SSTI(服务器端模板注入) WAF(仅过滤 { 不够) 原型链污染 注释污染相关代码 文件上传 后缀强校验 文件内容WAF MIME头校验(建议同时实施) Java 注释漏洞代码 上调库版本 WAF 代码审计 WAF 注释漏洞代码 三、WAF编写指南 通用注意事项 注意语法正确性,本地测试 单个语法错误可能导致全部防御失效 平时积累有效的WAF规则 PHP WAF示例 基础过滤: RCE防御: SQL注入防御: XSS防御: Go WAF示例 依赖strings库版本: 不依赖库版本: Node.js WAF示例 Java WAF示例 Python WAF示例 四、其他防御手段 PHP防御 SQL注入防御 addslashes() 函数: 全局过滤: 预处理(最佳方案): .htaccess防护 完全禁止访问: 禁止访问ph开头的文件: 防不死马: ThinkPHP框架防护 Java防御 文件上传监控 命令黑名单 反序列化防护 Node.js防御 参数白名单 将merge参数改为白名单,只能传入admin 黑名单过滤 Python防御 SQL注入防护 黑名单过滤 五、AWDP比赛实战经验 安恒AWDP比赛特点 历史比赛 :羊城杯2023、楚慧杯2024、CISCN2024华东南 赛制特点 : Break和Fix分开进行 通过SSH连接自行修改代码 每小时Check一次,统一检查修复情况 题目类型 : 签到题 文件上传 代码审计 Python漏洞 压轴题 策略建议 : 第一轮修出3个基本能拿证书 签到和文件上传通常能快速解决 永信至诚AWDP比赛特点 历史比赛 :CISCN2023、春秋杯夏季赛 赛制特点 : Fix给15-20次机会,可随时使用 上传压缩文件包(patch包) 检测状态 : exp利用成功 检测/运行异常 防御成功 服务检测异常(可能原因): 过滤了正常流量中的某些字符 页面返回结果不符合逻辑 Patch包制作指南 PHP示例 : Python示例 : Go示例 : Node.js示例 : 文件移动 : 打包命令 杀线程命令 权限设置 六、实战案例解析 案例1:[ 羊城杯-2023-决赛 ] ezSSTI Break阶段: 使用焚靖工具快速检测SSTI漏洞: Fix阶段: 加强正则过滤: 案例2:[ 羊城杯-2023-决赛 ] easyupload Break阶段: 利用Apache解析漏洞: 上传文件名: shell.php.txt Payload: 1=system('tac /flag.txt'); Fix阶段: 黑名单改白名单: 限制文件名只能有一个点: 案例3:[ 羊城杯-2023-决赛 ] BabyMemo Break阶段: 利用session文件伪造: 用户名设为 sess 文件名格式: sess_PHPSESSID 写入内容: admin|b:1;username|s:4:"sess";memos|a:2:{i:0;s:3:"aaa";i:1;s:3:"aaa";} Fix阶段: 禁止用户名为 sess : 案例4:[ 羊城杯-2023-决赛] fuzee_ rce Break阶段: 绕过数字检查(科学计数法): Payload: ?w1key=1e9 自增RCE: Payload: 传参: %ff=system&_=tac /flag Fix阶段: 加强WAF过滤: 案例5:[ 羊城杯-2023-决赛] Oh ! My PDF Break阶段: 伪造JWT(空密钥): Header: {"typ": "JWT","alg": "HS256"} Payload: {"username": "admin","isadmin": true} 利用WeasyPrint漏洞: 创建HTML文件: 通过PDF生成器访问该HTML Fix阶段: 加强JWT验证 限制PDF生成内容 禁止加载HTML文件 更换PDF库 七、正则表达式参考 PHP正则 Python正则 Java正则 八、总结 AWDP比赛要求选手同时具备攻击和防御能力,关键在于: 快速识别漏洞 :通过代码审计、黑盒测试等方法快速定位漏洞 有效防御 :根据漏洞类型选择合适的防御方案,WAF是最通用的手段 实战经验积累 :平时积累各种漏洞的利用和防御方法 工具准备 :准备好各种语言的WAF模板和正则表达式库 策略选择 :优先Fix,同时思考Break方案 通过系统学习和实践这些技术,可以显著提升在AWDP比赛中的表现。