So, is it enough to just purge any single quotes from str, before constructing buffer? (Assuming, as is the case, that single quote should
not ever occur in valid data).
The idea is that you have a string (say "str") that comes from outside (so
is not trusted) and you want to pass it as an argument to a program, via popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single quote. The problem is if str contains something like: foo';rm -rf $HOME;echo 'ha! ha!
so you end up with: program 'foo';rm -rf $HOME;echo 'ha! ha!'
So, is it enough to just purge any single quotes from str, before constructing buffer? (Assuming, as is the case, that single quote should
not ever occur in valid data).
sprintf(buffer,"program '%s'",str);
The idea is that you have a string (say "str") that comes from outside (so
is not trusted) and you want to pass it as an argument to a program, via >popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single quote. The >problem is if str contains something like: foo';rm -rf $HOME;echo 'ha! ha!
so you end up with: program 'foo';rm -rf $HOME;echo 'ha! ha!'
So, is it enough to just purge any single quotes from str, before >constructing buffer? (Assuming, as is the case, that single quote should
not ever occur in valid data).
gazelle@shell.xmission.com (Kenny McCormack) writes:
The idea is that you have a string (say "str") that comes from outside (so >is not trusted) and you want to pass it as an argument to a program, via >popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single quote. The >problem is if str contains something like: foo';rm -rf $HOME;echo 'ha! ha! >so you end up with: program 'foo';rm -rf $HOME;echo 'ha! ha!'
So, is it enough to just purge any single quotes from str, before >constructing buffer? (Assuming, as is the case, that single quote should >not ever occur in valid data).
No. It's not enough. You also need to remove grave accents, all
command substitution $(command) and variable substitution ${VARIABLE}
and all file redirection, amongst other things.
The idea is that you have a string (say "str") that comes from
outside (so is not trusted) and you want to pass it as an argument
to a program, via popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single
quote. The problem is if str contains something like:
foo';rm -rf $HOME;echo 'ha! ha!
so you end up with:
program 'foo';rm -rf $HOME;echo 'ha! ha!'
So, is it enough to just purge any single quotes from str, before constructing buffer? (Assuming, as is the case, that single quote
should not ever occur in valid data).
Can you give an example of what bad could happen if there is a trailing backslash?
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from >the untrusted source. Within single quotes , command substitutions , variable >substitutions and file redirections do not happen. But %s may end in a >backslash so this needs to be taken into account.
On Sat, 23 Jan 2021 19:18:51 -0500, Kenny McCormack <gazelle@shell.xmission.com> wrote:
Can you give an example of what bad could happen if there is a
trailing backslash?
The untrusted source could append a command string such as "; rm -rf
~/" (without the double quotes).
In article <asamiya-saki@bongo-ra.co>,
Spiros Bousbouras <spibou@gmail.com> wrote:
...
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from
the untrusted source. Within single quotes , command substitutions , variable >>substitutions and file redirections do not happen. But %s may end in a >>backslash so this needs to be taken into account.
You are of course correct that inside single quotes, none of those other characters matter. The only thing that's magic is the single quote.
Can you give an example of what bad could happen if there is a trailing backslash?
On Sun, 24 Jan 2021 00:18:51 -0000 (UTC)
gazelle@shell.xmission.com (Kenny McCormack) wrote:
In article <asamiya-saki@bongo-ra.co>,
Spiros Bousbouras <spibou@gmail.com> wrote:
...
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from
the untrusted source. Within single quotes , command substitutions , variable
substitutions and file redirections do not happen. But %s may end in a >backslash so this needs to be taken into account.
You are of course correct that inside single quotes, none of those other characters matter. The only thing that's magic is the single quote.
Can you give an example of what bad could happen if there is a trailing backslash?
On further thought , nothing. I had forgotten that backslash has no special meaning inside single quotes.
Remember: I don't care if bad input generates a garbage result. GIGO as they say. I just don't want anything evil to happen.
But I realised that the addition of single quotes can cause problems. If for example the user enters
echo Hello world
, with your addition of single quotes the shell will see 'echo Hello world' i.e. it would be as if typing on the command line
'echo Hello world'
and the shell will generate an error message that there is no such command whereas the user (of your programme) entered a valid command.
In article <asamiya-saki@bongo-ra.co>,
Spiros Bousbouras <spibou@gmail.com> wrote:
...
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from
the untrusted source. Within single quotes , command substitutions , variable
substitutions and file redirections do not happen. But %s may end in a >backslash so this needs to be taken into account.
You are of course correct that inside single quotes, none of those other characters matter. The only thing that's magic is the single quote.
Can you give an example of what bad could happen if there is a trailing backslash?
Remember: I don't care if bad input generates a garbage result. GIGO as
they say. I just don't want anything evil to happen.
But I realised that the addition of single quotes can cause problems. If for >example the user enters
echo Hello world
, with your addition of single quotes the shell will see 'echo Hello world' >i.e. it would be as if typing on the command line
'echo Hello world'
and the shell will generate an error message that there is no such command >whereas the user (of your programme) entered a valid command.
Correct grammar is classist.
So, is it enough to just purge any single quotes from str, before
constructing buffer? (Assuming, as is the case, that single quote
should not ever occur in valid data).
It's not enough, it's the wrong direction. Single quotes should be
added to str rather than purged from:
On Sat, 23 Jan 2021 21:39:44 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
gazelle@shell.xmission.com (Kenny McCormack) writes:
The idea is that you have a string (say "str") that comes from outside (so >> >is not trusted) and you want to pass it as an argument to a program, via
popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single quote. The >> >problem is if str contains something like: foo';rm -rf $HOME;echo 'ha! ha! >> >so you end up with: program 'foo';rm -rf $HOME;echo 'ha! ha!'
So, is it enough to just purge any single quotes from str, before
constructing buffer? (Assuming, as is the case, that single quote should >> >not ever occur in valid data).
No. It's not enough. You also need to remove grave accents, all
command substitution $(command) and variable substitution ${VARIABLE}
and all file redirection, amongst other things.
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from
the untrusted source. Within single quotes , command substitutions , variable substitutions and file redirections do not happen. But %s may end in a backslash so this needs to be taken into account.
Overall, it seems easier to me to call one of the exec* functions
directly and arrange the appropriate redirections instead of doing
it through popen() and worry about sanitising the input.
That is indeed what I do. Why roundtrip through the shell, if all
features it adds are features that I don't want, and that I have to
defend my data against, using ill-defined strategies?
The only reason is that's the widely available interface.
Jorgen Grahn , dans le message <slrns0rgp3.2ptb.grahn+nntp@frailea.sa.invalid>, a écrit :
That is indeed what I do. Why roundtrip through the shell, if all
features it adds are features that I don't want, and that I have to
defend my data against, using ill-defined strategies?
The only reason is that's the widely available interface.
Using the shell can also be a good idea to allow user-configurable commands.
The only reason is that's the widely available interface.
And that's, as I understand it, the story behind SQL injection
attacks, too.
On 24 Jan 2021 18:57:39 GMT
Jorgen Grahn <grahn+nntp@snipabacken.se> wrote:
The only reason is that's the widely available interface.
And that's, as I understand it, the story behind SQL injection
attacks, too.
SQL injection is universally the product of poor design choices.
On Sat, 23 Jan 2021 21:39:44 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
gazelle@shell.xmission.com (Kenny McCormack) writes:
The idea is that you have a string (say "str") that comes from outside (so >> >is not trusted) and you want to pass it as an argument to a program, via
popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single quote.
No. It's not enough. You also need to remove grave accents, all
command substitution $(command) and variable substitution ${VARIABLE}
and all file redirection, amongst other things.
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from
the untrusted source. Within single quotes , command substitutions , variable substitutions and file redirections do not happen. But %s may end in a backslash so this needs to be taken into account. Overall , it seems easier to me to call one of the exec* functions directly and arrange the appropriate
redirections instead of doing it through popen() and worry about sanitising the input.
Never suggest a simple, correct solution if there's a complicated,
incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
Spiros Bousbouras <spibou@gmail.com> writes:
On Sat, 23 Jan 2021 21:39:44 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
gazelle@shell.xmission.com (Kenny McCormack) writes:
The idea is that you have a string (say "str") that comes from outside (so >>>> is not trusted) and you want to pass it as an argument to a program, via >>>> popen(). So, you do something like:
sprintf(buffer,"program '%s'",str);
fp = popen(buffer, "r");
and this is peachy keen as long as str doesn't contain a single quote.
[...]
No. It's not enough. You also need to remove grave accents, all
command substitution $(command) and variable substitution ${VARIABLE}
and all file redirection, amongst other things.
Why ? popen() will call /bin/sh -c '%s' where %s is what was passed from
the untrusted source. Within single quotes , command substitutions , variable
substitutions and file redirections do not happen. But %s may end in a
backslash so this needs to be taken into account. Overall , it seems easier >> to me to call one of the exec* functions directly and arrange the appropriate
redirections instead of doing it through popen() and worry about sanitising
the input.
Never suggest a simple, correct solution if there's a complicated,
incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
:-))
Rainer Weikusat <rweikusat@talktalk.net> wrote:
...
Never suggest a simple, correct solution if there's a complicated, >>incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
Not to disagree with your basic thrust, but in this case, I think we've
shown pretty conclusively that as long as you handle (one way or the other) the single quote, you're OK.
On 27.01.2021 00:12, Rainer Weikusat wrote:
Never suggest a simple, correct solution if there's a complicated,
incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
:-))
Well, to be fair, the popen() interface is simple, and that is what
makes it appealing to use it (instead of a in comparison complex
exec-based approach with all that you need there).
Janis Papanagnou <janis_papanagnou@hotmail.com> writes:
On 27.01.2021 00:12, Rainer Weikusat wrote:
[popen with untrusted arguments]
Never suggest a simple, correct solution if there's a complicated,
incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
:-))
Well, to be fair, the popen() interface is simple, and that is what
makes it appealing to use it (instead of a in comparison complex
exec-based approach with all that you need there).
I don't think there's anything particularly complex in the code below.
------
#include <stdio.h>
#include <unistd.h>
static FILE *open_ls(char **argv)
{
int fds[2];
pipe(fds);
if (fork() == 0) {
close(*fds);
dup2(fds[1], 1);
*argv = "ls";
execvp("ls", argv);
}
close(fds[1]);
return fdopen(*fds, "r");
}
int main(int argc, char **argv)
{
char buf[4096];
FILE *fp;
fp = open_ls(argv);
while (fgets(buf, sizeof(buf), fp)) fputs(buf, stdout);
return 0;
}
On 28.01.2021 16:11, Rainer Weikusat wrote:
Janis Papanagnou <janis_papanagnou@hotmail.com> writes:
On 27.01.2021 00:12, Rainer Weikusat wrote:
[popen with untrusted arguments]
Never suggest a simple, correct solution if there's a complicated,
incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
:-))
Well, to be fair, the popen() interface is simple, and that is what
makes it appealing to use it (instead of a in comparison complex
exec-based approach with all that you need there).
I don't think there's anything particularly complex in the code below.
I didn't say it's "particularly complex", I said that popen() is simple
(and implying its use is [much] simpler that a fork/exec/dup2 etc.) and
thus appealing. - Don't you agree?
Janis Papanagnou <janis_papanagnou@hotmail.com> writes:
On 28.01.2021 16:11, Rainer Weikusat wrote:
Janis Papanagnou <janis_papanagnou@hotmail.com> writes:
On 27.01.2021 00:12, Rainer Weikusat wrote:
[popen with untrusted arguments]
Never suggest a simple, correct solution if there's a complicated,
incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
Well, to be fair, the popen() interface is simple, and that is what
makes it appealing to use it (instead of a in comparison complex
exec-based approach with all that you need there).
I don't think there's anything particularly complex in the code below.
I didn't say it's "particularly complex", I said that popen() is simple
(and implying its use is [much] simpler that a fork/exec/dup2 etc.) and
thus appealing. - Don't you agree?
No. Something which enables "saving" <20 lines of code is not worth any effort of supporting it, especially not when it's murkily designed[*] and
has a history of causing problems.
Popen() only gets complicated if you try to fix the inherent
security issues.
[*] There's a so-called "least privilege principle" supposed to apply to security/ safety critical code. Invoking the shell just to execute
another program is the exact opposite of that: Everything and two
kitchen sinks just to make sure it can do anything someone could
conceivably ever need.
[code example in original post]
On 28.01.2021 17:36, Rainer Weikusat wrote:
Janis Papanagnou <janis_papanagnou@hotmail.com> writes:
On 28.01.2021 16:11, Rainer Weikusat wrote:
Janis Papanagnou <janis_papanagnou@hotmail.com> writes:
On 27.01.2021 00:12, Rainer Weikusat wrote:
[popen with untrusted arguments]
Never suggest a simple, correct solution if there's a complicated, >>>>>> incorrect one involving useless intermediate execution of
/bin/sh. Programmers just love to do that!
Well, to be fair, the popen() interface is simple, and that is what
makes it appealing to use it (instead of a in comparison complex
exec-based approach with all that you need there).
I don't think there's anything particularly complex in the code below.
I didn't say it's "particularly complex", I said that popen() is simple
(and implying its use is [much] simpler that a fork/exec/dup2 etc.) and
thus appealing. - Don't you agree?
No. Something which enables "saving" <20 lines of code is not worth any
effort of supporting it, especially not when it's murkily designed[*] and
has a history of causing problems.
It's not (not primary) a question of "saving lines"; it's also about
avoiding complexity. More code and higher complexity makes software
more error prone. Of course it is worth to support short solutions,
libraries and languages with a higher abstraction level (to produce
shorter code).
The "history of causing problems" is likely to be interpreted as the
already mentioned security issues, depending on how you use it. In my
post upthread I addressed this already, but you decided to not quote
it:
Popen() only gets complicated if you try to fix the inherent
security issues.
For the context of this thread, the OP has a well defined special
case of an application and requirements, and I don't seem to recall
any post that proved his use of popen() to have security issues.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 293 |
Nodes: | 16 (2 / 14) |
Uptime: | 237:22:03 |
Calls: | 6,624 |
Files: | 12,172 |
Messages: | 5,319,873 |