finish RDP basic security layer for server side but have bug on faspath + basic security layer...

This commit is contained in:
speyrefitte
2014-12-24 17:20:09 +01:00
parent 28f50b1f0e
commit f4808d0ae2
7 changed files with 90 additions and 55 deletions

View File

@@ -22,6 +22,7 @@ Implement GCC structure use in RDP protocol
http://msdn.microsoft.com/en-us/library/cc240508.aspx
"""
import md5
from rdpy.core.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, Stream, sizeof, FactoryType, ArrayType
import per, mcs
from rdpy.core.error import InvalidExpectedDataException
@@ -314,7 +315,7 @@ class ServerCertificate(CompositeType):
"""
def __init__(self, certData = None, readLen = None, conditional = lambda:True):
CompositeType.__init__(self, readLen = readLen, conditional = conditional)
self.dwVersion = UInt32Le(lambda:self.certData.__class__._TYPE_)
self.dwVersion = UInt32Le(lambda:(self.certData.__class__._TYPE_))
def CertificateFactory():
"""
@@ -330,7 +331,7 @@ class ServerCertificate(CompositeType):
elif not "_TYPE_" in certData.__class__.__dict__:
raise InvalidExpectedDataException("Try to send an invalid Certificate")
self.certData = FactoryType(CertificateFactory)
self.certData = certData
class ProprietaryServerCertificate(CompositeType):
"""
@@ -339,6 +340,11 @@ class ProprietaryServerCertificate(CompositeType):
"""
_TYPE_ = CertificateType.CERT_CHAIN_VERSION_1
#http://msdn.microsoft.com/en-us/library/cc240776.aspx
_TERMINAL_SERVICES_MODULUS_ = "\x3d\x3a\x5e\xbd\x72\x43\x3e\xc9\x4d\xbb\xc1\x1e\x4a\xba\x5f\xcb\x3e\x88\x20\x87\xef\xf5\xc1\xe2\xd7\xb7\x6b\x9a\xf2\x52\x45\x95\xce\x63\x65\x6b\x58\x3a\xfe\xef\x7c\xe7\xbf\xfe\x3d\xf6\x5c\x7d\x6c\x5e\x06\x09\x1a\xf5\x61\xbb\x20\x93\x09\x5f\x05\x6d\xea\x87"
_TERMINAL_SERVICES_PRIVATE_EXPONENT_ = "\x87\xa7\x19\x32\xda\x11\x87\x55\x58\x00\x16\x16\x25\x65\x68\xf8\x24\x3e\xe6\xfa\xe9\x67\x49\x94\xcf\x92\xcc\x33\x99\xe8\x08\x60\x17\x9a\x12\x9f\x24\xdd\xb1\x24\x99\xc7\x3a\xb8\x0a\x7b\x0d\xdd\x35\x07\x79\x17\x0b\x51\x9b\xb3\xc7\x10\x01\x13\xe7\x3f\xf3\x5f"
_TERMINAL_SERVICES_PUBLIC_EXPONENT_ = "\x5b\x7b\x88\xc0"
def __init__(self):
CompositeType.__init__(self)
self.dwSigAlgId = UInt32Le(0x00000001, constant = True)
@@ -347,8 +353,9 @@ class ProprietaryServerCertificate(CompositeType):
self.wPublicKeyBlobLen = UInt16Le(lambda:sizeof(self.PublicKeyBlob))
self.PublicKeyBlob = RSAPublicKey(readLen = self.wPublicKeyBlobLen)
self.wSignatureBlobType = UInt16Le(0x0008, constant = True)
self.wSignatureBlobLen = UInt16Le(lambda:sizeof(self.SignatureBlob))
self.wSignatureBlobLen = UInt16Le(lambda:(sizeof(self.SignatureBlob) - 8))
self.SignatureBlob = String(readLen = self.wSignatureBlobLen)
self.padding = String("\x00" * 8, readLen = UInt8(8))
def getPublicKey(self):
"""
@@ -358,6 +365,37 @@ class ProprietaryServerCertificate(CompositeType):
#reverse because bignum in little endian
return rsa.PublicKey(self.PublicKeyBlob.pubExp.value, self.PublicKeyBlob.modulus.value[::-1])
def computeSignatureHash(self):
"""
@summary: compute hash
"""
s = Stream()
s.writeType(UInt32Le(self.__class__._TYPE_))
s.writeType(self.dwSigAlgId)
s.writeType(self.dwKeyAlgId)
s.writeType(self.wPublicKeyBlobType)
s.writeType(self.wPublicKeyBlobLen)
s.writeType(self.PublicKeyBlob)
md5Digest = md5.new()
md5Digest.update(s.getvalue())
return md5Digest.digest() + "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01"
def sign(self):
"""
@summary: sign proprietary certificate
@see: http://msdn.microsoft.com/en-us/library/cc240778.aspx
"""
self.SignatureBlob.value = rsa.sign(self.computeSignatureHash()[::-1], rsa.PrivateKey(d = ProprietaryServerCertificate._TERMINAL_SERVICES_PRIVATE_EXPONENT_[::-1], n = ProprietaryServerCertificate._TERMINAL_SERVICES_MODULUS_[::-1]))[::-1]
def verify(self):
"""
@summary: verify certificate signature
"""
return rsa.verify(self.SignatureBlob.value[::-1], rsa.PublicKey(e = ProprietaryServerCertificate._TERMINAL_SERVICES_PUBLIC_EXPONENT_[::-1], n = ProprietaryServerCertificate._TERMINAL_SERVICES_MODULUS_[::-1]))[::-1] == self.computeSignatureHash()
class CertBlob(CompositeType):
"""
@summary: certificate blob, contain x509 data
@@ -390,12 +428,19 @@ class X509CertificateChain(CompositeType):
n, e = x509.extractRSAKey(x509.load(self.CertBlobArray[-1].abCert.value))
return rsa.PublicKey(e, n)
def verify(self):
"""
@todo: verify x509 signature
"""
return True
class RSAPublicKey(CompositeType):
"""
@see: http://msdn.microsoft.com/en-us/library/cc240520.aspx
"""
def __init__(self, readLen):
CompositeType.__init__(self, readLen = readLen)
#magic is RSA1(0x31415352)
self.magic = UInt32Le(0x31415352, constant = True)
self.keylen = UInt32Le(lambda:(sizeof(self.modulus) + sizeof(self.padding)))
self.bitlen = UInt32Le(lambda:((self.keylen.value - 8) * 8))

View File

@@ -492,7 +492,7 @@ class Server(MCSLayer):
self._serverSettings.SC_SECURITY.encryptionMethod.value = gcc.EncryptionMethod.ENCRYPTION_FLAG_128BIT
self._serverSettings.SC_SECURITY.encryptionLevel.value = gcc.EncryptionLevel.ENCRYPTION_LEVEL_HIGH
self._serverSettings.SC_SECURITY.serverRandom.value = rsa.random(256)
self._serverSettings.SC_SECURITY.serverCertificate.certData = self._presentation.getCertificate()
self._serverSettings.SC_SECURITY.serverCertificate = self._presentation.getCertificate()
self._serverSettings.SC_CORE.clientRequestedProtocol.value = self._transport._requestedProtocol
self.setNextState(self.recvConnectInitial)

View File

@@ -235,7 +235,7 @@ class Capability(CompositeType):
"""
Closure for capability factory
"""
for c in [GeneralCapability, BitmapCapability, OrderCapability, BitmapCacheCapability, PointerCapability, InputCapability, BrushCapability, GlyphCapability, OffscreenBitmapCacheCapability, VirtualChannelCapability, SoundCapability, ControlCapability, WindowActivationCapability, FontCapability, ColorCacheCapability, ShareCapability]:
for c in [GeneralCapability, BitmapCapability, OrderCapability, BitmapCacheCapability, PointerCapability, InputCapability, BrushCapability, GlyphCapability, OffscreenBitmapCacheCapability, VirtualChannelCapability, SoundCapability, ControlCapability, WindowActivationCapability, FontCapability, ColorCacheCapability, ShareCapability, MultiFragmentUpdate]:
if self.capabilitySetType.value == c._TYPE_ and (self.lengthCapability.value - 4) > 0:
return c(readLen = self.lengthCapability - 4)
log.debug("unknown Capability type : %s"%hex(self.capabilitySetType.value))
@@ -527,3 +527,16 @@ class ShareCapability(CompositeType):
CompositeType.__init__(self, readLen = readLen)
self.nodeId = UInt16Le()
self.pad2octets = UInt16Le()
class MultiFragmentUpdate(CompositeType):
"""
@summary: Use to advertise fast path max buffer to use
client -> server
server -> client
@see: http://msdn.microsoft.com/en-us/library/cc240649.aspx
"""
_TYPE_ = CapsType.CAPSETTYPE_MULTIFRAGMENTUPDATE
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
self.MaxRequestSize = UInt32Le(0xffffffff)

View File

@@ -100,7 +100,8 @@ class PDULayer(LayerAutomata, tpkt.IFastPathListener):
caps.CapsType.CAPSTYPE_GLYPHCACHE : caps.Capability(caps.GlyphCapability()),
caps.CapsType.CAPSTYPE_OFFSCREENCACHE : caps.Capability(caps.OffscreenBitmapCacheCapability()),
caps.CapsType.CAPSTYPE_VIRTUALCHANNEL : caps.Capability(caps.VirtualChannelCapability()),
caps.CapsType.CAPSTYPE_SOUND : caps.Capability(caps.SoundCapability())
caps.CapsType.CAPSTYPE_SOUND : caps.Capability(caps.SoundCapability()),
caps.CapsType.CAPSETTYPE_MULTIFRAGMENTUPDATE : caps.Capability(caps.MultiFragmentUpdate())
}
#share id between client and server
self._shareId = 0x103EA
@@ -410,7 +411,7 @@ class Server(PDULayer):
self._clientCapabilities[cap.capabilitySetType] = cap
#find use full flag
self._clientFastPathSupported = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
self._clientFastPathSupported = bool(self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & (caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED | caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED))
self.setNextState(self.recvClientSynchronizePDU)
@@ -524,7 +525,7 @@ class Server(PDULayer):
generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
inputCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_INPUT].capability
inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX
@@ -582,7 +583,6 @@ class Server(PDULayer):
fastPathUpdateDataPDU = data.FastPathBitmapUpdateDataPDU()
fastPathUpdateDataPDU.rectangles._array = bitmapDatas
self._fastPathSender.sendFastPath(0, data.FastPathUpdatePDU(fastPathUpdateDataPDU))
else:
#slow path case
updateDataPDU = data.BitmapUpdateDataPDU()

View File

@@ -96,40 +96,6 @@ class AfInet(object):
AF_INET = 0x00002
AF_INET6 = 0x0017
def terminalServicesSign(certificate):
"""
@summary: sign proprietary certificate
@param certificate: {gcc.ProprietaryServerCertificate}
@see: http://msdn.microsoft.com/en-us/library/cc240778.aspx
"""
modulus = "\x3d\x3a\x5e\xbd\x72\x43\x3e\xc9\x4d\xbb\xc1\x1e\x4a\xba\x5f\xcb\x3e\x88\x20\x87\xef\xf5\xc1\xe2\xd7\xb7\x6b\x9a\xf2\x52\x45\x95\xce\x63\x65\x6b\x58\x3a\xfe\xef\x7c\xe7\xbf\xfe\x3d\xf6\x5c\x7d\x6c\x5e\x06\x09\x1a\xf5\x61\xbb\x20\x93\x09\x5f\x05\x6d\xea\x87"
privateExponent = "\x87\xa7\x19\x32\xda\x11\x87\x55\x58\x00\x16\x16\x25\x65\x68\xf8\x24\x3e\xe6\xfa\xe9\x67\x49\x94\xcf\x92\xcc\x33\x99\xe8\x08\x60\x17\x9a\x12\x9f\x24\xdd\xb1\x24\x99\xc7\x3a\xb8\x0a\x7b\x0d\xdd\x35\x07\x79\x17\x0b\x51\x9b\xb3\xc7\x10\x01\x13\xe7\x3f\xf3\x5f"
publicExponent = "\x5b\x7b\x88\xc0"
publicKeyBlob = Stream()
publicKeyBlob.writeType(certificate.wPublicKeyBlobType)
publicKeyBlob.writeType(certificate.wPublicKeyBlobLen)
publicKeyBlob.writeType(certificate.PublicKeyBlob)
dwVersion = Stream()
dwVersion.writeType(UInt32Le(certificate.__class__._TYPE_))
dwSigAlgId = Stream()
dwSigAlgId.writeType(certificate.dwSigAlgId)
dwKeyAlgId = Stream()
dwKeyAlgId.writeType(certificate.dwKeyAlgId)
md5Digest = md5.new()
md5Digest.update(dwVersion.getvalue())
md5Digest.update(dwSigAlgId.getvalue())
md5Digest.update(dwKeyAlgId.getvalue())
md5Digest.update(publicKeyBlob.getvalue())
message = md5Digest.digest() + "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01"
return rsa.sign(message[::-1], rsa.PrivateKey(d = privateExponent[::-1], n = modulus[::-1]))
def saltedHash(inputData, salt, salt1, salt2):
"""
@summary: Generate particular signature from combination of sha1 and md5
@@ -400,7 +366,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
"""
#if update is needed
if self._nbDecryptedPacket == 4096:
log.info("update decrypt key")
log.debug("update decrypt key")
self._currentDecrytKey = updateKey( self._initialDecrytKey, self._currentDecrytKey,
self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey)
@@ -427,7 +393,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
@return: {Tuple} (signature, encryptedData)
"""
if self._nbEncryptedPacket == 4096:
log.info("update encrypt key")
log.debug("update encrypt key")
self._currentEncryptKey = updateKey( self._initialEncryptKey, self._currentEncryptKey,
self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey)
@@ -590,6 +556,9 @@ class Client(SecLayer):
self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey)
self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey)
#verify certificate
if not self.getGCCServerSettings().SC_SECURITY.serverCertificate.certData.verify():
log.warning("cannot verify server identity")
#send client random encrypted with
serverPublicKey = self.getGCCServerSettings().SC_SECURITY.serverCertificate.certData.getPublicKey()
message = ClientSecurityExchangePDU()
@@ -644,8 +613,8 @@ class Server(SecLayer):
certificate = gcc.ProprietaryServerCertificate()
certificate.PublicKeyBlob.modulus.value = rsa.int2bytes(self._rsaPublicKey.n)[::-1]
certificate.PublicKeyBlob.pubExp.value = self._rsaPublicKey.e
certificate.SignatureBlob.value = terminalServicesSign(certificate)[::-1] + "\x00" * 8
return certificate
certificate.sign()
return gcc.ServerCertificate(certificate)
def recvClientRandom(self, s):
"""

View File

@@ -132,7 +132,7 @@ class X224Layer(LayerAutomata, IStreamSender):
"""
LayerAutomata.__init__(self, presentation)
#client requested selectedProtocol
self._requestedProtocol = Protocols.PROTOCOL_RDP
self._requestedProtocol = Protocols.PROTOCOL_SSL
#server selected selectedProtocol
self._selectedProtocol = Protocols.PROTOCOL_SSL
@@ -258,7 +258,7 @@ class Server(X224Layer):
#match best security layer available
if not self._serverPrivateKeyFileName is None and not self._serverCertificateFileName is None:
self._selectedProtocol = self._requestedProtocol & Protocols.PROTOCOL_RDP
self._selectedProtocol = self._requestedProtocol & Protocols.PROTOCOL_SSL
else:
self._selectedProtocol = self._requestedProtocol & Protocols.PROTOCOL_RDP

