Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Bugs, Faults, Quirks and Vulnerabilities in the Command Shell of Windows NT

Purpose
Reference
Fault № 0
Demonstration
Fault № 1
Demonstration
Background Information
Remediation
Fault № 2
Demonstration
Security Impact
Fault № 3
Demonstration
Fault № 4
Demonstration
Fault № 5
Falsification
Fault № 6
Demonstration
Fault № 7
Falsification
Fault № 8
Demonstration
Fault № 9
Demonstration
Work-Around
Fault № 10
Falsification
Fault № 11
Demonstration
Security Impact
Work-Around
Fault № 12
Demonstration
Fault № 13
Falsification
Fault № 14
Falsification
Fault № 15
Demonstration
Fault № 16
Demonstration
Fault № 17
Falsification
Fault № 18
Falsification
Security Impact
MSRC Case 59749
Remediation

Purpose

Reference

Windows Commands, 4/13/2018, https://download.microsoft.com/download/5/8/9/58911986-D4AD-4695-BF63-F734CD4DF8F2/ws-commands.pdf

Fault № 0

The documentation for the Command Processor Cmd.exe states:
Parameter Description
/a Formats internal command output to a pipe or a file as American National Standards Institute (ANSI).
/u Formats internal command output to a pipe or a file as Unicode.
Unicode here means of course Windows NT’s native UTF-16LE encoding.

Demonstration

Perform the following 3 simple steps to show the undocumented misbehaviour of the Command Processor Cmd.exe.
  1. Start the Command Processor Cmd.exe, then execute the following command lines:

    CHDIR /D "%PUBLIC%"
    1>comspec.bat "%COMSPEC%" /U /D /C ECHO PAUSE
    DIR comspec.bat
    TYPE comspec.bat
    CALL .\comspec.bat
    Note: the command lines can be copied and pasted as block into a Command Processor window.
     Volume in drive C has no label.
     Volume Serial Number is 1957-0427
    
     Directory of C:\Users\Public
    
    04/27/2018  08:15 PM                14 comspec.bat
                   1 File(s)             14 bytes
                   0 Dir(s)    9,876,543,210 bytes free
    
      A U S E 
    
    
    'P' is not recognized as an internal or external command,
    operable program or batch file.
    The text file comspec.bat contains 14 bytes in 7 UTF-16LE code units, the string PAUSE plus a CR/LF pair – contrary to Microsoft’s own recommendation the Command Processor writes no Byte Order Mark!

    OUCH¹: the internal Type command fails to display UTF-16LE encoded files without Byte Order Mark properly!

    OUCH²: (the internal Call command of) the Command Processor fails to execute batch scripts in Windows NT’s native UTF-16LE encoding!

  2. Open the batch script comspec.bat with NotePad.exe, press the Ctrl S keyboard shortcut to save it unchanged and exit the text editor:

    NOTEPAD.EXE comspec.bat
  3. Repeat the last 3 commands from step 1.:

    DIR comspec.bat
    TYPE comspec.bat
    CALL .\comspec.bat
     Volume in drive C has no label.
     Volume Serial Number is 1957-0427
    
     Directory of C:\Users\Public
    
    04/27/2018  08:15 PM                16 comspec.bat
                   1 File(s)             16 bytes
                   0 Dir(s)    9,876,543,210 bytes free
    
    PAUSE
    
    '■P' is not recognized as an internal or external command,
    operable program or batch file.
    Note: NotePad.exe silently added a Byte Order Mark, the batch script comspec.bat now contains 16 bytes in 8 UTF-16LE code units.

    OUCH³: while the internal Type command displays the file comspec.bat properly now, (the internal Call command of) the Command Processor still fails to execute it!

Fault № 1

The documentation for the Command Processor Cmd.exe states:
Parameter Description
/d Disables execution of AutoRun commands.

[…]

Note: this feature enables (unprivileged) users to tamper with Logon scripts configured by their (privileged) administrators who are unaware of the pitfalls demonstrated below!

Demonstration

Perform the following 3 simple steps to show that AutoRun commands are executed whenever a batch script is started with one of the Win32 functions ShellExecute(). ShellExecuteEx() or WinExec(), for example from Windows graphical shell Explorer.exe per double-click or the Run entry of its Start Menu:
  1. Create the text file comspec.bat with the following content in an arbitrary, preferable empty directory:

    @REM Copyleft © 1997-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    @SET /P =%CMDCMDLINE%
    @EXIT /B
  2. Execute the batch script comspec.bat created in step 1. per double-click:

    C:\Windows\system32\cmd.exe /c ""C:\Users\Stefan\Desktop\comspec.bat" "
    Oops: Explorer.exe fails to provide the parameter /d to disable the execution of AutoRun commands when starting batch scripts!
  3. Display the file types associated with the extensions .bat and .cmd and their command line templates:

    ASSOC .bat
    FTYPE batfile
    ASSOC .cmd
    FTYPE cmdfile
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    .bat=batfile
    batfile="%1" %*
    .cmd=cmdfile
    cmdfile="%1" %*

Background Information

The Win32 functions ShellExecute() and ShellExecuteEx() retrieve these command line templates, replace the various tokens %‹digit›, %‹letter› and %* with file or path names and arguments, then feed the completed command line to one of the CreateProcess(), CreateProcessAsUser(), CreateProcessWithLogonW() or CreateProcessWithTokenW() functions.

The documentation for the CreateProcess() function states:

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.
Due to the security vulnerability CVE-2014-0315 alias MS14-019 I discovered and reported at the MSRC about 11 years ago, which was fixed with security update 2922229 some months later, the following note was added several years later:

Important

The MSRC engineering team advises against this. See MS14-019 – Fixing a binary hijacking via .cmd or .bat file for more details.

Remediation

To prevent the execution of AutoRun commands when starting batch scripts, change the command line template registered with the file types alias Programmatic Identifiers batfile and cmdfile associated with the extensions .bat and .cmd from its default value "%1" %* to C:\Windows\System32\Cmd.exe /D /C "%1" %*:
FTYPE batfile=%COMSPEC% /D /C "%1" %*
FTYPE cmdfile=%COMSPEC% /D /C "%1" %*
Note: the internal Ftype command must be executed with administrative access rights.

If you still have not abandonded the bad habit of using the Protected Administrator account created during Windows Setup you also need to change the command line templates registered for the RunAs verb:

REGEDIT4

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\batfile\Shell\Open\Command]
@="C:\\Windows\\System32\\Cmd.exe /D /C \"%L\" %*"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\batfile\Shell\RunAs\Command]
@="C:\\Windows\\System32\\Cmd.exe /D /C \"%L\" %*"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\cmdfile\Shell\Open\Command]
@="C:\\Windows\\System32\\Cmd.exe /D /C \"%L\" %*"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\cmdfile\Shell\RunAs\Command]
@="C:\\Windows\\System32\\Cmd.exe /D /C \"%L\" %*"
CAVEAT: thanks to the Merged View of HKEY_CLASSES_ROOT introduced with Windows 2000 this remediation but fails if the unnamed default registry entry with the default command line template is present in the corresponding registry key HKEY_CURRENT_USER\Software\Classes\‹file type›\Shell\‹verb›\Command of a user account!

Fault № 2

The TechNet article The Windows NT Command Shell tells:
When the command shell processes a pipe (|) symbol, it actually runs both commands specified simultaneously.
Note: internal commands except Rem with an argument other than /?, i.e. Assoc, Break, Call, Cd, Chdir, Cls, Color, Copy, Date, Del, Dir, Dpath (undocumented), Echo, Endlocal, Erase, Exit, For, Ftype, Goto, If, Keys (undocumented), Md, Mkdir, Mklink, Move, Path, Pause, Popd, Prompt, Pushd, Rd, Ren, Rename, Rmdir, Set, Setlocal, Shift, Start, Time, Title, Type, Ver, Verify and Vol, are executed in a child Cmd.exe process!

The TechNet article Using command redirection operators states too:

Using the pipe operator (|)

The pipe operator (|) takes the output (by default, STDOUT) of one command and directs it into the input (by default, STDIN) of another command. For example, the following command sorts a directory:

dir | sort

In this example, both commands start simultaneously, but then the sort command pauses until it receives the dir command's output. The sort command uses the dir command's output as its input, and then sends its output to handle 1 (that is, STDOUT).

