Friday, August 30, 2013

Nice web server you got there. Be a shame if anything happened to it.

The Gaijin email to point out this reddit thread on the best way to code PHP to let remote web suers create new users (!) on the web server:
I have a form that creates a user by entering the username and their password. The code I'm using in php is:
shell_exec("sudo useradd -p $encpass -g groupname -s /bin/bash $username");
I have used a whoami and have confirmed that it runs as http. In /etc/sudoers I have
http ALL=(ALL) NOPASSWD: ALL
root ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
%sudo ALL=(ALL) ALL
I also added http to group wheel. The problem I am having is it's not setting the password correctly. The user is created, just the password isn't set. I know that $encpass has a value because I can display it. I also know the command works because it runs fine in command line. This was working before, but I had to reinstall Arch Linux, so does anyone have an idea for why this doesn't work?
Angels and Ministers of Grace, defend us ...

Since this is reddit, hilarity breaks out:
RichieSM 760 points  ago
This is some of the most dangerous code I've ever seen in my life.
[–]RichieSM 337 points  ago
I also added http to group wheel.
Are you actually serious?
[–]TheManCalledK 382 points  ago
Dude, obviously Apache needs root. How else is the web server supposed to take over?
I, for one, welcome our new Apache overlords.
[–]RommelTJ 133 points  ago
More like the Apache Trail of Tears.
For those not Linux heads, some of the more patient redditers explain it to Our Hero:
h2ooooooo 94 points  ago
If I actually said that my username is ; rm -rf /, then it'd first run the command
sudo useradd -p $encpass -g groupname -s /bin/bash (which would most likely fail)
and then run the following command:
rm -rf / which will delete your entire operating system (force remove files recursing through directories starting from the base of / (every file)). You might have to use sudo rm -rf /.
This all requires that $username and/or $encpass comes from the user in some way (through POST, GET, etc.).
You see, this is why we can't have nice things on the Internet.  Jimminy Cricket on a motorbike, this is maybe the most colossally boneheaded code I've ever seen.  And I've seen rather a lot, sad to say.  A number of the redditers accuse him of being a troll, but I think the query was legit.  After all, this sort of security fail is so epic that it has its very own xkcd:


Epic thread is epic.  Just know that code like this "escapes" into the wild, sometimes in production systems.  Be afraid.  Be very afraid.


8 comments:

Tango said...

Mother of God.... I can't imagine what the hell he was thinking? Who told him that it would be a good idea in the first place? That right there is the sold reason I don't like products like Webmin.

R.K. Brumbelow said...

Wait! You mean you are not supposed to run arbitrary code as a super user?

I used to be amazed at epic failure, now I just assume it is par for the course. I remember when globals were depreciated (thank the Universal Programmer[God]) we had all kinds of people on the old Mac PHP Development and Support forums (Marc Lyanage's before he went to work at Apple. We (Marc and I) went almost bonkers with all the people claiming PHP got broken and wanted to know how to re-enable globals or would call scripts using dodgy code. Oh those were fun days.

Opinionated Grump (Rich in NC) said...

... a little knowledge is a dangerous thing
no?
Rich in NC

Dave H said...

That's one of the things I hate about working with inexperienced programmers (and some experienced ones - usually contractors). They code like they're the only person on the project, and they'll be the only user.

I try to program the same way I ride my motorcycle: I assume that everyone -and- my equipment are all trying to kill me.

Tango said...

Hope for the best, prepare for the worst.

lelnet said...

The fun part is that, even if used exactly as intended and never noticed by someone with a heart of evil (or even just a mean-spirited practical joker), it _won't work_. (The argument for a -p option in useradd will inevitably contain embedded "$" characters, which when left unescaped, as this code does, the subshell will try to interpret as interpolated variables, leading to the actual entry in the shadow file being misformatted and not working properly.)

Also, everything the reddit people said. And everything Borepatch said.

Also, DON'T EVER DO THIS!

No, I don't mean "don't do it this way, do it some safer way, that sanitizes the inputs coming from the web before feeding them to 'sudo useradd' as arguments. I mean literally "DON'T FSCKING _DO_ THIS!" The very CONCEPT of creating new system users from a web-facing PHP script is INTRINSICALLY UNSAFE, no matter how well you sanitize! The fact that you're doing it BADLY is almost COMPLETELY FSCKING IRRELEVANT next to the fact that you're trying to do it AT ALL!!!

In a script like this, "sanitize your inputs" sounds like trying to persuade someone to be sure to wear his seatbelt when he DRIVES HIS CAR OFF A CLIFF.

Gah! So much stupid, and ammo is still too expensive. *sigh*

lelnet said...
This comment has been removed by the author.
lelnet said...

(Sorry about the double-post, there. Not sure how that happened.)