473,395 Members | 1,670 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Avoiding shell metacharacters in os.popen

I'm trying to avoid using shell metacharacters in os.popen in a portable
fashion.

os.popen() only seems to take a string as the command which would need
tricky quoting.

os.popen2() can take a string or a list - the relevant code in Unix
python (in popen2.py) being...

def _run_child(self, cmd):
if isinstance(cmd, basestring):
cmd = ['/bin/sh', '-c', cmd]
for i in range(3, MAXFD):
try:
os.close(i)
except OSError:
pass
try:
os.execvp(cmd[0], cmd)
finally:
os._exit(1)

This is perfect behaviour as far as I'm concerned - if you pass a list
it doesn't go through the shell and if you pass a string it does.

eg

w, r = os.popen2(["ls", "-l"])
r.read()

This leads on to my questions :-

1) is this behaviour (string vs list) of popen2 intentional? Its not
documented anywhere and it doesn't work under Windows (gives
"TypeError: popen2() argument 1 must be string, not list")

2) is there anything similar for os.popen() planned?

3) is there an equivalent to the perl quotemeta() command. This
quotes meta-characters in a string for use in the shell. Here is a
suitable definition for Unix, but I don't think that \ quoting works
in Windows

cmd = re.sub(r"(\W)", r"\\\1", cmd)

Avoiding shell metacharacter attacks is a must for secure programs.
Python does pretty well with its os.exec* and os.spawn* functions, but
seems to be lacking in the os.popen* department!

Any insights appreciated!

--
Nick Craig-Wood <ni**@craig-wood.com> -- http://www.craig-wood.com/nick
Jul 18 '05 #1
10 2853
Nick Craig-Wood wrote:
Avoiding shell metacharacter attacks is a must for secure programs.


Not passing down commands into a shell is a must for secure programs.

What you should do is recognize a command, identify it as a
valid and allowed one, then call it yourself. If you think that
escaping metacharacters gives you any kind of security you are
deceiving yourself.

Istvan.
Jul 18 '05 #2
Istvan Albert <ia*****@mailblocks.com> wrote:
Nick Craig-Wood wrote:
Avoiding shell metacharacter attacks is a must for secure programs.
Not passing down commands into a shell is a must for secure programs.

What you should do is recognize a command, identify it as a
valid and allowed one, then call it yourself.


I'm not running commands passed by the user - that would be nuts!

I'm running another program written by us. The program doing the
running is a CGI and it needs to pass parameters to the second program
which come from the user. It also needs to read the output of that
program - hence popen.

What my post was about was avoiding the shell completely. If you use
os.system(string) then you go via the shell. However if you use
os.spawnl(mode, file, *args) then it doesn't go anywhere near the
shell. As I pointed out in my post there isn't an equivalent for
os.popen* which doesn't go via the shell (except for undocumented
os.popen2).
If you think that escaping metacharacters gives you any kind of
security you are deceiving yourself.


As a second best escaping the metacharacters and using os.popen will
work, but AFAICS there isn't a portable metacharacter escaping routine
built into python.

--
Nick Craig-Wood <ni**@craig-wood.com> -- http://www.craig-wood.com/nick
Jul 18 '05 #3
In article <sl*****************@irishsea.home.craig-wood.com>,
Nick Craig-Wood <ni**@craig-wood.com> wrote:
....
What my post was about was avoiding the shell completely. If you use
os.system(string) then you go via the shell. However if you use
os.spawnl(mode, file, *args) then it doesn't go anywhere near the
shell. As I pointed out in my post there isn't an equivalent for
os.popen* which doesn't go via the shell (except for undocumented
os.popen2).


Well, it sounded to me like the real problem is that Microsoft
Windows doesn't support any functional equivalent to spawnv
for pipes. I don't know if that's true or not, I'm just
taking it from you that os.popen2 doesn't support a list of
parameters [1] on Microsoft Windows platforms, and inferring
that it doesn't because it can't - there isn't any specific
function that does it, and you can't just roll your own out
of pipe/fork/execve like you can on UNIX, as in fact popen2 does.

