Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
fatal0 authored Feb 25, 2020
1 parent 577c654 commit d28de70
Showing 1 changed file with 23 additions and 129 deletions.
152 changes: 23 additions & 129 deletions tomcat-cve-2020-1938-check.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func ajp_get_string(ajp_msg_ptr *[]byte, start uint16, end uint16) string {
return string(ajp_msg[start : start+end])
}

func readAjpResponseBody(conn net.Conn) string {
func readAjpResponseBody(conn net.Conn) (bool, string) {

//read header
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
Expand All @@ -117,7 +117,7 @@ func readAjpResponseBody(conn net.Conn) string {
_, err := conn.Read(header)
if err != nil {
fmt.Println("Read failed:", err.Error())
return ""
return false, ""
}
_ = ajp_get_string(&header, 0, 2)
length := ajp_get_uint16(&header, 2, 2)
Expand All @@ -127,14 +127,20 @@ func readAjpResponseBody(conn net.Conn) string {
_, err = conn.Read(content)
if err != nil {
fmt.Println("Read failed:", err.Error())
return ""
return false, ""
}
//read content
prefix := int(content[0])
status := ajp_get_uint16(&content, 1, 2)

if prefix != AJP13_SEND_HEADERS {
fmt.Println("Read Ajp Header failed")
return ""
return false, ""
} else {
if status == 403 {
fmt.Println("Read failed: status ", status)
return false, ""
}
}

for {
Expand All @@ -145,7 +151,7 @@ func readAjpResponseBody(conn net.Conn) string {
_, err = conn.Read(header)
if err != nil {
fmt.Println("Read failed:", err.Error())
return ""
return true, ""
}
_ = ajp_get_string(&header, 0, 2)
length := ajp_get_uint16(&header, 2, 2)
Expand All @@ -155,18 +161,18 @@ func readAjpResponseBody(conn net.Conn) string {
_, err = conn.Read(content)
if err != nil {
fmt.Println("Read failed:", err.Error())
return ""
return true, ""
}
//read content
prefix := int(content[0])

if prefix == AJP13_SEND_BODY_CHUNK {
dataLength := ajp_get_uint16(&content, 1, 2)
data := ajp_get_string(&content, 3, dataLength)
return data
return true, data

} else if prefix == AJP13_END_RESPONSE {
return ""
return true, ""
}

}
Expand Down Expand Up @@ -213,161 +219,49 @@ func makePayload(host string, port int16) []byte {

}

func getVersion(host string, port int16, payload []byte) string {
func getVersion(host string, port int16, payload []byte) (bool, string) {

conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 10*time.Second)

if err != nil {
fmt.Println("Connect failed:", err.Error())
return ""
return false, ""
}
defer conn.Close()

_, err = conn.Write(payload)
if err != nil {
fmt.Println("Write failed:", err.Error())
return ""
return false, ""
}

responseBody := readAjpResponseBody(conn)
isVulnerable, responseBody := readAjpResponseBody(conn)

verRegexp := regexp.MustCompile("Apache Tomcat/(.*)</h3>")

version := verRegexp.FindStringSubmatch(responseBody)
if len(version) > 1 {
return version[1]
return isVulnerable, version[1]
}
return ""
return isVulnerable, ""
}

func check(host string, port int16) {

conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Second*time.Duration(10))

if err != nil {
fmt.Println(err)
return
}
defer conn.Close()

ajpBuffer := makePayload(host, port)

version := getVersion(host, port, ajpBuffer)

if version == "" {
fmt.Println("get version error")
return
}

// Apache Tomcat 9.x < 9.0.31

// Apache Tomcat 8.x < 8.5.51

// Apache Tomcat 7.x < 7.0.100

// Apache Tomcat 6.x

isVulnerable := false

if strings.HasPrefix(version, "9") {
if compareStrVer(version, "9.0.31") == VersionSmall {
isVulnerable = true
}

} else if strings.HasPrefix(version, "8") {
if compareStrVer(version, "8.5.51") == VersionSmall {
isVulnerable = true
}

} else if strings.HasPrefix(version, "7") {
if compareStrVer(version, "7.0.100") == VersionSmall {
isVulnerable = true
}
} else if strings.HasPrefix(version, "6") {
isVulnerable = true
} else {
fmt.Println("unknown version: ", version)
return
}
isVulnerable, version := getVersion(host, port, ajpBuffer)

if isVulnerable {
fmt.Println("Apache Tomcat vulnerable, Version: ", version)
fmt.Printf("%s:%d is vulnerable, tomcat version: %s\n", host, port, version)
} else {
fmt.Println("Apache Tomcat not vulnerable, Version: ", version)
fmt.Printf("%s:%d is not vulnerable\n", host, port)
}

return

}

func compareStrVer(verA, verB string) int {

verStrArrA := spliteStrByNet(verA)
verStrArrB := spliteStrByNet(verB)

lenStrA := len(verStrArrA)
lenStrB := len(verStrArrB)

if lenStrA != lenStrB {
panic("version not match")

}

return compareArrStrVers(verStrArrA, verStrArrB)
}

func compareArrStrVers(verA, verB []string) int {

for index, _ := range verA {

littleResult := compareLittleVer(verA[index], verB[index])

if littleResult != VersionEqual {
return littleResult
}
}

return VersionEqual
}

func compareLittleVer(verA, verB string) int {

bytesA := []byte(verA)
bytesB := []byte(verB)

lenA := len(bytesA)
lenB := len(bytesB)
if lenA > lenB {
return VersionBig
}

if lenA < lenB {
return VersionSmall
}

return compareByBytes(bytesA, bytesB)
}

func compareByBytes(verA, verB []byte) int {

for index, _ := range verA {
if verA[index] > verB[index] {
return VersionBig
}
if verA[index] < verB[index] {
return VersionSmall
}

}

return VersionEqual
}

func spliteStrByNet(strV string) []string {

return strings.Split(strV, ". ")
}

func main() {

var host string
Expand Down

0 comments on commit d28de70

Please sign in to comment.