The documentation for the internal Rem command of the Command Processor states:

Demonstration

Perform the following 6 (plus 1 optional) simple steps to show undocumented (mis)behaviour and a more than 31 (in words: thirty-one) year old bug that crashes the Command Processor.
  1. Start the Command Processor, then run the following command lines to show proper but undocumented behaviour:

    ECHO %CMDCMDLINE^% | MORE.COM
    1>&2 ECHO %CMDCMDLINE^% | ECHO %CMDCMDLINE^%
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    C:\windows\system32\cmd.exe  /S /D /c" ECHO %CMDCMDLINE% "
    C:\windows\system32\cmd.exe  /S /D /c" ECHO %CMDCMDLINE% 1>&2"
    C:\windows\system32\cmd.exe  /S /D /c" ECHO %CMDCMDLINE%"
    Note: the Command Processor executes each internal command of these pipelines in a separate child Cmd.exe process – fortunately with the parameter /D to disable the execution of AutoRun commands!
  2. Execute the following command lines to show more proper behaviour:

    1>&2 ECHO %CMDCMDLINE^% | REM
    ECHO %CMDCMDLINE^% | REM
    ECHO %CMDCMDLINE^% | REM /?
    C:\Windows\system32\cmd.exe  /S /D /c" ECHO %CMDCMDLINE% 1>&2"
    The process tried to write to a nonexistent pipe.
    Records comments (remarks) in a batch file or CONFIG.SYS.
    
    REM [comment]
    Note: on the right hand side of a pipeline output redirection works with the internal Rem command.
  3. Execute the following command lines to show undocumented behaviour:

    REM /? | ECHO %CMDCMDLINE^%
    REM | ECHO 1>&2 %CMDCMDLINE^%
    C:\Windows\system32\cmd.exe  /S /D /c" ECHO %CMDCMDLINE%"
    Note: redirection characters can’t be used with the internal Rem command and an argument other than /? outside of batch scripts too – REM | … is not recognised as a pipeline.
  4. Execute the following command lines to show the first undocumented misbehaviour:

    SET COMSPEC=%SystemRoot%\System32\Reg.exe
    DPATH | KEYS
    SET COMSPEC=.
    BREAK | EXIT
    SET COMSPEC=NUL:
    ECHO | REM
    Note: the Registry Console Tool Reg.exe is only (ab)used as canary here.
    ERROR: Invalid Argument/Option - '/S'.
    Type "REG /?" for usage.
    ERROR: Invalid Argument/Option - '/S'.
    Type "REG /?" for usage.
    '.' is not recognized as an internal or external command,
    operable program or batch file.
    'NUL:' is not recognized as an internal or external command,
    operable program or batch file.
    OUCH¹: the Command Processor evaluates the (user-controlled) environment variable COMSPEC and tries to execute the file, directory or device it points to as child process of itself!

    CAVEAT: (ab)using an environment variable to locate an executable file is a well-known weakness, documented as CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') and CWE-73: External Control of File Name or Path in the CWE; it allows well-known attacks like CAPEC-13: Subverting Environment Variable Values documented in the CAPEC.

    Note: properly implemented, the Command Processor would fetch its own path name with the Win32 function GetModuleFileName() instead to (ab)use the value of a user-controlled environment variable!

  5. Execute the following command lines to show the second undocumented misbehaviour:

    SET COMSPEC=%RANDOM%
    SET PATHEXT
    DPATH | KEYS
    SET PATHEXT=NUL:
    BREAK | EXIT
    SET PATHEXT=%SystemRoot%\System32\Reg.exe
    ECHO | REM
    SET PATHEXT=
    SHIFT | VER
    PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    '.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC' is not recognized as an internal or external command,
    operable program or batch file.
    'NUL:' is not recognized as an internal or external command,
    operable program or batch file.
    'C:\Windows\System32\Reg.exe' is not recognized as an internal or external command,
    operable program or batch file.
    '' is not recognized as an internal or external command,
    operable program or batch file.
    OUCH²: if the environment variable COMSPEC points to a non-existent path, the Command Processor tries to execute the file, directory or device the (user-controlled) environment variable PATHEXT points to as child process of itself, even if this environment variable is missing – and fails always, independent of its value!
  6. Finally execute the following command lines to show the bug:

    SET COMSPEC=
    DPATH | KEYS
    OUCH³: the Command Processor crashes with an access violation exception 0xC0000005 reading address NULL when an arbitrary internal command is executed in a pipeline while the environment variable COMSPEC is missing!

    Note: the crash induced by the absence of the environment variable COMSPEC is yet another well-known weakness, documented as CWE-248: Uncaught Exception and CWE-476: NULL Pointer Dereference in the CWE.

  7. (Optional) If you have the Debugging Tools for Windows installed, execute the Command Processor under the debugger:

    CDB.EXE /C g;q /G /g "%COMSPEC%" /D /C SET COMSPEC=^& EXIT ^| EXIT
    Note: if necessary, see the MSDN articles Debugging Using CDB and NTSD and CDB Command-Line Options for an introduction.
    Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    CommandLine: "C:\Windows\system32\cmd.exe" /D /C SET COMSPEC=& EXIT | EXIT
    Symbol search path is: srv*
    Executable search path is: 
    ModLoad: 4ac70000 4acbc000   cmd.exe
    ModLoad: 779c0000 77b40000   ntdll.dll
    ModLoad: 75610000 75720000   C:\Windows\syswow64\kernel32.dll
    ModLoad: 752d0000 75317000   C:\Windows\syswow64\KERNELBASE.dll
    ModLoad: 75540000 755e1000   C:\Windows\syswow64\ADVAPI32.DLL
    ModLoad: 757a0000 7584c000   C:\Windows\syswow64\msvcrt.dll
    ModLoad: 77420000 77439000   C:\Windows\SysWOW64\sechost.dll
    ModLoad: 77300000 773f0000   C:\Windows\syswow64\RPCRT4.dll
    ModLoad: 750e0000 75140000   C:\Windows\syswow64\SspiCli.dll
    ModLoad: 750d0000 750dc000   C:\Windows\syswow64\CRYPTBASE.dll
    ModLoad: 73d60000 73d67000   C:\Windows\SysWOW64\WINBRAND.dll
    ModLoad: 76f60000 77060000   C:\Windows\syswow64\USER32.dll
    ModLoad: 764f0000 76580000   C:\Windows\syswow64\GDI32.dll
    ModLoad: 76580000 7658a000   C:\Windows\syswow64\LPK.dll
    ModLoad: 76690000 7672d000   C:\Windows\syswow64\USP10.dll
    ModLoad: 76630000 76690000   C:\Windows\SysWOW64\IMM32.DLL
    ModLoad: 75470000 7553e000   C:\Windows\syswow64\MSCTF.dll
    (2f60.32bc): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=00000000 ebx=00002000 ecx=00551210 edx=00000002 esi=005511a8 edi=005511a8
    eip=4ac7247d esp=002dfa00 ebp=002dfa0c iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
    *** ERROR: Module load completed but symbols could not be loaded for cmd.exe
    cmd+0x247d:
    4ac7247d 668b08          mov     cx,word ptr [eax]        ds:002b:00000000=????
    0:000:x86> cdb: Reading initial command 'g;q'
    (2f60.32bc): Access violation - code c0000005 (!!! second chance !!!)
    quit:

Security Impact

The (unintended) execution of a (bogus) application determined by the value of a (user-controlled) environment variable like COMSPEC is a well-known weakness, documented as CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') and CWE-73: External Control of File Name or Path in the CWE; it allows well-known attacks like CAPEC-13: Subverting Environment Variable Values documented in the CAPEC.

The crash induced by the absence of the (user-controlled) environment variable COMSPEC is yet another well-known weakness, documented as CWE-248: Uncaught Exception and CWE-476: NULL Pointer Dereference in the CWE.

This at least 31 year old bug (really: absolute beginner’s programming error) can trivially be (ab)used to conduct a denial of service attack against the Command Processor and crash it upon launch, thus disabling its use for single or all users of a machine:

REGEDIT4

[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"AutoRun"="SET COMSPEC=& EXIT | EXIT"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor]
"AutoRun"="SET COMSPEC=& EXIT | EXIT"

Fault № 3

Pairs of the characters % and ! are used for (delayed) expansion of environment variables at the (interactive) command prompt as well as in batch scripts – where the single % is used for parameter expansion.