View File

@@ -52,11 +52,11 @@ def PrivateKey(d, n):
n = rsa.transform.bytes2int(n)
return { 'd' : d, 'n' : n }
def int2bytes(i):
def int2bytes(i, fill_size=None):
"""
@summary: wrapper of rsa.transform.int2bytes
"""
return rsa.transform.int2bytes(i)
return rsa.transform.int2bytes(i,fill_size)
def random(size):
"""
@@ -71,7 +71,7 @@ def encrypt(message, publicKey):
@param message: {str} source message
@param publicKey: {rsa.PublicKey}
"""
return rsa.transform.int2bytes(rsa.core.encrypt_int(rsa.transform.bytes2int(message), publicKey['e'], publicKey['n']))
return rsa.transform.int2bytes(rsa.core.encrypt_int(rsa.transform.bytes2int(message), publicKey['e'], publicKey['n']), rsa.common.byte_size(publicKey['n']))
def decrypt(message, privateKey):
"""
@@ -87,4 +87,12 @@ def sign(message, privateKey):
@param message: {str} message to sign
@param privateKey : {rsa.privateKey} key use to sugn
"""
return rsa.transform.int2bytes(rsa.core.encrypt_int(rsa.transform.bytes2int(message), privateKey['d'], privateKey['n']))
return rsa.transform.int2bytes(rsa.core.encrypt_int(rsa.transform.bytes2int(message), privateKey['d'], privateKey['n']), rsa.common.byte_size(privateKey['n']))
def verify(message, publicKey):
"""
@summary: return hash
@param message: {str} message to verify
@param publicKey : {rsa.publicKey} key use to sugn
"""
return rsa.transform.int2bytes(rsa.core.decrypt_int(rsa.transform.bytes2int(message), publicKey['e'], publicKey['n']))