备战6月23日的CISCN线下赛 AWDP
前言 本次CISCN华东南赛区我们学校是承办方,当然晋级名额变成三队,不过由于本人实力有限加上最后黑灯的时候差一点做出来easycms-revenge,本来都打算退役了。在看到主办方发的晋级名单后,发现我们以倒一晋级线下赛,实在是续了下香火。既然都进了,总不能玩几小时pvz吧,所以打算从今天开始备战AWDP
AWDP 首先了解一下什么是 AWDP ,AWDP模式(Attack,Defense,WebandPwn),分为 Break 与 Fix 环节。根据英文全称也可以看出来,只有 Web 和 Pwn 这两个方向的题目。
每个战队拥有相同的起始分数及相同配置的虚拟靶机,参赛队员需对平台中的GameBox发起攻击,向平台提交正确的flag(证明自己具备对该题的攻击能力);在此期间,由平台以轮次制的方式向参赛战队的靶机发起攻击,检查其他选手的漏洞是否修补成功,若修补成功则认为参赛战队具备该漏洞的防御能力。
简单来说,AWDP 和传统 CTF 并无任何区别,仅仅是多了一个 Fix 功能,也就是你提交 flag 后拿到的是攻击分,而 Fix 成功后才会拿到防御分。
文件传输 这里以xshell和xftp为例
我们先使用xshell连接服务器,进入到test文件夹
然后新建一个shell,点击新建文件传输
然后自动弹出来xftp,添加会话连接
连接好后,右键对应文件点击传输即可
防守WAF 参考文章 
PHP RCE 1 2 3 function wafrce($str){     return !preg_match("/openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|scandir|assert|pcntl_exec|fwrite|curl|system|eval|assert|tail|flag|exec|base64|passthru|exec|chroot|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore/i", $str); } 
1 2 3 4 if (preg_match('/(system|exec|shell_exec|passthru|eval|assert)/i', $_GET['do'])) {         die('hacker');     }     return $_GET['do']; 
SQL注入 1 2 3 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 1 2 3 function wafxss($str){     return !preg_match("/\'|http|\"|\`|cookie|<|>|script/i", $str); } 
文件上传 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?php // 允许上传的文件类型 $allowedExtensions = array("jpg", "jpeg", "png", "gif"); // 上传文件的目录 $uploadDir = "uploads/"; // 检查文件是否上传成功 if (isset($_FILES["file"])) {     $file = $_FILES["file"];     // 获取文件的扩展名     $extension = pathinfo($file["name"], PATHINFO_EXTENSION);     // 检查文件类型是否允许上传     if (!in_array(strtolower($extension), $allowedExtensions)) {         echo "只允许上传以下类型的文件: " . implode(", ", $allowedExtensions);         exit;     }     // 检查上传文件是否为真实的图像文件     if (getimagesize($file["tmp_name"]) === false) {         echo "上传文件不是有效的图像文件。";         exit;     }     // 生成一个唯一的文件名以避免重复     $uniqueFileName = uniqid() . "." . $extension;     // 移动上传的文件到目标目录     if (move_uploaded_file($file["tmp_name"], $uploadDir . $uniqueFileName)) {         echo "文件上传成功!";     } else {         echo "文件上传失败。";     } } 
XXE 1 2 3 4 5 <?php $xmlData = file_get_contents('php://input'); libxml_disable_entity_loader(true); $xml = simplexml_load_string($xmlData); echo $xml->name; 
Python 自定义过滤关键词
1 2 3 4 5 filter_list = ["apple", "banana", "cherry"] strings = "ana"  # 匹配包含"ana"的字符串 for i in filter_list:     if i in strings:         print("Hacker!" ) 
Nodejs 自定义过滤关键词
1 2 3 4 5 6 7 const keywords = ["apple", "banana", "cherry"]; for (const i of keywords) {     if (code.includes(i)) {         console.log("Hacker!")      } } 
Java 自定义过滤关键词 1 2 3 4 5 6 7 8 String[] filterList = {"apple", "banana", "cherry"}; String str = "ana"; // 匹配包含"ana"的字符串 for (String s : filterList) {     if (s.contains(str)) {         System.out.println("Hacker!");     } } 
SSRF 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 /**  @ author: Drunkbaby  @ usages: 用于 SSRF 的自定义防护  去到对应的接口下面修改即可  */ import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Enumeration; /**  @ author: Drunkbaby  @ usages: 用于 SSRF 的自定义防护  @ ban 了几个协议,如果单纯全部阻挡什么 127.0.0.1,业务不一定过得去。  */ @Component @WebFilter(urlPatterns = "/system/role/list", filterName = "sqlInjectFilter") public class sqlFilter implements Filter {     public void destroy() {     }     public void init(FilterConfig arg0) throws ServletException {     }     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {         HttpServletRequest request = (HttpServletRequest) req;         HttpServletResponse response = (HttpServletResponse) res;         // 获得所有请求参数名         Enumeration params = request.getParameterNames();         String sql = "";         while (params.hasMoreElements()) {             // 得到参数名             String name = params.nextElement().toString();             // 得到参数对应值             String[] value = request.getParameterValues(name);             for (int i = 0; i < value.length; i++) {                 sql = sql + value[i];             }         }         if (sqlValidate(sql)) {             throw new IOException("您发送请求中的参数中含有非法字符");         } else {             chain.doFilter(request, response);         }     }     /**      * 参数校验      * @param str      */     public static boolean sqlValidate(String str) {         str = str.toLowerCase();//统一转为小写         String badStr = "file|http|jar|gopher|tar|war";         String[] badStrs = badStr.split("\\|");         for (int i = 0; i < badStrs.length; i++) {             //循环检测,判断在请求参数当中是否包含SQL关键字             if (str.indexOf(badStrs[i]) >= 0) {                 return true;             }         }         return false;     } } 
log4j2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package com.ruoyi.common.xss; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Enumeration; /**  @ author: Drunkbaby  @ usages: 用于 log4j2 的自定义防护  @ 过滤 url:在 WebFilter 当中添加 urlPatterns  */ @Component @WebFilter(urlPatterns = "/system/role/list", filterName = "sqlInjectFilter") public class Log4j2Filter implements Filter {     public void destroy() {     }     public void init(FilterConfig arg0) throws ServletException {     }     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {         HttpServletRequest request = (HttpServletRequest) req;         HttpServletResponse response = (HttpServletResponse) res;         // 获得所有请求参数名         Enumeration params = request.getParameterNames();         String sql = "";         while (params.hasMoreElements()) {             // 得到参数名             String name = params.nextElement().toString();             // 得到参数对应值             String[] value = request.getParameterValues(name);             for (int i = 0; i < value.length; i++) {                 sql = sql + value[i];             }         }         if (sqlValidate(sql)) {             throw new IOException("您发送请求中的参数中含有非法字符");         } else {             chain.doFilter(request, response);         }     }     /**      * 参数校验      * @param str      */     public static boolean sqlValidate(String str) {         str = str.toLowerCase();//统一转为小写         String badStr = "$|$$|jndi|rmi|ldap|{|}|";         String[] badStrs = badStr.split("\\|");         for (int i = 0; i < badStrs.length; i++) {             //循环检测,判断在请求参数当中是否包含log4j2关键字             if (str.indexOf(badStrs[i]) >= 0) {                 return true;             }         }         return false;     } } 
文件上传 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 /**  @ author: Drunkbaby  @ usages: 用于文件上传的接口修改  @ 需要在对应接口中修改  */ @RestController public class securityUpload {     @RequestMapping("/securityUpload")     public String handleFileUpload(@RequestParam("file") MultipartFile file){         if (file.isEmpty()){             return "请上传文件";         }         // 获取文件名         String fileName = file.getOriginalFilename();         String suffix = fileName.substring(fileName.lastIndexOf("."));         String contentType = file.getContentType();         //过滤         String[] picWhite = {".png",".jpg",".gif",".webp",".bmp"};         String[] white_type = {"image/gif","image/jpeg","image/jpg","image/png"};         Boolean SuffixFlag = false;         Boolean TypeFlag = false;         for (String pic_suffix:picWhite){             if (suffix.toLowerCase().equals(pic_suffix)){                 SuffixFlag = true;                 break;             }         }         for (String white_suffix:white_type){             if (contentType.toLowerCase().equals(white_suffix)){                 TypeFlag = true;                 break;             }         }         if (!SuffixFlag||!TypeFlag){             return "File Type not allow";         }         String filePath = System.getProperty("user.dir")+"/tmp";         Date date = new Date();         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");         String newfileName = dateFormat.format(date)+Integer.toHexString((int)new Date().getTime())+suffix;         File dest = new File(filePath+File.separator+newfileName);         if (!dest.getParentFile().exists()){             dest.getParentFile().mkdirs();         }         try{             file.transferTo(dest);             return "上传成功";         } catch (IOException e) {             e.printStackTrace();             return "上传失败";         }     } } 
fastjson 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package FastjsonFilters; import java.util.Objects; import java.util.regex.Pattern; /**  @ author: Drunkbaby  @ usages: 用于 Fastjson 的自定义防护  @ 针对 1.2.24 版本,则只添加过滤即可,若针对其他版本  ParserConfig.getGlobalInstance().setAutoTypeSupport(false); 将 autoTypeSupprt 设置为 false  */ public class Fastjson1224Filter {     public String Unserjson(@RequestParam String str, @RequestParam String input) throws Exception {         if (str != null && Objects.hashCode(str) == secret.getKey().hashCode() && !secret.getKey().equals(str)) {             String pattern = ".*rmi.*|.*jndi.*|.*ldap.*|.*\\\\x.*";             Pattern p = Pattern.compile(pattern, 2);             boolean StrMatch = p.matcher(input).matches();             if (StrMatch) {                 return "Hacker get out!!!";             }             ParserConfig.getGlobalInstance().setAutoTypeSupport(true);             JSON.parseObject(input);         }         return "hello";     } } 
Golang 自定义过滤关键词
1 2 3 4 5 6 7 filterList := []string{"apple", "banana", "cherry"} str := "ana" // 匹配包含"ana"的字符串 for _, s := range filterList {     if strings.Contains(s, str) {         fmt.Println("Hacker!")     } } 
防御修复 打包&解包 1 tar -zcvf update.tar.gz update.sh file1 file2 
如果要求把要修补的文件上传到服务器里,替换原来服务器中的文件,所以我们要知道文件具体的路径,大概思路就是在根目录下查找该漏洞对应的文件路径,然后把我们修复的上传即可
PHP php不用重启服务,我们先cp把源码保存下来
1 cp index.php ../index.php 
然后把改好的文件移到对应位置
1 mv -f explorer.php index/explorer.php 
python 1 2 3 4 #!/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 & 
nodejs 1 2 3 4 #!/bin/sh cp ./app.js /app/app.js ps -ef | grep app.js | grep -v grep | awk '{print $2}' | xargs kill -9 nohup node /app/app.js || tail -f /dev/null & 
参考文章 https://5ime.cn/awdp.html 
https://blog.csdn.net/weixin_51614272/article/details/125527593 
https://fushuling.com/index.php/2024/06/15/ciscn%e8%a5%bf%e5%8d%97%e5%a4%8d%e8%b5%9bawdp-web/