Skip Menu |

This queue is for tickets about the Pod-Perldoc CPAN distribution.

Report information
The Basics
Id: 87837
Status: resolved
Priority: 0/
Queue: Pod-Perldoc

People
Owner: Nobody in particular
Requestors: KENTNL [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in:
  • 3.20
  • 3.25
Fixed in: (no value)



Subject: perldoc should not always drop privs when UID=0

Granted the "drop privs" thing may be well intentioned, but there's no adequate description of the exact security risk dropping privs serves to achieve protecting against.

Additionally, there are usage case for perldoc where "UID=0" is *required*, and dropping privs just causes problems.

For instance, if you try to use perldoc -d $FILE as UID=0,  perldoc will likely be unable to write to $FILE if only UID=0 can write to it.

https://gist.github.com/kentfredric/6227848

And its quite plausible that root may want to use perldoc to do something useful, and other software, such as Parrot, use perldoc to format POD to text files.

In one instance, Parrot calls 'perldoc' to format documentation during `make install`, and as `make install` frequently *REQUIRES* running as root, which means perldoc drops privs.

One work-around people use for this problem is shell > redirection, but that doesn't work on win32, so parrot has to use -d

https://github.com/parrot/parrot/issues/520


TL;DR  -

1. The security risk is not obvious
2. Would be nice to have a way to go "Ok, I don't care about the security, I'm a grown up" at the very least.


 

On Tue Aug 13 23:54:35 2013, KENTNL wrote: Show quoted text
> 1. The security risk is not obvious
There are tons of security risks running perl setuid which are detailed pretty well in perlsec http://perldoc.perl.org/perlsec.html. In addition, perldoc responds to many different command names (as a historical curiosity partly) See https://github.com/mrallen1/Pod-Perldoc/blob/master/lib/Pod/Perldoc.pm#L323-L386 and it uses untainting pervasively throughout the codebase. Show quoted text
> 2. Would be nice to have a way to go "Ok, I don't care about the > security, I'm a grown up" at the very least.
I guess it would be possible to add a patch to *not* drop the setuid bits, but I don't think its going to solve the problem with parrot. IMO, the pattern would be # perldoc -d /tmp/foo.txt foo.pod and then later, # mv /tmp/foo.txt /final/place/in/my/path totally external to perldoc. Cheers, Mark

On 2013-08-15 03:00:01, mallen wrote:
> On Tue Aug 13 23:54:35 2013, KENTNL wrote:
> > 1. The security risk is not obvious
>
> There are tons of security risks running perl setuid which are
> detailed pretty well in perlsec http://perldoc.perl.org/perlsec.html.
>
I think my question is more "What security risks exist specific are there that are specific to perldoc".

If you're arguing there's security risks in general from running perl as root, or running perl setuid, sure, I can't argue that, ... but if we wanted to "solve" that, perl itself would have to tell every user who ran it for *any* reason, "No, you may not run Perl as root, its too insecure"  =)

Now if you're arguing about /setuid/ perl, ie: a perl that runs as root when called by a user as a result of filesystem bits that cause it to escalate privelage, thats a security risk, but thats a security risk for *every* perl program that is installed setuid.

In our problem scenario, the code is not being installed/run as *setuid*, it is merely running normally as root.

However, if a root user wants to do "perl -E"system(q[rm -rf /])", thats their problem. We dont' bar them from running perl simply because they're root =).

> > In addition, perldoc responds to many different command names (as a
> historical curiosity partly)
>
> See https://github.com/mrallen1/Pod-
> Perldoc/blob/master/lib/Pod/Perldoc.pm#L323-L386
>
> and it uses untainting pervasively throughout the codebase.
>

This, in itself, is not a security hole. No more than bash can cause gross damage if root invokes commands that do gross damage. The security hole is when root is tricked into doing insecure things they didn't intend on.

> > 2. Would be nice to have a way to go "Ok, I don't care about the
> > security, I'm a grown up" at the very least.
>
> I guess it would be possible to add a patch to *not* drop the setuid
> bits, but I don't think its going to
> solve the problem with parrot. IMO, the pattern would be
>
> # perldoc -d /tmp/foo.txt foo.pod
>
> and then later,
>
> # mv /tmp/foo.txt /final/place/in/my/path
>
> totally external to perldoc.
>

Thats the problem here though, it *is* doing perldoc -d ./target ./source and it *is* later moving the files to the final place.

However, ./ is controlled, and owned, and readable and writeable only by the user who created it: Root.
So when perldoc drops root, even though its install target is not the "OS", dropping privs means it can't write to any directory at all, because it can *ONLY* write to directories that are writeable by UID=nobody

And that *is* a potential security hole that is being introduced, because it means you have to make the directory writeable either by a) UID=nobody  and UID=nobody *only* in *advance*, or you have to make the directory +RW to everyone. And both those scenarios create a directory, which a well timed attack could conceivably add their own files to that tree, which might be accidentally installed to the final system.

