Open khast3x opened 3 years ago
This would be really helpful as I'm also looking to using this in an Ubuntu honeypot running xrdp.
Hey @michelbf @khast3x, have either of you figured out a way around this? I am running into it as well.
I, unfortunately, don't have a solution for this.
Same ^
Also wrestling with this error; can't say I have a solution but maybe someone who knows more about xRDP can shed some light on what I've found so far:
On page 91 of Microsoft's RDP spec, they lay out the structure for CapabilitySets. As you can see, there is no corresponding type for a value of 6. The structure is mirrored in PyRDP here - https://github.com/GoSecure/pyrdp/blob/933ca2aac09f0b993c5937eb346c61c2052c4d94/pyrdp/enum/rdp.py#L409
It appears from the above stack trace that xRDP has sent a CapabilitySetType of 6, which does not exist. I'm trying to track down where and why this is set in the xRDP source- my best guess so far is here on line 87- https://github.com/neutrinolabs/xrdp/blob/devel/libxrdp/xrdp_caps.c ...but I don't know squat about xRDP. If I have time to read and understand more of the code that sets the CapabilitySetType, I'll make some changes and try building from source, and see what happens, or if there's any further useful errors.
You could just add an entry in the enum in pyrdp and test. Something like:
CAPSTYPE_BOGUS_XRDP = 0x0006
and see if everything starts working from there or if something fails
I made that change and am now digging into this error:
[2021-10-15 18:46:51,772] - ERROR - Ted978785 - pyrdp.mitm.connections.tcp - <CapabilityType.CAPSTYPE_VIRTUALCHANNEL: 20>
Traceback (most recent call last):
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/tcp.py", line 92, in dataReceived
self.recv(data)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 145, in recv
self.pduReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 203, in pduReceived
self.next.recv(pdu.payload)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/segmentation.py", line 79, in recv
layer.recv(forwarded)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/buffered.py", line 55, in recv
self.pduReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 203, in pduReceived
self.next.recv(pdu.payload)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 145, in recv
self.pduReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 203, in pduReceived
self.next.recv(pdu.payload)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 145, in recv
self.pduReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 110, in pduReceived
self.observer.onPDUReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/core/observer.py", line 82, in __call__
self.composite.doCall(self.item, args, kwargs)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/core/observer.py", line 56, in doCall
getattr(observer, item)(*args, **kwargs)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 48, in onPDUReceived
self.handlers[pdu.header](pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/mitm/MCSMITM.py", line 259, in onSendDataIndication
self.serverChannels[pdu.channelID].recv(pdu.payload)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/mcs/channel.py", line 33, in recv
self.next.recv(data)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/rdp/security.py", line 142, in recv
self.next.recv(data)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 145, in recv
self.pduReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/layer.py", line 110, in pduReceived
self.observer.onPDUReceived(pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/core/observer.py", line 82, in __call__
self.composite.doCall(self.item, args, kwargs)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/core/observer.py", line 56, in doCall
getattr(observer, item)(*args, **kwargs)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/mitm/SlowPathMITM.py", line 56, in onServerPDUReceived
SlowPathObserver.onPDUReceived(self.serverObserver, pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/layer/rdp/slowpath.py", line 49, in onPDUReceived
self.handlers[pdu.header.pduType](pdu)
File "/opt/venv/lib/python3.8/site-packages/pyrdp-1.1.1.dev0-py3.8-linux-x86_64.egg/pyrdp/mitm/SlowPathMITM.py", line 112, in onDemandActive
pdu.parsedCapabilitySets[CapabilityType.CAPSTYPE_VIRTUALCHANNEL].flags = \
KeyError: <CapabilityType.CAPSTYPE_VIRTUALCHANNEL: 20>
I don't understand why but there is no VirtualChannel setup at this point in the connection yet PyRDP assumes there is. Apply this patch. It will test if there's a virtualchannel before trying to disable its compression.
diff --git a/pyrdp/mitm/SlowPathMITM.py b/pyrdp/mitm/SlowPathMITM.py
index 0bff4aa..f4e1dd5 100644
--- a/pyrdp/mitm/SlowPathMITM.py
+++ b/pyrdp/mitm/SlowPathMITM.py
@@ -109,5 +109,6 @@ class SlowPathMITM(BasePathMITM):
supported[Order.TS_NEG_DRAWNINEGRID_INDEX] = 0
orders.orderSupport = supported
- pdu.parsedCapabilitySets[CapabilityType.CAPSTYPE_VIRTUALCHANNEL].flags = \
- VirtualChannelCompressionFlag.VCCAPS_NO_COMPR
+ if CapabilityType.CAPSTYPE_VIRTUALCHANNEL in pdu.parsedCapabilitySets:
+ pdu.parsedCapabilitySets[CapabilityType.CAPSTYPE_VIRTUALCHANNEL].flags = \
+ VirtualChannelCompressionFlag.VCCAPS_NO_COMPR
Did the patch get you further? Should I add this to PyRDP?
hey, sorry for not following up sooner, that was very helpful! Yes, the patch worked to resolve that, although we ran into some separate issues with our virtualization that prevented us from confirming full functionality afterwards. I think adding the patch would be great; it would be really helpful to be able to deploy it in docker without having to manually overwrite the source.
Added the patch to master. It will be part of the next release. Leaving this issue open since we are not sure about resolution.
In addition to the two already mentioned patches (this and this, where currently only the latter is merged/released), I also had to change 0x2a
to len(pdu.payload) + 14)
in parser/gcc.py#L132. It seems that XRDP would otherwise ignore the requested channels and return 0 channels, resulting in an error on the client side.
After the changes, a simple pyrdp MITM seems to work (on Linux with XRDP server and Remmina client or FreeRDP client), even though the client shows the following messages (which don't occur when connecting directly to XRDP instead of MITM server):
[...] [ERROR][com.freerdp.core.rdp] - incorrect PDU type: 0x0000
[...] [WARN][com.freerdp.core.rdp] - pduType UNKNOWN 0000 not properly parsed, 122 bytes remaining unhandled. Skipping.
I'm not sure what this might break. Also, I'm not sure whether my patch breaks support for other servers, e.g. on Windows. Could someone check that? I currently only have Linux with XRDP.
Hello,
Does PyRDP support using the mitm feature in front of a xrdp server? If not, this could help deploy honeypots with a small alpine/ubuntu container acting as RDP backend. This is the current output when running as a mitm for a ubuntu+xrdp container (it is a bit verbose, sorry):
Cheers!