[issue36021] [Security][Windows] webbrowser: WindowsDefault uses os.startfile() and so can be abused to run arbitrary commands

Eryk Sun report at bugs.python.org
Wed Feb 20 10:14:07 EST 2019


Eryk Sun <eryksun at gmail.com> added the comment:

> Windows has the GetBinaryTypeW function

ShellExecute[Ex] doesn't check for a PE image. It uses the file extension, and a tangled web of registry settings to determine what to execute. If a file should run directly via CreateProcess, you'll find the template command starts with the target file ("%1" or "%L"). For example:

    >>> AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_COMMAND,
    ...     '.exe', 'open', command, n)
    0
    >>> print(command.value)
    "%1" %*

OTOH, a script requires an interpreter, e.g for .py files:

    >>> AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_COMMAND,
    ...     '.py', 'open', command, n)
    0
    >>> print(command.value)
    "C:\WINDOWS\py.exe" "%L" %*

Except .bat and .cmd scripts are executed directly via the %ComSpec% interpreter:

    >>> AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_COMMAND,
    ...     '.bat', 'open', command, n)
    0
    >>> print(command.value)
    "%1" %*

One bit of metadata we can check is the file's "PerceivedType": unknown=0, text, image, audio, video, compressed, document, system, application, game-media, contacts. If a file's type is unknown (0), system (7), or application (8), or if getting the type fails, we probably don't want to run it. For example:

    >>> _ = AssocGetPerceivedType(".txt", ptype, flags, None); print(ptype[0])
    1
    >>> _ = AssocGetPerceivedType(".jpg", ptype, flags, None); print(ptype[0])
    2
    >>> _ = AssocGetPerceivedType(".mp3", ptype, flags, None); print(ptype[0])
    3
    >>> _ = AssocGetPerceivedType(".mp4", ptype, flags, None); print(ptype[0])
    4
    >>> _ = AssocGetPerceivedType(".zip", ptype, flags, None); print(ptype[0])
    5
    >>> _ = AssocGetPerceivedType(".html", ptype, flags, None); print(ptype[0])
    6
    >>> _ = AssocGetPerceivedType(".sys", ptype, flags, None); print(ptype[0])
    7
    >>> _ = AssocGetPerceivedType(".exe", ptype, flags, None); print(ptype[0])
    8
    >>> _ = AssocGetPerceivedType(".com", ptype, flags, None); print(ptype[0])
    8
    >>> _ = AssocGetPerceivedType(".bat", ptype, flags, None); print(ptype[0])
    8
    >>> _ = AssocGetPerceivedType(".cmd", ptype, flags, None); print(ptype[0])
    8

Except for a small number of hard-code definitions, the PerceivedType has to be defined for a filetype, and it's optional. It gets set either in the file-extension key under [HKCU|HKLM]\Software\Classes, or in the SystemFileAssocations subkey, or probably in 10 other locations sprawled across the registry. Python's installer doesn't set the PerceivedType of .py files to the application type (8), but it should. 

Another bit of metadata is the MIME "Content Type". This is also optional information provided in a filetype definition. For example:

    >>> AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_CONTENTTYPE,
    ...     '.exe', 'open', mtype, n)
    0
    >>> print(mtype.value)
    application/x-msdownload

    >>> AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_CONTENTTYPE,
    ...     '.html', 'open', mtype, n)
    0
    >>> print(mtype.value)
    text/html

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue36021>
_______________________________________


More information about the Python-bugs-list mailing list