Demonstration

Perform the following 2 simple steps to show a bug.
  1. Create the text file com!spec.bat with the following content in an arbitrary, preferable empty directory:

    REM Copyleft © 1997-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    SETLOCAL DISABLEDELAYEDEXPANSION
    CALL :com%spec
    SETLOCAL ENABLEDELAYEDEXPANSION
    :comspec
    DIR "%~f0"
    ECHO comspec%
    ECHO com%spec
    ECHO %comspec
    ECHO !%!
    ECHO comspec!
    %ECHO com!spec
    ECHO !comspec
    MKDIR !!
    ECHO% !
    RMDIR !!
    !PAUSE
    EXIT /B
    Note: the single exclamation mark (or a single percent sign) can be placed anywhere in the filename!
  2. Start the batch script com!spec.bat created in step 1. per double-click:

    REM Copyleft © 1997-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de>
    SETLOCAL DISABLEDELAYEDEXPANSION
    CALL :comspec
    DIR "C:\Users\Stefan\Desktop\com!spec.bat"
    
     Volume in drive C has no label.
     Volume Serial Number is 1957-0427
    
     Directory of C:\Users\Stefan\Desktop
    
    04/27/2018  08:15 PM               320 com!spec.bat
                   1 File(s)            320 bytes
                   0 Dir(s)    9,876,543,210 bytes free
    
    ECHO comspec
    comspec
    ECHO comspec
    comspec
    ECHO comspec
    comspec
    ECHO !!
    !!
    ECHO comspec!
    comspec!
    ECHO com!spec
    com!spec
    ECHO !comspec
    !comspec
    MKDIR !!
    ECHO !
    !
    RMDIR !!
    !PAUSE
    '!PAUSE' is not recognized as an internal or external command,
    operable program or batch file.
    EXIT /B
    SETLOCAL ENABLEDELAYEDEXPANSION
    DIR "C:\Users\Stefan\Desktop\com!spec.bat"
    
     Volume in drive C has no label.
     Volume Serial Number is 1957-0427
    
     Directory of C:\Users\Stefan\Desktop
    
    File Not Found
    
    ECHO comspec
    comspec
    ECHO comspec
    comspec
    ECHO comspec
    comspec
    ECHO !!
    ECHO is on.
    ECHO comspec!
    comspec
    ECHO com!spec
    comspec
    ECHO !comspec
    comspec
    MKDIR !!
    The syntax of the command is incorrect.
    ECHO !
    ECHO is on.
    RMDIR !!
    The syntax of the command is incorrect.
    !PAUSE
    Press any key to continue . . .
    EXIT /B
    OUCH¹: in batch scripts, the Command Processor strips single percent signs from the command line before it is echoed and executed!

    OUCH²: when delayed environment variable expansion is enabled in batch scripts, the Command Processor strips all exclamation marks which don’t surround the name of an environment variable from the command line after it is echoed and before it is executed!

Fault № 4

The TechNet article The Windows NT Command Shell states under the heading Command Search Sequence:
When a command is submitted for execution (either by typing or as part of a script), the shell performs the following actions:
  1. All parameter and environment variable references are resolved (see chapter 3).

  2. Compound commands are split into individual commands and each is then individually processed according to the following steps (see the section "Running Multiple Commands" for details of compound commands). Continuation lines are also processed at this step.

  3. The command is split into the command name and any arguments.

[…]
Note: unfortunately there’s no explicit statement when input and output redirection are processed.

Demonstration

  1. Create the text file comspec.bat with the following content in an arbitrary, preferable empty directory:

    @REM Copyleft © 1997-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    @SETLOCAL ENABLEDELAYEDEXPANSION
    @ECHO %%0 com %~0 spec
    @ECHO %%1 com %~1 spec
    @ECHO %%2 com %~2 spec
    @ECHO %%3 com %~3 spec
    @ECHO %%4 com %~4 spec
    @ECHO %%5 com %~5 spec
    @ECHO %%6 com %~6 spec
    @ECHO %%7 com %~7 spec
    @ECHO %%8 com %~8 spec
    @ECHO %%9 com %~9 spec
    @EXIT /B
  2. Start the Command Processor Cmd.exe, then execute the batch script comspec.bat created in step 1. via the following command line with 9 properly quoted arguments containing special characters:

    .\comspec.bat "!!" "&" "&&" "0<." "1>." "^" "^^" "|" "||"
    %0 com .\comspec.bat spec
    %1 com  spec
    %2 com
    'spec' is not recognized as an internal or external command,
    operable program or batch file.
    %3 com
    'spec' is not recognized as an internal or external command,
    operable program or batch file.
    Access denied
    Access denied
    %6 com  spec
    %7 com ^ spec
    'spec' is not recognized as an internal or external command,
    operable program or batch file.
    OOPS: input and output redirection are processed after parameter and environment variable expansion!

    OUCH¹: the Command Processor fails to execute the last ECHO command – its output %9 com is missing!

  3. Execute the batch script comspec.bat created in step 1. a second time with the same 9 arguments, now unquoted and their special characters properly escaped:

    .\comspec.bat ^!^! ^& ^&^& 0^<. 1^>. ^^ ^^^^ ^| ^|^|
    %0 com .\comspec.bat spec
    %1 com  spec
    %2 com
    'spec' is not recognized as an internal or external command,
    operable program or batch file.
    %3 com
    'spec' is not recognized as an internal or external command,
    operable program or batch file.
    Access denied
    Access denied
    %6 com  spec
    'spec' is not recognized as an internal or external command,
    operable program or batch file.
    OUCH²: now the eighth and tenth ECHO fail execution!

Fault № 5

The documentation for the internal Assoc command of the Command Processor states:
Displays or modifies file name extension associations. […]
assoc [<.ext>[=[<FileType>]]]

[…]

Remarks

Falsification

Perform the following 2 simple steps to prove the highlighted statement of the documentation cited above wrong and also show undocumented behaviour.
  1. Start the Command Processor Cmd.exe, then execute the following command lines to display some non-associations:

    ASSOC batfile
    ASSOC batfile\DefaultIcon
    ASSOC batfile\Shell\Open\Command
    ASSOC CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32
    batfile=Windows Batch File
    batfile\DefaultIcon=%SystemRoot%\System32\imageres.dll,-68
    batfile\Shell\Open\Command="%1" %*
    CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32=%ProgramFiles%\Windows Defender\MpOav.dll
    Oops¹: the internal Assoc command reads not just associations, but also the values of unnamed default registry entries in arbitrary registry keys of the HKEY_LOCAL_MACHINE\SOFTWARE\Classes registry branch.
  2. Start the Command Processor Cmd.exe with administrative access rights, then execute the following command lines to write, display and remove some non-associations, also prove the highlighted statement of the documentation cited above wrong:

    ASSOC CLSID
    ASSOC CLSID=%RANDOM%
    ASSOC CLSID
    ASSOC CLSID=
    ASSOC CLSID
    File association not found for extension CLSID
    CLSID=12345
    CLSID=12345
    File association not found for extension CLSID
    Oops²: the internal Assoc command reads and writes not just associations, but also the values of unnamed default registry entries in arbitrary registry keys in the HKEY_LOCAL_MACHINE\SOFTWARE\Classes registry branch.

    Oops³: contrary to the highlighted statement of the documentation cited above, the internal Assoc command requires no white space after the equal sign to remove a value!

Fault № 6

The documentations for the internal Call, Del alias Erase, Move, Ren alias Rename and Type commands of the Command Processor state:
Calls one batch program from another without stopping the parent batch program. […]
Deletes one or more files. This command is the same as the erase command.
Moves one or more files from one directory to another directory.
Renames files or directories. This command is the same as the rename command.
Displays the contents of a text file. Use the type command to view a text file without modifying it.

Demonstration

