cssp protocol proxy
This commit is contained in:
@@ -183,7 +183,6 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
|
||||
#len of next packet pass to next state function
|
||||
self._expectedLen = 0
|
||||
self._factory = None
|
||||
self._immediateCallback = None
|
||||
|
||||
def setFactory(self, factory):
|
||||
"""
|
||||
@@ -242,28 +241,6 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
|
||||
self._expectedLen = expectedLen
|
||||
#default callback is recv from LayerAutomata
|
||||
self.setNextState(callback)
|
||||
|
||||
def dataReceivedAll(self, data):
|
||||
"""
|
||||
@summary: by pass automata received
|
||||
@warning: ignore rest in buffer
|
||||
@param data: {str} received from twisted
|
||||
"""
|
||||
self._immediateCallback(Stream(data))
|
||||
|
||||
def expectImmediately(self, callback):
|
||||
"""
|
||||
@summary: call immediately when available data is received
|
||||
@param callback: {func} callback called
|
||||
"""
|
||||
self.dataReceived = lambda data:self.__class__.dataReceivedAll(self, data)
|
||||
self._immediateCallback = callback
|
||||
|
||||
def restartAutomata(self):
|
||||
"""
|
||||
@summary: restart automata
|
||||
"""
|
||||
self.dataReceived = lambda data:self.__class__.dataReceived(self, data)
|
||||
|
||||
def send(self, message):
|
||||
"""
|
||||
|
||||
@@ -303,9 +303,12 @@ class LicenseManager(object):
|
||||
"""
|
||||
#get server information
|
||||
serverRandom = licenseRequest.serverRandom.value
|
||||
s = Stream(licenseRequest.serverCertificate.blobData.value)
|
||||
serverCertificate = gcc.ServerCertificate()
|
||||
s.readType(serverCertificate)
|
||||
if self._transport.getGCCServerSettings().SC_SECURITY.serverCertificate._is_readed:
|
||||
serverCertificate = self._transport.getGCCServerSettings().SC_SECURITY.serverCertificate
|
||||
else:
|
||||
s = Stream(licenseRequest.serverCertificate.blobData.value)
|
||||
serverCertificate = gcc.ServerCertificate()
|
||||
s.readType(serverCertificate)
|
||||
|
||||
#generate crypto values
|
||||
clientRandom = rsa.random(256)
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
|
||||
from pyasn1.type import namedtype, univ, tag
|
||||
from pyasn1.codec.der import encoder, decoder
|
||||
from rdpy.core.type import Stream, String
|
||||
from rdpy.core.type import Stream
|
||||
from rdpy.security import x509
|
||||
from twisted.internet import protocol
|
||||
from OpenSSL import crypto
|
||||
|
||||
class NegoToken(univ.Sequence):
|
||||
componentType = namedtype.NamedTypes(
|
||||
@@ -101,7 +104,7 @@ def encodeDERTRequest(negoTypes = [], pubKeyAuth = None):
|
||||
"""
|
||||
@summary: create TSRequest from list of Type
|
||||
@param negoTypes: {list(Type)}
|
||||
@return: {String}
|
||||
@return: {str}
|
||||
"""
|
||||
negoData = NegoData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))
|
||||
|
||||
@@ -121,18 +124,94 @@ def encodeDERTRequest(negoTypes = [], pubKeyAuth = None):
|
||||
if not pubKeyAuth is None:
|
||||
request.setComponentByName("pubKeyAuth", univ.OctetString(pubKeyAuth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)))
|
||||
|
||||
return String(encoder.encode(request))
|
||||
return encoder.encode(request)
|
||||
|
||||
def decodeDERTRequest(s):
|
||||
"""
|
||||
@summary: Decode the stream as
|
||||
@param s: ([{Stream}], {str} pubKeyAuth)
|
||||
@param s: {str}
|
||||
"""
|
||||
return decoder.decode(s.getvalue(), asn1Spec=TSRequest())[0]
|
||||
return decoder.decode(s, asn1Spec=TSRequest())[0]
|
||||
|
||||
def getNegoTokens(tRequest):
|
||||
negoData = tRequest.getComponentByName("negoTokens")
|
||||
return [Stream(negoData.getComponentByPosition(i).getComponentByPosition(0).asOctets()) for i in range(len(negoData))]
|
||||
|
||||
def getPubKeyAuth(tRequest):
|
||||
return tRequest.getComponentByName("pubKeyAuth").asOctets()
|
||||
return tRequest.getComponentByName("pubKeyAuth").asOctets()
|
||||
|
||||
class CSSP(protocol.Protocol):
|
||||
"""
|
||||
@summary: Handle CSSP connection
|
||||
Proxy class for authentication
|
||||
"""
|
||||
def __init__(self, layer, authenticationProtocol):
|
||||
"""
|
||||
@param layer: {type.Layer.RawLayer}
|
||||
@param authenticationProtocol: {sspi.IAuthenticationProtocol}
|
||||
"""
|
||||
self._layer = layer
|
||||
self._authenticationProtocol = authenticationProtocol
|
||||
|
||||
def setFactory(self, factory):
|
||||
"""
|
||||
@summary: Call by RawLayer Factory
|
||||
@param param: RawLayerClientFactory or RawLayerFactory
|
||||
"""
|
||||
self._layer.setFactory(factory)
|
||||
|
||||
def dataReceived(self, data):
|
||||
"""
|
||||
@summary: Inherit from twisted.protocol class
|
||||
main event of received data
|
||||
@param data: string data receive from twisted
|
||||
"""
|
||||
self._layer.dataReceived(data)
|
||||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
@summary: install proxy
|
||||
"""
|
||||
self._layer.transport = self
|
||||
self._layer.connectionMade()
|
||||
|
||||
def write(self, data):
|
||||
"""
|
||||
@summary: write data on transport layer
|
||||
@param data: {str}
|
||||
"""
|
||||
self.transport.write(data)
|
||||
|
||||
def startTLS(self, sslContext):
|
||||
"""
|
||||
@summary: start TLS protocol
|
||||
@param sslContext: {ssl.ClientContextFactory | ssl.DefaultOpenSSLContextFactory} context use for TLS protocol
|
||||
"""
|
||||
self.transport.startTLS(sslContext)
|
||||
|
||||
def startNLA(self):
|
||||
"""
|
||||
@summary: start NLA authentication
|
||||
"""
|
||||
#send negotiate message
|
||||
self.transport.write(encodeDERTRequest( negoTypes = [ self._authenticationProtocol.getNegotiateMessage() ] ))
|
||||
#next state is receive a challenge
|
||||
self.dataReceived = self.recvChallenge
|
||||
|
||||
def recvChallenge(self, data):
|
||||
"""
|
||||
@summary: second state in cssp automata
|
||||
@param {str}: all data available on buffer
|
||||
"""
|
||||
#get back public key
|
||||
toto = self.transport.protocol._tlsConnection.get_peer_certificate().get_pubkey()
|
||||
lolo = crypto.dump_privatekey(crypto.FILETYPE_ASN1, toto)
|
||||
modulus, exponent = x509.extractRSAKey2(lolo)
|
||||
import hexdump
|
||||
print lolo
|
||||
hexdump.hexdump(lolo)
|
||||
request = decodeDERTRequest(data)
|
||||
message, interface = self._authenticationProtocol.getAuthenticateMessage(getNegoTokens(request)[0])
|
||||
#send authenticate message with public key encoded
|
||||
import ntlm
|
||||
self.transport.write(encodeDERTRequest( negoTypes = [ message ], pubKeyAuth = interface.GSS_WrapEx("".join([chr(i) for i in ntlm.pubKeyHex]))))
|
||||
@@ -683,9 +683,9 @@ if __name__ == "__main__":
|
||||
ClientChallenge = temp[16:24]
|
||||
EncryptedRandomSessionKey = authenticate.getEncryptedRandomSession()
|
||||
|
||||
domain = "dodo"
|
||||
user = "uouo"
|
||||
password = "popo"
|
||||
domain = "siradel"
|
||||
user = "speyrefitte"
|
||||
password = "spe+99@12"
|
||||
ResponseKeyNT = NTOWFv2(password, user, domain)
|
||||
ResponseKeyLM = LMOWFv2(password, user, domain)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import pdu.caps
|
||||
import rdpy.core.log as log
|
||||
import tpkt, x224, sec
|
||||
from t125 import mcs, gcc
|
||||
from nla import cssp, ntlm
|
||||
|
||||
class RDPClientController(pdu.layer.PDUClientListener):
|
||||
"""
|
||||
@@ -526,7 +527,8 @@ class ClientFactory(layer.RawLayerClientFactory):
|
||||
"""
|
||||
controller = RDPClientController()
|
||||
self.buildObserver(controller, addr)
|
||||
return controller.getProtocol()
|
||||
#Add cssp proxy in case of nla protocol
|
||||
return cssp.CSSP(controller.getProtocol(), ntlm.NTLMv2("toto", "coco", "lolo"))
|
||||
|
||||
def buildObserver(self, controller, addr):
|
||||
"""
|
||||
|
||||
@@ -114,7 +114,6 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
self._fastPathListener = None
|
||||
#last secure flag
|
||||
self._secFlag = 0
|
||||
self._ntlm = ntlm.NTLMv2("dodo", "uouo", "popo")
|
||||
|
||||
def setFastPathListener(self, fastPathListener):
|
||||
"""
|
||||
@@ -224,18 +223,4 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
@summary: use to start NLA (NTLM over SSL) protocol
|
||||
must be called after startTLS function
|
||||
"""
|
||||
#import hexdump
|
||||
#hexdump.hexdump(self.transport.protocol._tlsConnection.getpeercert())
|
||||
#send NTLM negotiate message packet
|
||||
RawLayer.send(self, cssp.encodeDERTRequest( negoTypes = [ self._ntlm.getNegotiateMessage() ] ))
|
||||
self.expectImmediately(self.readNTLMChallenge)
|
||||
|
||||
def readNTLMChallenge(self, data):
|
||||
"""
|
||||
@summary: server NTLM challenge
|
||||
@param data: {Stream}
|
||||
"""
|
||||
request = cssp.decodeDERTRequest(data)
|
||||
message, interface = self._ntlm.getAuthenticateMessage(cssp.getNegoTokens(request)[0])
|
||||
RawLayer.send(self, cssp.encodeDERTRequest( negoTypes = [ message ], pubKeyAuth = interface.GSS_WrapEx("".join([chr(i) for i in ntlm.pubKeyHex]))))
|
||||
self.restartAutomata()
|
||||
self.transport.startNLA()
|
||||
@@ -150,8 +150,14 @@ def extractRSAKey(certificate):
|
||||
|
||||
binaryTuple = certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('subjectPublicKey')
|
||||
l = int("".join([str(i) for i in binaryTuple]), 2)
|
||||
rsaKey = decoder.decode(hex(l)[2:-1].decode('hex'), asn1Spec=RSAPublicKey())[0]
|
||||
return extractRSAKeyFromASN1(hex(l)[2:-1].decode('hex'))
|
||||
|
||||
def extractRSAKeyFromASN1(subjectPublicKey):
|
||||
rsaKey = decoder.decode(subjectPublicKey, asn1Spec=RSAPublicKey())[0]
|
||||
return rsaKey.getComponentByName('modulus')._value , rsaKey.getComponentByName('publicExponent')._value
|
||||
|
||||
|
||||
|
||||
def extractRSAKey2(key):
|
||||
binaryTuple = decoder.decode(key, asn1Spec=univ.BitString())[0]
|
||||
l = int("".join([str(i) for i in binaryTuple]), 2)
|
||||
return extractRSAKeyFromASN1(hex(l)[2:-1].decode('hex'))
|
||||
|
||||
Reference in New Issue
Block a user