Escaping Code for Different Shells
Posted
by Jon Purdy
on Stack Overflow
See other posts from Stack Overflow
or by Jon Purdy
Published on 2010-05-01T17:04:18Z
Indexed on
2010/05/01
17:07 UTC
Read the original article
Hit count: 315
Question:
What characters do I need to escape in a user-entered string to securely pass it into shells on Windows and Unix? What shell differences and version differences should be taken into account? Can I use printf "%q"
somehow, and is that reliable across shells?
Backstory (a.k.a. Shameless Self-Promotion):
I made a little DSL, the Vision Web Template Language, which allows the user to create templates for X(HT)ML documents and fragments, then automatically fill them in with content. It's designed to separate template logic from dynamic content generation, in the same way that CSS is used to separate markup from presentation.
In order to generate dynamic content, a Vision script must defer to a program written in a language that can handle the generation logic, such as Perl or Python. (Aside: using PHP is also possible, but Vision is intended to solve some of the very problems that PHP perpetuates.) In order to do this, the script makes use of the @system
directive, which executes a shell command and expands to its output. (Platform-specific generation can be handled using @unix
or @windows
, which only expand on the proper platform.) The problem is obvious, I should think:
test.htm
:
<!-- ... -->
<form action="login.vis" method="POST">
<input type="text" name="USERNAME"/>
<input type="password" name="PASSWORD"/>
</form>
<!-- ... -->
login.vis
:
#!/usr/bin/vision
# Think USERNAME = ";rm -f;"
@system './login.pl' { USERNAME; PASSWORD }
One way to safeguard against this kind of attack is to set proper permissions on scripts and directories, but Web developers may not always set things up correctly, and the naive developer should get just as much security as the experienced one. The solution, logically, is to include a @quote
directive that produces a properly escaped string for the current platform.
@system './login.pl' { @quote : USERNAME; @quote : PASSWORD }
But what should @quote
actually do? It needs to be both cross-platform and secure, and I don't want to create terrible problems with a naive implementation. Any thoughts?
© Stack Overflow or respective owner