cssp protocol proxy

This commit is contained in:
citronneur
2015-03-05 22:28:33 +01:00
parent 8fb4893b6f
commit 0695825d98
7 changed files with 107 additions and 55 deletions

View File

@@ -183,7 +183,6 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
#len of next packet pass to next state function #len of next packet pass to next state function
self._expectedLen = 0 self._expectedLen = 0
self._factory = None self._factory = None
self._immediateCallback = None
def setFactory(self, factory): def setFactory(self, factory):
""" """
@@ -243,28 +242,6 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
#default callback is recv from LayerAutomata #default callback is recv from LayerAutomata
self.setNextState(callback) 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): def send(self, message):
""" """
@summary: Send Stream on TCP layer @summary: Send Stream on TCP layer

View File

@@ -303,9 +303,12 @@ class LicenseManager(object):
""" """
#get server information #get server information
serverRandom = licenseRequest.serverRandom.value serverRandom = licenseRequest.serverRandom.value
s = Stream(licenseRequest.serverCertificate.blobData.value) if self._transport.getGCCServerSettings().SC_SECURITY.serverCertificate._is_readed:
serverCertificate = gcc.ServerCertificate() serverCertificate = self._transport.getGCCServerSettings().SC_SECURITY.serverCertificate
s.readType(serverCertificate) else:
s = Stream(licenseRequest.serverCertificate.blobData.value)
serverCertificate = gcc.ServerCertificate()
s.readType(serverCertificate)
#generate crypto values #generate crypto values
clientRandom = rsa.random(256) clientRandom = rsa.random(256)

View File

@@ -24,7 +24,10 @@
from pyasn1.type import namedtype, univ, tag from pyasn1.type import namedtype, univ, tag
from pyasn1.codec.der import encoder, decoder 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): class NegoToken(univ.Sequence):
componentType = namedtype.NamedTypes( componentType = namedtype.NamedTypes(
@@ -101,7 +104,7 @@ def encodeDERTRequest(negoTypes = [], pubKeyAuth = None):
""" """
@summary: create TSRequest from list of Type @summary: create TSRequest from list of Type
@param negoTypes: {list(Type)} @param negoTypes: {list(Type)}
@return: {String} @return: {str}
""" """
negoData = NegoData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) negoData = NegoData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))
@@ -121,14 +124,14 @@ def encodeDERTRequest(negoTypes = [], pubKeyAuth = None):
if not pubKeyAuth is None: if not pubKeyAuth is None:
request.setComponentByName("pubKeyAuth", univ.OctetString(pubKeyAuth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) 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): def decodeDERTRequest(s):
""" """
@summary: Decode the stream as @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): def getNegoTokens(tRequest):
negoData = tRequest.getComponentByName("negoTokens") negoData = tRequest.getComponentByName("negoTokens")
@@ -136,3 +139,79 @@ def getNegoTokens(tRequest):
def getPubKeyAuth(tRequest): 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]))))

View File

@@ -683,9 +683,9 @@ if __name__ == "__main__":
ClientChallenge = temp[16:24] ClientChallenge = temp[16:24]
EncryptedRandomSessionKey = authenticate.getEncryptedRandomSession() EncryptedRandomSessionKey = authenticate.getEncryptedRandomSession()
domain = "dodo" domain = "siradel"
user = "uouo" user = "speyrefitte"
password = "popo" password = "spe+99@12"
ResponseKeyNT = NTOWFv2(password, user, domain) ResponseKeyNT = NTOWFv2(password, user, domain)
ResponseKeyLM = LMOWFv2(password, user, domain) ResponseKeyLM = LMOWFv2(password, user, domain)

View File

@@ -29,6 +29,7 @@ import pdu.caps
import rdpy.core.log as log import rdpy.core.log as log
import tpkt, x224, sec import tpkt, x224, sec
from t125 import mcs, gcc from t125 import mcs, gcc
from nla import cssp, ntlm
class RDPClientController(pdu.layer.PDUClientListener): class RDPClientController(pdu.layer.PDUClientListener):
""" """
@@ -526,7 +527,8 @@ class ClientFactory(layer.RawLayerClientFactory):
""" """
controller = RDPClientController() controller = RDPClientController()
self.buildObserver(controller, addr) 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): def buildObserver(self, controller, addr):
""" """

View File

@@ -114,7 +114,6 @@ class TPKT(RawLayer, IFastPathSender):
self._fastPathListener = None self._fastPathListener = None
#last secure flag #last secure flag
self._secFlag = 0 self._secFlag = 0
self._ntlm = ntlm.NTLMv2("dodo", "uouo", "popo")
def setFastPathListener(self, fastPathListener): def setFastPathListener(self, fastPathListener):
""" """
@@ -224,18 +223,4 @@ class TPKT(RawLayer, IFastPathSender):
@summary: use to start NLA (NTLM over SSL) protocol @summary: use to start NLA (NTLM over SSL) protocol
must be called after startTLS function must be called after startTLS function
""" """
#import hexdump self.transport.startNLA()
#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()

View File

@@ -150,8 +150,14 @@ def extractRSAKey(certificate):
binaryTuple = certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('subjectPublicKey') binaryTuple = certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('subjectPublicKey')
l = int("".join([str(i) for i in binaryTuple]), 2) 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 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'))