jborean93 / pypsrp

PowerShell Remoting Protocol for Python
MIT License
326 stars 49 forks source link

When a remote error occurs, wsman requests infinitely until it is closed #120

Open mu0gua opened 3 years ago

mu0gua commented 3 years ago

wsmanpy

### line: 415 
if b"http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" in response:
            f_messages = response.decode("utf-8")
            f_messages = f_messages.split("<f:Message>")[1].split("</f:Message>")[0]
            raise WinRMError("Received related id does not match related "
                             "expected message id: Sent: %s, Received: %s"
                             % (message_id, f_messages))

Rude solution

jborean93 commented 3 years ago

I'm sorry I don't understand the problem. The code you've given doesn't match up with anything in https://github.com/jborean93/pypsrp/blob/master/pypsrp/wsman.py and the error at the end occurs when the client receives a response for the wrong request. What exactly is the problem here?

mu0gua commented 3 years ago

Maybe the version is different, or the problem I described, the line : 398

......
    except ET.ParseError:
                # no XML message is present so not a WSManFault error
                log.error("Failed to parse WSManFault message on WinRM error"
                          " response, raising original WinRMTransportError")
                raise err

        print(response.decode("utf-8"))

        response_xml = ET.fromstring(response)
        relates_to = response_xml.find("s:Header/wsa:RelatesTo",
                                       namespaces=NAMESPACES).text
        # add new code
        if b"http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" in response:
            f_messages = response.decode("utf-8")
            f_messages = f_messages.split("<f:Message>")[1].split("</f:Message>")[0]
            raise WinRMError("Received related id does not match related "
                             "expected message id: Sent: %s, Received: %s"
                             % (message_id, f_messages))

        if message_id != relates_to:
            raise WinRMError("Received related id does not match related "
                             "expected message id: Sent: %s, Received: %s"
                             % (message_id, relates_to))

        return response_xml
.......

cause:

I received a package like this

<s:Envelope xml:lang="zh-CN" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:x="http://schemas.xmlsoap.org/ws/2004/09/transfer" xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:w="http://schemas.**************/wbem/wsman/1/wsman.xsd" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd">
<s:Header>
<a:Action>http://schemas.**************/wbem/wsman/1/wsman/fault</a:Action>
<a:MessageID>uuid:33F8EE19-AD58-416B-8DCC-F6C20AB88992</a:MessageID>
<a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
<a:RelatesTo>uuid:4F4CBEBE-3C00-45B9-A211-A9E1174580A7</a:RelatesTo>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value>w:InvalidSelectors</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="zh-CN">WS-Management 服务无法处理该请求,因为请求包含对资源无效的选择器。 </s:Text>
</s:Reason>
<s:Detail>
<w:FaultDetail>http://schemas.**************/wbem/wsman/1/wsman/faultDetail/UnexpectedSelectors</w:FaultDetail>
<f:WSManFault xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2150858843" Machine="127.0.0.1">
<f:Message>ShellId 为 4D7B2AAC-6369-4500-8B59-5DAB633D77FB 的 Windows 远程 Shell 的请求失败,因为在服务器上找不到该 Shell。可能的原因是: 指定的 ShellId 不正确,或该 Shell 不在该服务器上。请提供正确的 ShellId 或创建新的 Shell,然后重试该操作。 </f:Message>
</f:WSManFault>
</s:Detail>
</s:Fault>
</s:Body>
</s:Envelope>

message_id and relatives_to are always equal, so he will not stop because of “raise” (raise WinRMError.......) But in fact he should stop, because the server has already reported the execution result Therefore, I have adopted the above solution, which is probably wrong.

This project references your project, the address is: https://github.com/dmaasland/proxyshell-poc

There is no need to merge the request, it is only my temporary solution, providing a description of the problem, just hoping that the project can have more test scenarios

Forgive my poor English, it comes from Google Translate

thank you for your reply

jborean93 commented 3 years ago

Ahh I see what you mean now, the code you've shared is what you've added to ensure the failure. I was assuming that this was existing code that was causing problems for you but I understand now.

As for the problem in question, the error is usually picked up in as part of this check https://github.com/jborean93/pypsrp/blob/e4e5130d10baff683edfc51a4c5c42301787e067/pypsrp/wsman.py#L382-L392. A WSMan fault is usually returned with a status code of 500 from the server which raises the WinRMTransportError in the transport. From there the code is attempting to parse the WSManFault error with self._parse_wsman_fault(err.response_text) to give a better structured error message. It sounds like the proxy shell is not returning the fault with a HTTP status code of 500 to pick up this problem. In any case I would have thought that processing the message further down would raise an exception anyway.

Ultimately it wouldn't hurt to try and parse the WSManFault anyway at this stage even if the HTTP status code was 200.