This subject seemed to tail off without resolution, yet using ECHO to reliably display information is such a necessity.
jeb wrote: ↑12 Aug 2010 12:17
...
fails, if a file in the current directory exists named my.bat
Code: Select all
echo\..\my.bat
echo:\..\my.bat
echo.\..\my.bat
...
dbenham wrote: ↑16 Jun 2011 16:22
...
The
echo:\..\my.bat behavior really blows my mind.
...
Not only that, it's a seemingly unexploited code-injection security vulnerability! This had me searching for a character that did not exhibit the ability to invoke file system action at all.
Perhaps if the known issues were summarized in some way. This lead me to layout the issues with each character in some objective/digestible form, so I started tabulating my own efforts and verifying some of those that may've have been discussed in various forums.
I believe these are issues toward consistently using internal ECHO command to display intended content:
- avoid searching for or unintentionally invoking external commands [CRITICAL--could inadvertently cause loss of data]
- prevent unpredictable failure behavior due to a particular file name/path existing in the file system
- suppress unintended invocation of ECHO's HELP [or CALL's HELP] when line begins with /? or ?, instead output those characters as intended
- suppress ECHO's tendency to report status [ECHO is on / off] when nothing follows, and output a blank/new line as intended
Here's the reference I've been developing in table form. Basically, one would want to
choose the character that checks the most "Ok" boxes, but I'd also avoid the insecure ones, those that have the potential for the file system vulnerability:
Code: Select all
Test _________________________________________ Type__________
Char Echo %Macro% Call For ECHO /? ECHO ? Ext File Batch Prompt isDelim Note
_______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______________________________
ECHO[Space] On/Off On/Off bat/cmd On/Off Help Ok Ext Valid 9009 Token CALL ECHO runs ECHO.bat/.cmd if exist in dir, ignores PATHEXT
ECHO[Tab] On/Off On/Off On/Off On/Off Help Ok Ok Ok Invalid Token
ECHO, Ok Ok Ok Ok Help Ok Ok Valid Ok Token
ECHO; Ok Ok Ok Ok Help Ok Ok Valid Ok Token
ECHO= Ok Ok Ok Ok Help Ok Ok Valid Ok Token
ECHO/ Ok Ok Ok Ok -Help +Help Ok Ok Ok Ok Ok -+Prints ECHO's Help if content begins with ? or /? follows any token [CALL's Help if CALLed and contncontains /? anywhere]
ECHO\ Ok Ok Ok Ok Ok-Call Ok Ext Path .ext 9009 Ok -CALL ECHO\/? produces CALL's Help; Executes ECHO\batchfilename.bat if path exists
ECHO: Ok Ok Ok Ok Ok-Call Ok Ext Ok .ext 9009-2K Ok -CALL ECHO:/? produces CALL's Help; Executes if \..\my.pathext exists
ECHO+ Ok Ok Ok Ok Ok-Call Ok Call Valid bat/cmd Ok Ok -CALL ECHO+/? produces CALL's Help
ECHO. *9009 *9009 File Ok Ok-Call Ok Ext Valid bat/cmd 9009 Ok -CALL ECHO./? produces CALL's Help; *9009 if path to bat/cmd/js exists, ignores PATHEXT
ECHO[ Ok Ok 9009 Ok Ok-Call Ok Call Valid bat/cmd Ok Ok -CALL ECHO[/? produces CALL's Help
ECHO] Ok Ok 9009 Ok Ok-Call Ok Call Valid bat/cmd Ok Ok -CALL ECHO]/? produces CALL's Help
ECHO( Ok Ok 9009 9009 Ok%Call Ok%9009 Call Valid Ok Ok Command -CALL ECHO(/? produces CALL's Help; %9009 in FOR command variable: FOR %%a in ("(")do @ECHO%%~a/?
ECHO) 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Command
ECHO^& 9009 9009 On/Off Ok 9009 9009 Ext Valid 9009 Command
ECHO^| 9009 9009 On/Off Ok 9009 9009 Ext Valid 9009 Pipe
ECHO^< 9009 9009 9009 9009 9009 9009 Ext? Ok 9009 Ok
ECHO^> 9009 9009 9009 9009 9009 9009 Ext? Ok 9009 Ok
ECHO* 9009 9009 9009 9009 9009 9009 Ext? Ok 9009 Ok
ECHO? 9009 9009 9009 9009 9009 9009 Ext? Ok 9009 Ok
ECHO_ 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO- 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO! 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO@ 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO# 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO$ 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO% 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO^ 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO{ 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO} 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO' 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO` 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO~ 9009 9009 9009 9009 9009 9009 Ext Valid 9009 Ok
ECHO" 9009 9009 9009 Unknown 9009 9009 Ext Valid 9009 Command
Legend ("Ok" passes the test):
Echo Displays intended blank line without giving status: ECHO is [on/off].
%Macro% Displays as intended when used as an environment variable macro
Call Displays as intended without attempting external path search
For Displays as intended when used as a FOR command variable
Help /? Displays as intended despite beginning with /?
Help ? Displays as intended despite beginning with ?
Ext Most likely remains internal, Ext means content can trigger external access to the file system: ()[]{}^=;!'+,`~ and [space] and/or .\:
File Character cannot exist in File System preventing introduction of potential conflicts--exclude if Valid
Path Displays as intended despite content beginning with valid path reference \..\name.bat
Batch Results when executed from batch file
Prompt Results typing at Command Prompt
isDelim is a delimiter, potential conflict as a:
Command delimiter
Pipe delimiter
Token delimiter
After years of wrestling with this, I think we can categorize the adverse issues into a few main categories:
- [Potentially] Destructive - Any character that can cause ECHO to inadvertently trigger invocation of any file system entry. This must be avoided at all costs.
- Confusing/Deceiving - Characters that may cause inconsistent/undesirable/unbalanced actions either due to code readability by humans or machine [yes, I'm specifically thinking of "ECHO(" which makes the code appear to have unbalanced parenthesis, or worse making it look deceivingly like a certain code block should/(not) be executed when it actually isn't].
- Cosmetic - Everything else that may result in the wrong information being displayed. [Granted, the display of wrong information could potentially cause subsequent destruction from actions taken due to incorrect information being displayed, it is not immediately destructive through the act of displaying the information itself].
There were some posts here referring to "safe" characters, which I now believe is a relative term. I'm going to refer as:
- "insecure" any character that could cause inadvertent invocation
- "safe" one that reliably displays the intended information
alan_b wrote: ↑09 Dec 2009 11:19
... I prefer to avoid any future confusion of : and \ as elements of a file path, and am now using
ECHO/
The OP's original suggestion of "/" as the ECHO delimiter actually may appear to be the most secure one, in that (at least in my. testing), I've been unable to have it inadvertently try to invoke anything from the file system. In my reference table above, ECHO/ emerges as the one that has the most "Ok" columns and doesn't have the file system invocation vulnerability.
When I look at
ECHO/ as my choice of ECHO delimiter, there is really only one problem to tackle: the ? anomalies.
jeb wrote: ↑12 Aug 2010 12:17
...
they show the HELP of the ECHO command
...
While I know this refers to the specific characters listed, I found these not shown interesting:
Correctly displays "/?":
Correctly displays "?":
On the other hand, this show ECHO's Help:
alan_b wrote: ↑12 Aug 2010 11:25
...
ECHO/ ? WHAT'S UP DOC ?
gives a result I never expected ! !
More...
Using "/":
Code: Select all
>echo//?
/?
>echo/ / ?
/ ?
>echo/ / . ?
/ . ?
>echo/ . / ?
... ECHO [ON | OFF] ...
>echo/ ? . / ?
... ECHO [ON | OFF] ...
>echo/ / ? . ?
/ ? . ?
Using "=":
Code: Select all
>echo= / ?
... ECHO [ON | OFF] ...
>echo= / . ?
/ . ?
>echo= . / ?
. / ?
>echo= ? . / ?
? . / ?
>echo= / ? . ?
... ECHO [ON | OFF] ...
This suggests there's some sort of escaping possible:
Code: Select all
>echo/?
... ECHO [ON | OFF] ...
>echo//?
/?
>echo///?
... ECHO [ON | OFF] ...
>echo////?
///?
>echo/////?
... ECHO [ON | OFF] ...
>echo//////?
/////?
So it seems that ECHO/ can be used unless the content begins with "?", in which case these work equally inconsistent:
Has anyone found a way to reliably ECHO a line that contains a "/?" or "?" character? Using ECHO/ as a delimiter-of-choice, this would seem to be the only unsolved mystery. Except...
dbenham wrote: ↑30 Jan 2018 08:56
... because I don't think a safe form exists for CALL ECHO. ...
I agree. When CALL ECHO invokes CALL's Help, I've found no amount of escaping to stop it.