If that's really a question and not a well known fact, you
might pose it again with a subject line that would attract
more attention from Microsoft Windows developers, since
only they would know. The attempt to cast it as a general
Python problem could be counterproductive, if it means the
people who read about this problem tend to be those who
don't really suffer from it.

Donn Cave, do**@u.washington.edu
Jul 18 '05 #4
Nick Craig-Wood wrote:
As I pointed out in my post there isn't an equivalent for
os.popen* which doesn't go via the shell (except for undocumented
os.popen2).


Is it the undocumented nature of it that is unnerving you?

I submitted a bug on the documentation more than six months ago but no
one has responded.

http://sourceforge.net/tracker/?func...70&atid=105470
--
Michael Hoffman
Jul 18 '05 #5
Michael Hoffman <m.*********************************@example.com > wrote:
Nick Craig-Wood wrote:
As I pointed out in my post there isn't an equivalent for
os.popen* which doesn't go via the shell (except for undocumented
os.popen2).
Is it the undocumented nature of it that is unnerving you?


Yes! If it was documented then it would have to be made to work on
Windows too I gues.
I submitted a bug on the documentation more than six months ago but no
one has responded.

http://sourceforge.net/tracker/?func...70&atid=105470


At least it is in the system.

--
Nick Craig-Wood <ni**@craig-wood.com> -- http://www.craig-wood.com/nick
Jul 18 '05 #6
Donn Cave <do**@u.washington.edu> wrote:
Well, it sounded to me like the real problem is that Microsoft
Windows doesn't support any functional equivalent to spawnv for
pipes. I don't know if that's true or not,
No me neither!
I'm just taking it from you that os.popen2 doesn't support a list
of parameters [1] on Microsoft Windows platforms,
Well it didn't work when I tried it.
and inferring that it doesn't because it can't - there isn't any
specific function that does it, and you can't just roll your own
out of pipe/fork/execve like you can on UNIX, as in fact popen2
does.
It could always do " ".join(cmd) which would leave windows users
exactly where they are at the moment.

I'll probably end up writing a little wrapper to popen2 which does
something like that, possibly with a bit better quoting for windows.
If that's really a question and not a well known fact, you
might pose it again with a subject line that would attract
more attention from Microsoft Windows developers, since
only they would know. The attempt to cast it as a general
Python problem could be counterproductive, if it means the
people who read about this problem tend to be those who
don't really suffer from it.


Good point. I'll have a think about it (and a look at the Windows
source of popen2!)

--
Nick Craig-Wood <ni**@craig-wood.com> -- http://www.craig-wood.com/nick
Jul 18 '05 #7
Nick Craig-Wood <ni**@craig-wood.com> writes:
Michael Hoffman <m.*********************************@example.com > wrote:
Nick Craig-Wood wrote:
As I pointed out in my post there isn't an equivalent for
os.popen* which doesn't go via the shell (except for undocumented
os.popen2).
Is it the undocumented nature of it that is unnerving you?


Yes! If it was documented then it would have to be made to work on
Windows too I gues.


I think this might be part of the reason it's underdocumented. I also
have a sneaking suspicion it's impossible on windows, but don't really
know...

Cheers,
mwh

-- Why are we talking about bricks and concrete in a lisp newsgroup?

After long experiment it was found preferable to talking about why
Lisp is slower than C++...
-- Duane Rettig & Tim Bradshaw, comp.lang.lisp
Jul 18 '05 #8
Nick Craig-Wood wrote:
I'm trying to avoid using shell metacharacters in os.popen in a portable
fashion.

os.popen() only seems to take a string as the command which would need
tricky quoting.

os.popen2() can take a string or a list - the relevant code in Unix
python (in popen2.py) being...

def _run_child(self, cmd):
if isinstance(cmd, basestring):
cmd = ['/bin/sh', '-c', cmd]
for i in range(3, MAXFD):
try:
os.close(i)
except OSError:
pass
try:
os.execvp(cmd[0], cmd)
finally:
os._exit(1)

This is perfect behaviour as far as I'm concerned - if you pass a list
it doesn't go through the shell and if you pass a string it does.

eg

w, r = os.popen2(["ls", "-l"])
r.read()

This leads on to my questions :-

1) is this behaviour (string vs list) of popen2 intentional? Its not
documented anywhere and it doesn't work under Windows (gives
"TypeError: popen2() argument 1 must be string, not list")