Perform the following 7 simple steps to show their braindead misbehaviour:
  1. Start the Command Processor Cmd.exe, then create the subdirectory comspec in the public TMP directory of the system and remove it, then create a file comspec there and (try to) erase it:

    MKDIR "%SystemRoot%\Temp\comspec"
    RMDIR "%SystemRoot%\Temp\comspec"
    COPY "%COMSPEC%" "%SystemRoot%\Temp\comspec"
    ERASE "%SystemRoot%\Temp\comspec"
    Note: the command lines can be copied and pasted as block into a Command Processor window.
            1 file(s) copied.
    The system cannot find the file C:\Windows\Temp\comspec.
    OOPS: WTF?
  2. Verify that the file %SystemRoot%\Temp\comspec created in step 1. really exists, then overwrite it and (try to) display its content, (try to) execute it, (try to) rename it and (try to) move it into your current (working) directory:

    MKDIR "%SystemRoot%\Temp\comspec"
    COPY /Y NUL: "%SystemRoot%\Temp\comspec"
    TYPE "%SystemRoot%\Temp\comspec"
    CALL "%SystemRoot%\Temp\comspec"
    RENAME "%SystemRoot%\Temp\comspec" COMSPEC
    MOVE "%SystemRoot%\Temp\comspec"
    A subdirectory or file C:\Windows\Temp\comspec already exists.
            1 file(s) copied.
    Access denied
    Access denied
    Access denied
    Access denied
    OUCH: the Command Processor seems to perform a (superfluous) access check on files!
  3. Display the access permissions of the file %SystemRoot%\Temp\comspec created in step 1.:

    ICACLS.EXE "%SystemRoot%\Temp\comspec"
    C:\Windows\Temp\comspec NT AUTHORITY\SYSTEM:(I)(F)
                            AMNESIAC\Stefan:(I)(F)
                            BUILTIN\Administrators:(I)(F)
    
    Successfully processed 1 files; Failed processing 0 files
    Note: your user account %COMPUTERNAME%\%USERNAME% has full access to this file, inherited from the parent directory!
  4. Create the text file comspec.c with the following content in an arbitrary, preferable empty directory:

    // Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	WCHAR	szBuffer[MAX_PATH];
    	DWORD	dwBuffer = GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(*szBuffer));
    	DWORD	dwError = ERROR_SUCCESS;
    
    	if (dwBuffer == 0UL)
    		dwError = GetLastError();
    	else
    	{
    		memcpy(szBuffer + dwBuffer, L"\\Temp\\comspec", sizeof(L"\\Temp\\comspec"));
    
    		if (!DeleteFile(szBuffer))
    			dwError = GetLastError();
    	}
    
    	ExitProcess(dwError);
    }
  5. Compile and link the source file comspec.c created in step 4.:

    SET CL=/Oi /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /NODEFAULTLIB /SUBSYSTEM:CONSOLE
    CL.EXE comspec.c kernel32.lib
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    comspec.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /ENTRY:mainCRTStartup /NODEFAULTLIB /SUBSYSTEM:CONSOLE
    /out:comspec.exe
    comspec.obj
    kernel32.lib
  6. Execute the console application comspec.exe built in step 5. and evaluate its exit code:

    .\comspec.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    0x0 (WIN32: 0 ERROR_SUCCESS) -- 0 (0)
    Error message text: The operation completed successfully.
    CertUtil: -error command completed successfully.
  7. Finally verify that the file %SystemRoot%\Temp\comspec created in step 1. doesn’t exist any more:

    MKDIR "%SystemRoot%\Temp\comspec"
    RMDIR "%SystemRoot%\Temp\comspec"

Fault № 7

The documentation for the internal Call command of the Command Processor states:
Calls one batch program from another without stopping the parent batch program. […]

Note

Call has no effect at the command prompt when it is used outside of a script or batch file.

Falsification

Perform the following 3 (plus 1 optional) simple steps to prove both highlighted statements of the documentation cited above wrong and show the true behaviour.
  1. Start the Command Processor Cmd.exe in an arbitrary, preferable empty directory, then execute the following single command line:

    CALL :EOF
    Invalid attempt to call batch label outside of batch script.
    Oops: the internal Call command yields at least an error message when used at the (interactive) command prompt.
  2. Execute another single command line: [Screen shot of message box from 'Windows Script Host' on Windows 7]

    CALL winrm.vbs

    OOPS: contrary to both highlighted statements of the documentation cited above, the internal Call command has effect at the (interactive) command prompt outside of a script or batch program and calls not just batch programs – it acts similar to the internal Start command and evaluates the association of file types to file extensions as well as the environment variable PATH!
  3. Display the file type of the file extension .vbs and its associated command line template:

    ASSOC .vbs
    FTYPE VBSFile
    .vbs=VBSFile
    VBSFile="%SystemRoot%\System32\WScript.exe" "%1" %*
  4. Optionally execute the following command lines, then close the windows of Editor and WordPad:

    ASSOC .ini
    FTYPE inifile
    CALL system.ini
    ASSOC .rtf
    FTYPE rtffile
    CALL license.rtf
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    .ini=inifile
    inifile=%SystemRoot%\system32\NOTEPAD.EXE %1
    .rtf=rtffile
    rtffile="%ProgramFiles%\Windows NT\Accessories\WORDPAD.EXE" "%1"

Fault № 8

Like the environment variable PATH is used to locate executable files, standard input redirection and the internal Type command of the Command Processor use the undocumented environment variable DPATH to locate (data) files; it is queried and set with the undocumented internal Dpath command, similar to the internal Path command.

Demonstration

Perform the following 2 simple steps to show the (mis)behaviour.
  1. Start the Command Processor Cmd.exe, then execute the following command line:

    DPATH /?
    Allows programs to open data files in specified directories as if they were
    in the current directory.
    
    APPEND [[drive:]path[;...]] [/X[:ON | :OFF]] [/PATH:ON | /PATH:OFF] [/E]
    APPEND ;
    
      [drive:]path Specifies a drive and directory to append.
      /X:ON        Applies appended directories to file searches and
                   application execution.
      /X:OFF       Applies appended directories only to requests to open files.
                   /X:OFF is the default setting.
      /PATH:ON     Applies the appended directories to file requests that already
                   specify a path.  /PATH:ON is the default setting.
      /PATH:OFF    Turns off the effect of /PATH:ON.
      /E           Stores a copy of the appended directory list in an environment
                   variable named APPEND.  /E may be used only the first time
                   you use APPEND after starting up your system.
    
    Type APPEND ; to clear the appended directory list.
    Type APPEND without parameters to display the appended directory list.
    OOPS: the Command Processor is confused – an (external) APPEND.EXE command is not shipped with 64-bit editions of Windows!

    OUCH: the internal Dpath command has a single argument, either a single semicolon or a list of semicolon-separated directory names!

  2. Execute the following command lines to show the true behaviour:

    DPATH
    SET DPATH
    TYPE system.ini
    CLIP.EXE 0<system.ini
    DPATH %SystemRoot%
    SET DPATH
    TYPE system.ini
    CLIP.EXE 0<system.ini
    MORE.COM system.ini
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    DPATH=(null)
    
    Environment variable DPATH not defined
    
    The system cannot find the file system.ini.
    
    The system cannot find the file specified.
    
    DPATH=C:\Windows
    
    ; for 16-bit app support
    [386Enh]
    woafont=dosapp.fon
    EGA80WOA.FON=EGA80WOA.FON
    EGA40WOA.FON=EGA40WOA.FON
    CGA80WOA.FON=CGA80WOA.FON
    CGA40WOA.FON=CGA40WOA.FON
    
    [drivers]
    wave=mmdrv.dll
    timer=timer.drv
    
    [mci]
    
    Cannot access file C:\Users\Stefan\Desktop\system.ini

Fault № 9

The documentation for the internal Echo command of the Command Processor states:
Remarks

[…]

The documentation for the internal If command of the Command Processor states:
Remarks

[…]

Examples

[…]

To delete the file Product.dat from the current directory or display a message if Product.dat is not found, type the following lines in a batch file:

IF EXIST Product.dat (
del Product.dat
) ELSE (
echo The Product.dat file is missing.
)

Note

These lines can be combined into a single line as follows:

IF EXIST Product.dat (del Product.dat) ELSE (echo The Product.dat file is missing.)
Oops: the example proves the highlighted statement wrong!

Demonstration

