473,624 Members | 2,154 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 2876
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*****@mailbl ocks.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(strin g) 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(strin g) 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 counterproducti ve, 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.washingt on.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.washing ton.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 counterproducti ve, 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

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

Similar topics

12
2117
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
1374
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 keep getting a 0 where I should be getting a 1. I am trying to do this: grep "Sep 22" /var/log/auth.log | grep "Illegal user" | wc -l which returns a 1 when I run this manually. This is what I did with python:
4
2616
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 syntax; >, <, | That really shouldn't be too hard to wrap in a class, but so far I didn't succeed to do so this well, since I'm facing some trouble with operator precedence that I do not know how to overcome.
2
3970
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 of python program rather than creating a new shell process for each line I process in the app. For example, the code might look like: std = stdin, stdout, stderr = os.popen3("bash")
7
2693
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 newbie. Thanks a lot. Bin
3
4788
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()) os.system(syscmd) because no escaping was done. Is there a more principled way to construct a shell command and execute
2
2841
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. But running the script as a child process only sets values for that process, which are lost after execution. So I thought I could simply tack on an 'env' command line to the script input lines as shown below. However, using subprocess.Popen gives...
3
3813
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 expected pipe = Popen(' '.join(cmd), shell=True, stderr=PIPE, stdout=PIPE) else: # this captures only stdout pipe = Popen(cmd, shell=False, stderr=PIPE, stdout=PIPE) # this prints the empty string if not run through the shell
7
6226
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 this shell script using the Subprocess module. Here is my code: def resultFromRunning_(command):
0
8234
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8172
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8677
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8620
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8335
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8474
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7158
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4079
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4174
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.