2) is there anything similar for os.popen() planned?

3) is there an equivalent to the perl quotemeta() command. This
quotes meta-characters in a string for use in the shell. Here is a
suitable definition for Unix, but I don't think that \ quoting works
in Windows

cmd = re.sub(r"(\W)", r"\\\1", cmd)

Avoiding shell metacharacter attacks is a must for secure programs.
Python does pretty well with its os.exec* and os.spawn* functions, but
seems to be lacking in the os.popen* department!

Any insights appreciated!


I can't exactly remember the details but I now I've had painful
experiences on Windows trying to do this kind of thing. It seems to mess
up quoting parameters / exe file names

David
Jul 18 '05 #9
David Fraser <da****@sjsoft.com> wrote:
Nick Craig-Wood wrote:
3) is there an equivalent to the perl quotemeta() command. This
quotes meta-characters in a string for use in the shell. Here is a
suitable definition for Unix, but I don't think that \ quoting works
in Windows

cmd = re.sub(r"(\W)", r"\\\1", cmd)


I can't exactly remember the details but I now I've had painful
experiences on Windows trying to do this kind of thing. It seems to mess
up quoting parameters / exe file names


Last time I did this for Windows was in C (urk!). I put every
parameter in double quotes and then doubled up any " in the parameter.
This worked mostly but I don't think the OS parsed some bizarre cases
properly.

--
Nick Craig-Wood <ni**@craig-wood.com> -- http://www.craig-wood.com/nick
Jul 18 '05 #10
Nick Craig-Wood wrote:
David Fraser <da****@sjsoft.com> wrote:
Nick Craig-Wood wrote:
3) is there an equivalent to the perl quotemeta() command. This
quotes meta-characters in a string for use in the shell. Here is a
suitable definition for Unix, but I don't think that \ quoting works
in Windows

cmd = re.sub(r"(\W)", r"\\\1", cmd)


I can't exactly remember the details but I now I've had painful
experiences on Windows trying to do this kind of thing. It seems to mess
up quoting parameters / exe file names

Last time I did this for Windows was in C (urk!). I put every
parameter in double quotes and then doubled up any " in the parameter.
This worked mostly but I don't think the OS parsed some bizarre cases
properly.

If I recall correctly (yikes) the problem was that Python's os.system
would handle either a program name with spaces in it or a parameter with
spaces in it, but quoting them both didn't work. Anyway if someone can
get it to work nicely please post the details here :-)

David
Jul 18 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: km | last post by:
hi all, can any linux command be invoked/ executed without using shell (bash) ? what abt security concerns ? regards, KM
0
by: Tom Brown | last post by:
I need to chain together three linux commands and get the final output. I read the documentation for Popen in the subprocess module for replacing the shell pipe line. I followed the example and...
4
by: jelle | last post by:
Hi, I use python quite a bit to couple different programs together. Doing so has been a _lot_ easier since subprocess came around, but would really like to be able to use the succinct shell...
2
by: Jeremy Moles | last post by:
I'm not sure if this is really the right place to ask this question, but since the implementation is in Python, I figured I'd give it a shot. I want to "wrap" a shell process using popen inside...
7
by: Bin Chen | last post by:
Hi, I want to do following: get a user input regex, then pass this as a parameter to grep, and then get the result from grep. Any code snip to implement the similar function? I am a python...
3
by: metaperl | last post by:
I downloaded a file which has a space in the filename. I want to run a shell unzip on it, but it fails in my current code: syscmd = "cd %s ; unzip %s" % (self.storage.input, file.basename())...
2
by: Gerard Flanagan | last post by:
Hello, I have a third party shell script which updates multiple environment values, and I want to investigate (and ultimately capture to python) the environment state after the script has run....
3
by: George Sakkis | last post by:
I'm trying to figure out why Popen captures the stderr of a specific command when it runs through the shell but not without it. IOW: cmd = if 1: # this captures both stdout and stderr as...
7
by: Samuel A. Falvo II | last post by:
I have a shell script script.sh that launches a Java process in the background using the &-operator, like so: #!/bin/bash java ... arguments here ... & In my Python code, I want to invoke...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.