Perform the following 6 simple steps to prove the highlighted part of the documentation cited above wrong and show a stupid, about 30 (in words: thirty) year old bug in the Command Processor.
  1. Start the Command Processor Cmd.exe, then execute the ECHO command line from the documentation cited above with only the inner closing parenthesis escaped:

    (ECHO This is (also^) correct)
    This is (also) correct
    Oops;: contrary to the highlighted statement of the first documentation cited above, the inner opening parenthesis doesn’t need to be escaped!
  2. Execute the following ECHO command lines referencing an environment variable with both, one or no inner parentheses escaped:

    (ECHO %CommonProgramFiles^(x86^)% but fails to evaluate the variable!)
    (ECHO %CommonProgramFiles(x86^)% also fails to evaluate the variable!)
    (ECHO %CommonProgramFiles(x86)% fails miserably!)
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    %CommonProgramFiles(x86)% but fails to evaluate the variable!
    %CommonProgramFiles(x86)% also fails to evaluate the variable!
    "\Common" cannot be processed syntactically at this point.
    OOPS: contrary to the highlighted statement of the first documentation cited above, this example but fails!

    OUCH: the last command line is reparsed after environment variable expansion and fails due to the expanded parentheses!

  3. Execute an IF … ELSE … command block that evaluates the (system) environment variable ProgramFiles(x86) in its then clause:

    IF DEFINED ProgramFiles(x86) (
    ECHO %ProgramFiles(x86)% comspec
    ) ELSE (
    ECHO %ProgramFiles%
    )
    "comspec)" cannot be processed syntactically at this point.
  4. Combine the command block from step 1. into a single line:

    IF DEFINED ProgramFiles(x86) (ECHO %ProgramFiles(x86)% comspec) ELSE (ECHO %ProgramFiles%)
    "comspec)" cannot be processed syntactically at this point.
  5. Invert the condition of the IF clause and swap the then clause with the ELSE clause:

    IF NOT DEFINED ProgramFiles(x86) (ECHO %ProgramFiles%) ELSE (ECHO %ProgramFiles(x86)% comspec)
    "comspec)" cannot be processed syntactically at this point.

Work-Around

  1. Enable delayed (environment variable) expansion and repeat step 2. with exclamation marks instead of the percent signs:

    SETLOCAL ENABLEDELAYEDEXPANSION
    (ECHO !CommonProgramFiles^(x86^)! is evaluated now!)
    (ECHO !CommonProgramFiles(x86^)! is evaluated now!)
    (ECHO !CommonProgramFiles(x86)! fails but miserably too!)
    C:\Program Files (x86)\Common Files is evaluated now!
    C:\Program Files (x86)\Common Files is evaluated now!
    "!" cannot be processed syntactically at this point.

    OUCH: the parser is severely broken – parentheses inside a pair of exclamation marks which surround the name of an environment variable don’t terminate an outer block!

  2. Drop the (here superfluous) parentheses around the single command of the ELSE clause from step 5.:

    IF NOT DEFINED ProgramFiles(x86) (ECHO %ProgramFiles%) ELSE ECHO %ProgramFiles(x86)%
    C:\Program Files (x86)
  3. Enable delayed (environment variable) expansion and escape the closing parenthesis:

    SETLOCAL ENABLEDELAYEDEXPANSION
    IF DEFINED ProgramFiles(x86) (ECHO !ProgramFiles(x86^)!) ELSE (ECHO %ProgramFiles%)
    C:\Program Files (x86)

Fault № 10

The documentation for the internal For command of the Command Processor states:
Runs a specified command for each file in a set of files.

[…]

for {%%|%}<Variable> in (<Set>) do <Command> [<CommandLineOptions>]

[…]

Parameter Description
{%%|%}<Variable> Required. Represents a replaceable parameter. Use a single percent sign (%) to carry out the for command at the command prompt. Use double percent signs (%%) to carry out the for command within a batch file. Variables are case sensitive, and they must be represented with an alphabetical value such as %A, %B, or %C.

[…]

Remarks

OUCH: the highlighted parts but contradict each other – any character allows more than just an alphabetical value alias (upper or lower case) letter!

Falsification