Just to clarify, I'm not so much nessecarily asking you to fix this /for/ parrot. That ship has sailed and parrot will have to find a workaround, though it would be nice if there was just a flag that controlled whether or not to drop privs, or a flag that specified what priv to drop to.  ( And additionally, here, the problem with parrot is a problem with their tool-chaining, because "make install" should not be building documentation, it should just be installing it ).

Just when I encountered this bug(or misfeature), it was confusing as hell, because the vast majority of commandline tools don't drop privs, and debugging the cause of the read/write failure was rather challenging, because you're not expecting something like

gzcat foo -o bar # to die with a permissions problem when you are root, unless the filesystem is broken  =)

 

On Tue Aug 13 23:54:35 2013, KENTNL wrote: Show quoted text
> Granted the "drop privs" thing may be well intentioned, but there's no > adequate > description of the exact security risk dropping privs serves to > achieve > protecting against. > > Additionally, there are usage case for perldoc where "UID=0" is > *required*, and > dropping privs just causes problems. > > For instance, if you try to use perldoc -d $FILE as UID=0, perldoc > will likely > be unable to write to $FILE if only UID=0 can write to it. > > https://gist.github.com/kentfredric/6227848 > > And its quite plausible that root may want to use perldoc to do > something > useful, and other software, such as Parrot, use perldoc to format POD > to text > files. > > In one instance, Parrot calls 'perldoc' to format documentation during > `make > install`, and as `make install` frequently *REQUIRES* running as root, > which > means perldoc drops privs. > > One work-around people use for this problem is shell > redirection, > but that > doesn't work on win32, so parrot has to use -d > > https://github.com/parrot/parrot/issues/520 >
I can only agree, this behavior is broken and stupid. Firstly because it doesn't seem to solve any problem. Perldoc is to show code, not to execute it. Secondly, the logic that triggers it is idiotic. «if (($< == 0 || $> == 0) && !tainted($ENV{WHATEVER}))». So apparently you can actually disable this behavior by adding a -T to the perldoc shebang line. This "security feature" gets disabled if you ask for more security. WTF! Thirdly, because it doesn't always work. The way the permissions are dropped is broken, wrong and silly. Bashing at $< and $> until hopefully all UIDs have the right value? Even if you know it sometimes doesn't work? And after all that hard work, continue (admittedly with a warning) even if it failed? And not paying any attention to GIDs? POSIX::set[ug]id would have fixed that more easily. Show quoted text
> 2. Would be nice to have a way to go "Ok, I don't care about the > security, I'm > a grown up" at the very least.
There used to be a -U flag once upon a time, it seems to have been removed in 3.09. Leon
On Thu Oct 24 12:30:47 2013, LEONT wrote: Show quoted text
> There used to be a -U flag once upon a time, it seems to have been > removed in 3.09.
I added it back. Committed as 89f3df0. (Not pushed yet.) Will that meet your needs?

On 2014-01-31 17:07:52, mallen wrote:
> On Thu Oct 24 12:30:47 2013, LEONT wrote:
> > There used to be a -U flag once upon a time, it seems to have been
> > removed in 3.09.
>
> I added it back. Committed as 89f3df0. (Not pushed yet.) Will that
> meet your needs?

Yeah. I would consider that a helpful addition.

On security: I'd have to make sure there's no way for some ambient env/configuration toggling that flag and was only accepted on the CLI.

 

With regards to the original parrot problem, I've worked around it downstream with this patch, because for what Parrot is doing, it doesn't need most of the features anyway, and its just using perldoc as a simple pod extractor.

 

https://github.com/parrot/parrot/pull/1028/files

I agree with kentnl and leont that the drop privs logic seems to be an un-feature. I ran into it while trying to figure out why -F wasn't working for me, which led to a debug/trace, at which point I discovered -U (undocumented) and this ticket via a git blame. In lieu of killing this drop privs stuff altogether (which would be my vote) the -U option at least needs to be documented. That would have saved me an hour of debugging. Also, it seems to me that -F is basically non-functional without -U, so I think it makes sense to make -U implied with -F. I've opened a PR to address both: https://github.com/mrallen1/Pod-Perldoc/pull/14
On Sat Mar 14 06:18:55 2015, VANSTYN wrote: Show quoted text
So this got merged a long time ago and it was marked as broken in 3.25. Would you please explain what is still broken? Was the previous patch not effective?