0

Would anyone know why a Windows Update server (ie: download.windowsupdate.com) would give what looks like a bogus reply on certain networks? Taking the example of a patch for MSE I get the following header using a 4G mobile network (Vodafone). I've chopped the response down a bit for brevity.

curl -I "http://download.windowsupdate.com/d/msdownload/update/software/defu/2021/05/am_delta_6a3649beb57cee48081bd31631c8774de6505d2f.exe"

HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 8995
Content-Type: application/octet-stream
Date: Fri, 14 May 2021 13:59:10 GMT
Server: ECAcc (lha/8DA7)
Content-Length: 0
Connection: keep-alive

Note the invalid Content-Length, especially in tandem with keep-alive. This does not happen on our main network, which is supplied by UPC/Virgin Media. The Content-Length is a valid number on that network.

There is content (a several megabyte .exe file) and curl can deal with it just fine - I guess it checks to see if a read() comes back with more bytes and ignored Content-Length if it does. Good for curl.

However older versions of BITS do not seem to be able to deal with this nicely. Using a Windows 7 Pro in a VM, BITS starts running in a loop - it write to C:\ProgramData\Microsoft\Network\Downloader\qmgr0.dat over and over until I do a "net stop bits". This uses 100% disk and is effectively a DOS against Windows 7.

I know that Windows 7 is out of support but I saw this issue originally with Windows Server 2016. I will admit right now that this may already be a known bug and may already have been patched but I'm not sure how to find out (other than testing on an appropriate machine, when I get access. This is a Covid 19 related difficulty!)

As far as I know, BITS was rewritten for Windows 10 so it may not have the same issue. It's an interesting one though!

carveone
  • 101
  • 1
  • 1
    interesting. does it happen when you use HTTPS? is it only limited to `HEAD` verb? [RFC7230](https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2) says web server *may* send `Content-Length` in response to `HEAD` requests, probably a proxy sees a response without `Content-Length` and append its own (0 because, well, `HEAD`)? – mforsetti May 14 '21 at 17:25
  • @mforsetti Ack! You totally got me - I should have known this! Yes, you are absolutely correct. Using `curl --verbose -o filename` to download and see the header at the same time, the header output changes compared to that of just the HEAD request. Using the 4G network, the Content-Length changes to the correct value. I wonder what's going on with BITS under Windows 7 though. Might be worth investigating that one. Thanks! – carveone May 14 '21 at 20:48
  • Now that I read the RFC link you sent (thanks for that), it also says that "a server MUST NOT send Content-Length in such a response unless its field-value equals the decimal number of octets that would have been sent in the payload body of a response if the same request had used the GET method". So maybe it's still doing it wrong but your comment points to the reason why it is wrong! A proxy is appending something to the response. I'd love to phone the service provider and ask :-) – carveone May 14 '21 at 20:57
  • BITS [do use `HEAD`](https://docs.microsoft.com/de-de/security-updates/windowsupdateservices/18127392#proxy-servers-must-support-http-11-range-requests) requests and there's also `BG_E_MISSING_FILE_SIZE`, so that bad `Content-Length` is probably the case. Have you tried that `HEAD` request using HTTPS? Wonder if we can bypass ISP modifications with that. – mforsetti May 15 '21 at 07:03
  • Thanks. I tried with https but there's no https service available, probably because the IP address changes between many servers. I tried using bitsadmin manually and that succeeds in downloading a 0 byte file. I think I'll try logging a bug with Microsoft and see where that gets me! – carveone May 15 '21 at 16:23

1 Answers1

0

This appears to be a valid DOS type bug against Windows Update on versions of Windows prior to Windows 10. Reported to MSRC but report was closed so I don't see why I can't disclose. For those interested, report is duplicated at: https://github.com/conoror/wudos

I can reproduce this easily (Win7 ESU June 2021) with mitmproxy configured as a transparent proxy and a Python addon that messes with the HEAD response:

from mitmproxy import ctx

class ZeroContentLength:
    def response(self, flow):
        if "msdownload" in flow.request.pretty_url and \
                flow.request.method == "HEAD" and\
                "Content-Length" in flow.response.headers:
            ctx.log.info("Msdownload HEAD of len %s seen and set to 0" %
                            flow.response.headers["Content-Length"])
            flow.response.headers["Content-Length"] = '0'

addons = [
    ZeroContentLength()
]

In the event, it likely isn't trivial to position yourself as a transparent proxy so it's probably not significant. I switched provider to solve the issue.

carveone
  • 101
  • 1