Perform the following 3 simple steps to prove the documentation cited above misleading and wrong.
  1. Start the Command Processor Cmd.exe, then execute the following command lines which use non-alphabetical ASCII characters for the variable:

    FOR /F "Tokens=1-15" %! IN ("Exclamation Quote Hash Dollar Percent Ampersand Apostrophe Left_Parenthesis Right_Parenthesis Asterisk Plus Comma Minus Dot Slash") DO @ECHO %! %^" %# %$ %^% %^& %' %( %) %* %+ %, %- %. %/
    FOR /F "Tokens=1-10" %0 IN ("Zero One Two Three Four Five Six Seven Eight Nine") DO @ECHO %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
    FOR /F "Tokens=1-7"  %: IN ("Colon Semicolon Less Equal Greater Question At") DO @ECHO %: %; %^< %= %^> %? %@
    FOR /F "Tokens=1-6"  %[ IN ("Left_Square_Bracket Backslash Right_Square_Bracket Caret Underline BackQuote") DO @ECHO %[ %\ %] %^^ %_ %`
    FOR /F "Tokens=1-4"  %{ IN ("Left_Curly_Bracket Vertical_Bar Right_Curly_Bracket Tilde") DO @ECHO %{ %^| %} %~
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    Exclamation Quote Hash Dollar %% Ampersand Apostrophe Left_Parenthesis Right_Parenthesis Asterisk Plus Comma Minus Dot Slash
    Zero One Two Three Four Five Six Seven Eight Nine
    Colon Semicolon Less Equal Greater Question
    Left_Square_Bracket Backslash Right_Square_Bracket Caret Underline BackQuote
    Left_Curly_Bracket Vertical_Bar Right_Curly_Bracket Tilde
    Oops¹: with exception of the percent sign, all printable ASCII characters can be used for the variable!
  2. Use some (arbitrary) characters for the variable:

    FOR /F %€ IN ("Euro") DO @ECHO %€
    FOR /F "Tokens=1-11" %¢ IN ("Cent Pound Currency Yen Broken_Bar Section Diaeresis Copyright Feminine_Ordinal Left_Angle Not") DO @ECHO %¢ %£ %¤ %¥ %¦ %§ %¨ %© %ª %« %¬
    FOR /F %® IN ("Registered") DO @ECHO %®
    FOR /F %¶ IN ("Paragraph") DO @ECHO %¶
    Euro
    Cent Pound Currency Yen Broken_Bar Section Diaeresis Copyright Feminine_Ordinal Left_Angle Not
    Registered
    Paragraph
    Note: a demonstration with (for example) Cyrillic, Greek or Hebrew letters is left as an exercise to the reader!
  3. Execute the following command lines to show surprising behaviour:

    FOR /F "Delims=" %? IN ("! !! "" & && <NUL: >NUL: ^ ^^ | ||") DO ECHO %?
    FOR /F "Tokens=1-10" %0 IN ("! !! "" & && <NUL: >NUL: ^ ^^ | ||") DO ECHO %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
    ECHO ! !! "" & && <NUL: >NUL:  ^ | ||
    ! !! "" & && <NUL: >NUL:   | ||
    ECHO ! !! "" & && <NUL: >NUL: ^ | ||
    ! !! "" & && <NUL: >NUL:  | ||
    Oops²: with exception of the caret, which keeps its function as escape character, unescaped special characters forwarded by the internal For command via %‹character› are treated as literals!

    Caveat: in batch scripts with delayed expansion enabled, exclamation marks are but removed!

Fault № 11

The documentation for the internal For command of the Command Processor states:
The documentation for the Command Processor Cmd.exe states:
Parameter Description
/d Disables execution of AutoRun commands.

[…]

Note: this feature enables (unprivileged) users to tamper with Logon scripts configured by their (privileged) administrators who are unaware of the pitfalls demonstrated below!

Demonstration

Perform the following 4 simple steps to show undocumented (mis)behaviour plus important details missing in the documentation cited above.
  1. Start the Command Processor, then run the following command lines to set the Windows directory as CWD, remove all environment variables, verify that none are left and list the environment variables of a child Cmd.exe process:

    REM Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    CHDIR /D "%SystemRoot%"
    FOR /F "Delims==" %? IN ('SET') DO @SET %?=
    SET
    FOR /F "Delims=" %? IN ('SET') DO @ECHO %?
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    COMSPEC=C:\Windows\system32\cmd.exe
    PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC
    PROMPT=$P$G
    Oops: if the Command Processor does not inherit the environment variables COMSPEC, PATHEXT and PROMPT from its parent process it sets them with default values.
  2. Execute the following (equivalent) command lines to show the command line of the child Cmd.exe process:

    FOR /F "Delims=" %? IN ('ECHO %CMDCMDLINE^%') DO @ECHO %?
    FOR /F "Delims= UseBackQ" %? IN (`ECHO %CMDCMDLINE^%`) DO @ECHO %?
    C:\Windows\system32\cmd.exe /c ECHO %CMDCMDLINE%
    C:\Windows\system32\cmd.exe /c ECHO %CMDCMDLINE%
    OUCH¹: both FOR /F … IN ('…') DO … and FOR /F "UseBackQ" … IN (`…`) DO … execute their child Cmd.exe process only with the parameter /c, i.e. AutoRun commands are executed!
  3. Execute the following command lines to set an AutoRun command in the user’s Registry, start a child Cmd.exe process and remove the AutoRun command afterwards:

    System32\REG.EXE ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /V "AutoRun" /T REG_SZ /D "VERIFY" /F
    FOR /F "Delims=" %? IN ('EXIT') DO @ECHO %?
    System32\REG.EXE DELETE "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /V "AutoRun" /F
    The operation completed successfully.
    VERIFY is off.
    The operation completed successfully.
    OUCH²: due to the missing parameter /d the child Cmd.exe process executes the AutoRun command(s) set in the Registry which (can) create additional and typically unwanted output or perform arbitrary nefarious atrocities!
  4. Finally execute the following command line to quit the Command Processor:

    EXIT

Security Impact

The (unintended) execution of a (bogus) command specified by a (user-controlled) Registry entry like AutoRun is a well-known weakness, documented as CWE-??: and CWE-??: in the CWE; it allows well-known attacks like CAPEC-??: documented in the CAPEC.

Work-Around

Use
1>"‹file›" (‹command›)
FOR /F "UseBackQ" … IN ("‹file›") DO …
ERASE "‹file›"
instead of
FOR /F "UseBackQ" … IN (`‹command›`) DO …
or
FOR /F … IN ('‹command›') DO …
to prevent the execution of AutoRun commands.

Note: this also saves the execution of a (hidden) instance of the Command Processor!

Fault № 12

The documentation for the internal If command of the Command Processor states:
Performs conditional processing in batch programs.

[…]

Remarks

Demonstration

Perform the following 5 simple steps to prove the highlighted statement of the documentation cited above incomplete as well as misleading and show a more than 25 (in words: twenty-five) year old bug.
  1. Start the Command Processor Cmd.exe, then display the help text of its internal Set command:

    SET /?
    Environment variable substitution has been enhanced as follows:
    […]
    May also specify substrings for an expansion.
    
        %PATH:~10,5%
    
    would expand the PATH environment variable, and then use only the 5
    characters that begin at the 11th (offset 10) character of the expanded
    result.  If the length is not specified, then it defaults to the
    remainder of the variable value.  If either number (offset or length) is
    negative, then the number used is the length of the environment variable
    value added to the offset or length specified.
    
        %PATH:~-10%
    
    would extract the last 10 characters of the PATH variable.
    
        %PATH:~0,-2%
    
    would extract all but the last 2 characters of the PATH variable.
    […]
    If Command Extensions are enabled, then there are several dynamic
    environment variables that can be expanded but which don't show up in
    the list of variables displayed by SET.  These variable values are
    computed dynamically each time the value of the variable is expanded.
    If the user explicitly defines a variable with one of these names, then
    that definition will override the dynamic one described below:
    
    %CD% - expands to the current directory string.
    
    %DATE% - expands to current date using same format as DATE command.
    
    %TIME% - expands to current time using same format as TIME command.
    
    %RANDOM% - expands to a random decimal number between 0 and 32767.
    
    %ERRORLEVEL% - expands to the current ERRORLEVEL value
    
    %CMDEXTVERSION% - expands to the current Command Processor Extensions
        version number.
    
    %CMDCMDLINE% - expands to the original command line that invoked the
        Command Processor.
  2. Create the text file comspec.bat with the following content in an arbitrary, preferable empty directory:

    REM Copyleft © 2001-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    SET CMDCMDLINE=
    IF NOT DEFINED CMDCMDLINE EXIT /B
    SET CMDCMDLINE
    REM '%CMDCMDLINE%'
    :comspec
    IF NOT "%CMDCMDLINE:~33,-3%" == "" GOTO :comspec
    SET CMDCMDLINE
    IF DEFINED CMDCMDLINE REM '%CMDCMDLINE%'
    PAUSE
    EXIT /B
  3. Start the batch script comspec.bat created in step 2. per double-click:

    REM Copyleft © 2001-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de>
    SET CMDCMDLINE=
    IF NOT DEFINED CMDCMDLINE EXIT /B
    SET CMDCMDLINE
    Environment variable CMDCMDLINE not defined
    REM 'C:\Windows\System32\cmd.exe /c ""C:\Users\Stefan\Desktop\comspec.bat" "'
    IF NOT "C:\Users\Stefan\Desktop\comspec.bat" == "" GOTO :comspec
    IF NOT "" == "" GOTO :comspec
    SET CMDCMDLINE
    Environment variable CMDCMDLINE not defined
    IF DEFINED CMDCMDLINE REM ''
    PAUSE
    Press any key to continue . . .
    EXIT /B
    OUCH¹: contrary to the highlighted statement of the documentation cited above, the CMDCMDLINE variable is not added to the environment!

    OUCH²: extracting a substring from the CMDCMDLINE variable sets it to the resulting substring, i.e. modifies the variable!

  4. Overwrite the text file comspec.bat created in step 2. with the following content:

    REM Copyleft © 2001-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    SET CMDCMDLINE=
    IF NOT DEFINED CMDCMDLINE EXIT /B
    SET CMDCMDLINE
    REM '%CMDCMDLINE%'
    SETLOCAL ENABLEDELAYEDEXPANSION
    :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    SET CMDCMDLINE
    IF DEFINED CMDCMDLINE REM '%CMDCMDLINE%'
    PAUSE
    EXIT /B
  5. Start the batch script comspec.bat modified in step 4. per double-click:

    REM Copyleft © 2001-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de>
    SET CMDCMDLINE=
    IF NOT DEFINED CMDCMDLINE EXIT /B
    SET CMDCMDLINE
    Environment variable CMDCMDLINE not defined
    REM 'C:\Windows\System32\cmd.exe /c ""C:\Users\Stefan\Desktop\comspec.bat" "'
    SETLOCAL ENABLEDELAYEDEXPANSION
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    IF NOT "!CMDCMDLINE:~1,-1!" == "" GOTO :comspec
    SET CMDCMDLINE
    Environment variable CMDCMDLINE not defined
    IF DEFINED CMDCMDLINE REM ''
    PAUSE
    Press any key to continue . . .
    EXIT /B
    OUCH³: with delayed expansion enabled same as above!

Fault № 13

When executed with the argument ON on OFF, the undocumented internal Keys command sets the also undocumented environment variable to this value. When executed without argument, it displays its setting like the internal Verify command, but does not evaluate the environment variable.

Falsification

  1. KEYS /?
    KEYS
    SET KEYS
    KEYS ON
    SET KEYS
    KEYS OFF
    SET KEYS
    SET KEYS=ON
    KEYS
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    Enables or disables command line editing on DOS system
    
    This is present for Compatibility with DOS systems. It has no effect
    under Windows, as command line editing is always enabled.
    
    KEYS is off.
    Environment variable KEYS not defined
    KEYS=ON
    KEYS=OFF
    KEYS is off.
    OOPS: contrary to its help text, the internal KEYS command has effect under Windows – it sets an environment variable!

Fault № 14

The documentation for the internal Mkdir alias Md command of the Command Processor states:
Creates a directory or subdirectory.

Note

This command is the same as the mkdir command.

[…]

md [<Drive>:]<Path>
mkdir [<Drive>:]<Path>
The documentation for the internal Rmdir alias Rd command of the Command Processor states:
Deletes a directory. This command is the same as the rmdir command.

[…]

rd [<Drive>:]<Path> [/s [/q]]
rmdir [<Drive>:]<Path> [/s [/q]]

Falsification

Perform the following 2 simple steps to prove the documentation cited above as well as the help texts of both internal commands wrong.
  1. Start the Command Processor Cmd.exe, then display the help texts of both internal commands:

    MKDIR /?
    RMDIR /?
    Creates a directory.
    
    MKDIR [drive:]path
    MD [drive:]path
    
    […]
    
    Removes (deletes) a directory.
    
    RMDIR [/S] [/Q] [drive:]path
    RD [/S] [/Q] [drive:]path
    
        /S      Removes all directories and files in the specified directory
                in addition to the directory itself. Used to remove a directory
                tree.
    
        /Q      Quiet mode, do not ask if ok to remove a directory tree with /S
  2. Create and delete more than a single directory with both internal commands:

    MKDIR COMSPEC comspec
    RMDIR COMSPEC comspec
    A subdirectory or file COMSPEC already exists.
    Error occurred while processing: COMSPEC.
    
    The system cannot find the file COMSPEC.
    Oops: contrary to their documentation cited above as well as their help texts, both internal commands accept more than a single directory pathname!

Fault № 15

The documentation for the internal Prompt command of the Command Processor states:
Changes the Cmd.exe command prompt. If used without parameters, prompt resets the command prompt to the default setting, which is the current drive letter and directory followed by the greater than symbol (>).
Note: the documentation but fails to mention that the current setting is stored in the environment variable PROMPT.

Demonstration

Perform the following 3 simple steps to show the true behaviour.
  1. Start the Command Processor Cmd.exe, then execute the following command lines:

    SET PROMPT
    PROMPT
    SET PROMPT
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    PROMPT=$P$G
    Environment variable PROMPT not defined
    Oops¹: when the internal Set command is executed without parameters the environment variable PROMPT is unset and thus removed from the process environment block.
  2. Start another instance of the Command Processor and display its (default) value of the environment variable PROMPT:

    "%COMSPEC%" /D /C SET PROMPT
    PROMPT=$P$G
    Oops²: when a new instance of the Command Processor is started and the environment variable PROMPT is not inherited from the parent process it is preset with the default value $P$G of the prompt.
  3. Set the environment variable PATHEXT to an (arbitrary valid) value:

    SET PROMPT=$$$A$B$C$D$E$F$G$L$M$N$P$Q$S$T$V$+$_
    $&|(04/27/2012←)><CC:\Users\Stefan\Desktop= 12:34:56,78Microsoft Windows [Version 6.1.7601]
    Oops³: setting the environment variable PROMPT changes the prompt immediately.

Fault № 16

The documentation for the internal Rem command of the Command Processor states:
Remarks

[…]

Demonstration

Perform the following 3 simple steps to prove the documentation cited above incomplete and show surprising behaviour as well as a bug.
  1. Start the Command Processor Cmd.exe, then execute the following command lines to show undocumented behaviour at the (interactive) command prompt:

    0<. REM /?
    1>. REM /?
    2>>.. REM /?
    REM 0<. /?
    REM 1>. /?
    REM 2>>.. /?
    REM /? 0<.
    REM /? 1>.
    REM /? 2>..
    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Oops¹: a redirection operator <, > or >> following or preceeding the internal Rem command with parameter /? is interpreted – and vice versa!

  2. Execute the following command lines to show surprising behaviour:

    REM /? & VER
    REM /?=%RANDOM%
    REM com/?;spec
    REM http://www.microsoft.com/?q=comspec
    Records comments (remarks) in a batch file or CONFIG.SYS.
    
    REM [comment]
    
    Microsoft Windows [Version 6.1.7601]
    
    12345 was unexpected at this time.
    spec was unexpected at this time.
    comspec was unexpected at this time.
    Oops²: a pipe operator | or an ampersand operator & following the internal Rem command with parameter /? is interpreted – and vice versa!

    Oops³: the internal Rem command fails when /? is followed by arbitrary characters which include one of the separators space, comma, semicolon and the undocumented equal sign!

  3. Execute the following command lines which use the special characters not covered in the documentation cited above:

    ECHO
    REM & ECHO &
    REM && ECHO &&
    REM || ECHO ||
    0<NUL: 1>NUL: REM ^
    comspec
    (REM ^)
    )
    ECHO is on.
    More?
    More?
    Oops⁴: an ampersand (&) is also not interpreted as special character!

    Oops⁵: neither the double ampersand (&&) nor the double pipe (||) are interpreted as conditional operators!

    Oops⁶: the caret (^) is but interpreted as special character – it escapes both the newline and the closing parenthesis here!

    Oops⁷: neither input nor output redirection are honored, both are ignored completely!

  4. Finally show the bug:

    (REM ^))
    )
    (REM ^))))
    )
    More?
    More?
    OUCH: inside a block started by an opening parenthesis any number of closing parentheses after an escaped one are discarded!

Fault № 17

The documentation for the internal Set command of the Command Processor states:
Displays, sets, or removes CMD.EXE environment variables. If used without parameters, set displays the current environment variable settings.

[…]

set [<Variable>=[<String>]]
set [/p] <Variable>=[<PromptString>]
set /a <Variable>=<Expression>

[…]

Parameter Description
/a Sets String to a numerical expression that is evaluated.
<Expression> Specifies a numerical expression. […]
/? Displays help at the command prompt.

[…]

The following table lists the operators supported for /a in descending order of precedence.

Operator Operation performed
<< >> Logical shift.

Falsification

Perform the following 2 (plus 1 optional) simple steps to show the true behaviour plus a really stupid, at least 28 (in words: twenty-eight) year old bug which crashes the Command Processor.
  1. Start the Command Processor Cmd.exe, then evaluate some constants and expressions:

    SET /A 0xFFFFFFFF
    SET /A ~0
    SET /A ~0 ^<^< 32
    SET /A 0x80000000
    SET /A 0x80000000 ^>^> 99
    SET /A -2147483648
    SET /A ~2147483647
    SET /A ~2147483647 * 2
    SET /A ~2147483647 / ~0
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    -1
    -1
    0
    -2147483648
    -1
    Invalid number. Numbers are limited to 32-bits of precision.
    -2147483648
    0
    Invalid number. Numbers are limited to 32-bits of precision.
    OOPS¹: contrary to the first highlighted part of the documentation cited above, <Variable> is but optional with SET /A; if present it is set to the signed decimal string form of the resulting value.

    Note: shifts are not limited to the size of the internal (32-bit) number width.

    OOPS²: contrary to the last highlighted part of the documentation cited above, shifts are performed arithmetical, i.e. right shifts propagate the sign!

    Ouch: although valid, a literal −2147483648, the smallest signed 32-bit integer, is erroneously reported as invalid number!

    Oops: (signed) integer overflow is detected only for division, other operations wrap around.

  2. Finally demonstrate the bug:

    SET /A ~2147483647 % ~0
    OUCH: on systems with i386 or AMD64 processor, the Command Processor crashes with an integer overflow exception 0xC0000095 when computing the modulus of −2147483648 ÷ −1 (which happens to be 0, the only number smaller in magnitude than the divisor −1)!

    Note: dividing −2147483648, the smallest signed 32-bit integer, by −1 yields the quotient 2147483648, which is but not representable as signed 32-bit integer and therefore produces an overflow (really: raises a divide error exception alias #DE) that the Command Processor fails to handle, i.e. neither prevents nor catches for the modulus operator, while it does so for the division operator!

    Note: integer overflow and failure to catch the eventually resulting exception are well-known weaknesses, documented as CWE-190: Integer Overflow or Wraparound and CWE-248: Uncaught Exception in the CWE; they allow well-known attacks like CAPEC-92: Forced Integer Overflow documented in the CAPEC.

  3. (Optional) If you have the Debugging Tools for Windows installed, execute the Command Processor under the debugger:

    CDB.EXE /C g;q /G /g "%COMSPEC%" /D /C SET /A ~2147483647 % ~0
    Note: if necessary, see the MSDN articles Debugging Using CDB and NTSD and CDB Command-Line Options for an introduction.
    Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    CommandLine: "C:\Windows\system32\cmd.exe" /D /C SET /A ~2147483647 % ~0
    Symbol search path is: srv*
    Executable search path is: 
    ModLoad: 4a6d0000 4a71c000   cmd.exe
    ModLoad: 779c0000 77b40000   ntdll.dll
    ModLoad: 75610000 75720000   C:\Windows\syswow64\kernel32.dll
    ModLoad: 752d0000 75317000   C:\Windows\syswow64\KERNELBASE.dll
    ModLoad: 75540000 755e1000   C:\Windows\syswow64\ADVAPI32.DLL
    ModLoad: 757a0000 7584c000   C:\Windows\syswow64\msvcrt.dll
    ModLoad: 77420000 77439000   C:\Windows\SysWOW64\sechost.dll
    ModLoad: 77300000 773f0000   C:\Windows\syswow64\RPCRT4.dll
    ModLoad: 750e0000 75140000   C:\Windows\syswow64\SspiCli.dll
    ModLoad: 750d0000 750dc000   C:\Windows\syswow64\CRYPTBASE.dll
    ModLoad: 73d10000 73d17000   C:\Windows\SysWOW64\WINBRAND.dll
    ModLoad: 76f60000 77060000   C:\Windows\syswow64\USER32.dll
    ModLoad: 764f0000 76580000   C:\Windows\syswow64\GDI32.dll
    ModLoad: 76580000 7658a000   C:\Windows\syswow64\LPK.dll
    ModLoad: 76690000 7672d000   C:\Windows\syswow64\USP10.dll
    ModLoad: 76630000 76690000   C:\Windows\SysWOW64\IMM32.DLL
    ModLoad: 75470000 7553e000   C:\Windows\syswow64\MSCTF.dll
    (3314.4098): Integer overflow - code c0000095 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=80000000 ebx=00000025 ecx=00000025 edx=ffffffff esi=003ef680 edi=003ef69c
    eip=4a6e5176 esp=003ef650 ebp=003ef650 iopl=0         nv up ei ng nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010286
    *** ERROR: Module load completed but symbols could not be loaded for cmd.exe
    cmd+0x15176:
    4a6e5176 f77d14          idiv    eax,dword ptr [ebp+14h] ss:002b:003ef664=ffffffff
    0:000:x86> cdb: Reading initial command 'g;q'
    (3314.4098): Integer overflow - code c0000095 (!!! second chance !!!)
    quit:

Fault № 18

The documentation for the internal Start command of the Command Processor states:
Starts a separate Command Prompt window to run a specified program or command.

[…]

Remarks

OUCH: the default value for the PATHEXT environment variable is but .COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC!

Falsification

Perform the following 9 simple steps to prove the 3 highlighted statements of the documentation cited above wrong and show undocumented (mis)behaviour that causes a security vulnerability.
  1. Start the Command Processor Cmd.exe, then execute the following command lines to display the current setting of the environment variable PATHEXT and determine its origin:

    SET PATHEXT
    REG.EXE QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V PATHEXT
    Note: the command lines can be copied and pasted as block into a Command Processor window.
    PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
        PATHEXT    REG_SZ    .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    OOPS¹: in the installation images distributed by Microsoft, the environment variable PATHEXT is preset with a non-default value!
  2. Unset the environment variable PATHEXT to remove it from the process environment block and start another instance of the Command Processor to display its (default) value of this environment variable:

    SET PATHEXT=
    START /B CMD /D /C SET PATHEXT
    PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC
    OOPS²: the default value of the environment variable PATHEXT differs from the value given in the documentation cited above!
  3. Set the environment variable COMSPEC to the path name of an arbitrary application and start another instance of the Command Processor:

    SET COMSPEC=%SystemRoot%\System32\Reg.exe
    START /B CMD /D /C ECHO
    Note: the Registry Console Tool Reg.exe is only (ab)used as canary here.
    ECHO is on.
    OUCH¹: contrary to the first highlighted sentence of the documentation cited above, the environment variable COMSPEC is not evaluated by the internal START […] CMD […] command!
  4. Create an empty file CMD.EXE in the current directory and start another instance of the Command Processor to prove the first remark of the documentation cited above completely wrong:

    COPY NUL: CMD.EXE
    START CMD
    [Screen shot of message box from module loader on Windows 7]
            1 file(s) copied.
    Access Denied
    OUCH²: contrary to the second highlighted sentence of the documentation cited above, the internal START […] CMD […] command executes an arbitrary application CMD.EXE that happens to exist in the CWD!
  5. Rename of the empty file CMD.EXE to CMD.COM and repeat to last command the prove the first remark of the documentation cited above again completely wrong:

    RENAME CMD.EXE CMD.COM
    START CMD
    [Screen shot of message box from module loader on Windows 7]
    Access Denied
    OUCH³: START CMD also executes an arbitrary application CMD.COM that happens to exist in the CWD!
  6. Delete the empty file CMD.COM, create the text file CMD.BAT with the single (command) line @VERIFY & EXIT in the current directory and repeat the proof from step 4. once more:

    ERASE CMD.COM
    1>CMD.BAT ECHO @VERIFY & EXIT
    START /B CMD
    VERIFY is off.
    OUCH⁴: START […] CMD […] even executes an arbitrary batch script CMD.BAT that happens to exist in the CWD!

    Note: a repetition of the previous step 6. using other extensions from the PATHEXT environment variable is left as an exercise to the reader.

  7. Execute the following command line to show undocumented (mis)behaviour:

    START /B EXIT
    ERROR: Invalid Argument/Option - '/K'.
    Type "REG /?" for usage.
    OUCH⁵: contrary to the documentation cited above, without a first token CMD the internal command START ‹arguments› evaluates the (user-controlled) environment variable COMSPEC and executes an arbitrary application using the command line %COMSPEC% /K ‹arguments›!

    Note: properly implemented, the Command Processor would fetch its own path name with the Win32 function GetModuleFileName() instead to use the value of a user-controlled environment variable!

  8. Delete the environment variable COMSPEC and repeat the previous step 7. to show more undocumented (mis)behaviour:

    SET COMSPEC=
    START /B EXIT
    The COMSPEC environment variable does not point to CMD.EXE.
  9. Finally clean up and quit the Command Processor:

    ERASE CMD.BAT
    EXIT

Security Impact

The (unintended) execution of (a bogus) application or script CMD.EXE, CMD.COM, CMD.BAT etc. from the CWD constitutes a security vulnerability, similar to CVE-2014-0315 alias MS14-019 I discovered and reported at the MSRC about 10 years ago and which was fixed with security update 2922229 back then.

Note: the post MS14-019 – Fixing a binary hijacking via .cmd or .bat file on Microsoft’s Security Research and Defense Blog provides additional information.

The well-known underlying weakness is documented as CWE-426: Untrusted Search Path and CWE-427: Uncontrolled Search Path Element in the CWE; the well-known attacks are documented as CAPEC-471: Search Order Hijacking and CAPEC-635: Alternative Execution Due to Deceptive Filenames in the CAPEC.

The (unintended) execution of a (bogus) application determined by the value of a (user-controlled) environment variable like COMSPEC is another well-known weakness, documented as CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') and CWE-73: External Control of File Name or Path in the CWE; it too allows well-known attacks like CAPEC-13: Subverting Environment Variable Values documented in the CAPEC.

MSRC Case 59749

Due to its security impact I reported this bug at the MSRC where case number 59749 was assigned.

They replied with the following statements:

The engineering team has looked over the issue and has stated that this appears to be a documentation error and has been handed over to the team owning that site. In this case this does not appear to be a vulnerability and we will be closing it out on our side. The method of using this information in an attack would require a remote attacker to find malicious program that uses the START cmd and trick the user to trigger this program as a minimum.
OUCH: it appears to me that the engineering team is wrong; I recommend to have them read (and understand) especially (the end of) the chapter titled Current Working Directory (CWD) DLL planting of the blog post Triaging a DLL planting vulnerability and recognise the striking similarity:
A DLL planting issue that falls into this category of CWD DLL planting is treated as an Important severity issue and we will issue a security patch for this.

Remediation

Set the environment variable NoDefaultCurrentDirectoryInExePath which controls the Win32 function NeedCurrentDirectoryForExePath() with an arbitrary value to remove the (implicit) . alias CWD from (the front of) the search path for executable files.

CAVEAT: the (internal) command SET NoDefaultCurrentDirectoryInExePath= removes this environment variable from the environment block of the current instance of the Command Processor and neutralises the remediation for it and all its future child processes; the command line SetX.exe NoDefaultCurrentDirectoryInExePath "" as well as the VBScript statement WScript.CreateObject("WScript.Shell").Environment("VOLATILE").Item("NoDefaultCurrentDirectoryInExePath") = vbNullString remove this environment variable from the environment block of the shell Explorer.exe and neutralise the remediation for all its future child processes!

Contact and Feedback

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2024 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>