
How we broke PHP, hacked Pornhub and earned $20k - KngFant
https://www.evonide.com/how-we-broke-php-hacked-pornhub-and-earned-20000-dollar/
======
krapp
The takeway:

    
    
        You should never use user input on unserialize. Assuming that 
        using an up-to-date PHP version is enough to protect 
        unserialize in such scenarios is a bad idea. Avoid it or use 
        less complex serialization methods like JSON.

~~~
segmondy
Actually, the takeaway is not that "you should never use user input on
unserialize." It is, that you should NEVER TRUST USER INPUT. This rule is as
old as computing itself and trust of user input has always been the beginning
of a security vulnerability. You need user input, you will use user input, but
you must understand how it's used and filter, strip everything that is not
needed away.

~~~
codedokode
> you should NEVER TRUST USER INPUT

That is not clear at all and pretty useless. What does it mean? I should not
accept any user input at all?

> strip everything that is not needed

That does not always work. What if I have a comment form that should accept
any characters?

~~~
krapp
>What does it mean? I should not accept any user input at all?

No, it means you should never assume that user data is safe, or even sane.
Assume, rather, that everything every user is sending you is malicious, all
the time, and write your code accordingly.

>. What if I have a comment form that should accept any characters?

First, you probably shouldn't, because your database and HTML should be using
explicit character encodings, so a comment form that accepts _anything_
doesn't make a lot of sense. How are you expecting to _deal_ with "any
characters"? What happens when they paste in a binary blob, or javascript
code?

Secondly, assuming you want to do that, you still shouldn't _trust_ the data.
Add it to the database using parameterized queries, escape it when rendering,
never mix it in to javascript variables and never serialize it into a format
designed to unserialize executable objects.

It's not an unreasonable burden to expect web developers to at least be aware
and code defensively. _Especially_ with PHP.

~~~
dmix
> it means you should never assume that user data is safe, or even sane

I'm curious if Haskell's purity helps developers focus on this issue and
therefore makes it easier to mitigate. Given that all user input/state already
has to be handled carefully (for ex: with monads). It will be obvious in the
codebase which parts need to be zero'd in on for possible attack vectors.

~~~
MustardTiger
>I'm curious if Haskell's purity helps developers focus on this issue and
therefore makes it easier to mitigate

No, haskell's type system does, not its purity.

>Given that all user input/state already has to be handled carefully (for ex:
with monads)

What? Monads are not some mythical beast, there is nothing "handled carefully"
about it. A monad is just a general interface.

~~~
dmix
I'm talking about clear separation of state via Monads making it easier to
_focus_ on the riskier input. For example when you are doing code reviews.
That is about the developer nothing to do with some inherent functionality of
Monads. Not sure what it being a "general interface" has to do with that.
Maybe I wasn't clear.

~~~
MustardTiger
>Not sure what it being a "general interface" has to do with that

I was explaining what monads are. You have read some of the weird
misconceptions about haskell and monads and are now repeating them.

~~~
dmix
How does purity _not_ help the developer focus in on areas where user input
might have a negative affect the codebase or system?

I used monads only as an example (in brackets) but it's hardly the only form
where purity creates clear divisions in the codebase. So, once again, the
specific functionality of monads has nothing to do with it. I'm speaking about
the coding style that Haskell promotes making detecting bugs easier during
code reviews.

Having done security reviews of code I would have loved to have that type of
distinction exist in a codebase compared to the usual OOP mess (with PHP or
Ruby for example, which is typically the only paid work available in infosec)
where state/user input is leaking all over the place. Compared to clearly
defined paths containing IO - which are separated from pure functions which
don't have unexpected side effects and require far less scrutiny.

I'm answering my own question here but I was hoping someone who has more
experience than me at conducting security-centric code reviews would chime in
to provide their perspective.

~~~
MustardTiger
I don't know how to be any more clear. Monads are not an example, that is the
point. It is like saying in python "Given that all user input/state already
has to be handled carefully (for ex: with dictionaries)." It is nonsense.

------
danso
OT: Is there a site that curates these kinds of interestingly detailed hacks?
Like Dan Luu does for debugging stories?
([https://github.com/danluu/debugging-
stories](https://github.com/danluu/debugging-stories))

~~~
ssclafani
The r/netsec subreddit:
[https://www.reddit.com/r/netsec/top/?sort=top&t=all](https://www.reddit.com/r/netsec/top/?sort=top&t=all)

~~~
zaroth
Interestingly, I've noticed just about every well upvoted story on /r/netsec
will hit the HN front page 2-3 days later.

~~~
sbierwagen
Arbitrage opportunity there: submit them to HN yourself.

~~~
danso
I've been guilty of doing that before. Also, from top r/reverseengineering,
though that subreddit is a little less traveled so doesn't get as many
comments, so it's interesting to read what HNers think.

------
ckdarby
That moment when the company you work at is on the front page of Hacker News
xD

~~~
khoury
Seriously, please do an AMA. As a developer, I am very curious about how it
feels like working for a company like that :)

~~~
ymse
Some other Pornhubbers did one 2,5 years ago:
[https://www.reddit.com/r/IAmA/comments/1un3wn/we_are_the_por...](https://www.reddit.com/r/IAmA/comments/1un3wn/we_are_the_pornhub_team_ask_us_anything/)

------
watbe
This is an elaborate hack and a very detailed writeup. Thanks for sharing.

------
ndesaulniers
> Using a locally compiled version of PHP we scanned for good candidates for
> stack pivoting gadgets

Surprised that worked. Guess they got lucky and either got the
comiler+optization flags the same as the PHP binary used, or the release
process can create higly similar builds.

~~~
chatmasta
They mention that PH had a custom compiled PHP and that's why they couldn't
get the address of the function they wanted to call for evaluating code.

My understanding is that ROP gadgets are a separate issue. Basically you want
to find a function that compiles to assembly instructions resembling the ones
you need to move the stack pointer to your desired location. Testing this
locally shouldn't be a problem, because functions across builds will compile
to the same assembly instructions (even if their headers have different load
addresses).

Again, that's my understanding - I have a very vague grasp of this stuff.

------
aprdm
Really good write up. Some people are really smart, I wouldn't ever be able to
do that kind of stuff even after being programming for years.

~~~
i_am_cam
As well as being good, they'll also be very experienced. What you're seeing in
that post is specialised knowledge, likely built up over many years. We can't
all know everything, as much as we'd like to!

------
tjallingt
I have some questions about two things in the exploit code that puzzled me:

    
    
      my $php_code = 'eval(\'
         header("X-Accel-Buffering: no");
         header("Content-Encoding: none");
         header("Connection: close");
         error_reporting(0);
         echo file_get_contents("/etc/passwd");
         ob_end_flush();
         ob_flush();
         flush();
      \');';
    

1\. they seem to be using php to code the exploit (solely based on the $
before the variable name) but i've never seen the 'my' keyword before, what
exactly is this language?

2\. if i understand the exploit correctly they got remote code execution by
finding the pointer to 'zend_eval_string' and then feeding the above code into
it. doesn't that mean the use of 'eval' in the code that is being executed is
unnecessary?

~~~
anglebracket
>i've never seen the 'my' keyword before, what exactly is this language?

It's Perl:
[http://perldoc.perl.org/functions/my.html](http://perldoc.perl.org/functions/my.html)

------
Phithagoras
Appears to be experiencing the hug of death. May be quite slow

~~~
expression
I guess the site is served using PHP.

~~~
cocotino
That's funny because in my experience php is one of the fastest languages.

~~~
percept
FWIW, it places well across TechEmpower benchmarks:

[http://www.techempower.com/benchmarks/](http://www.techempower.com/benchmarks/)

~~~
jake_morrison
Raw PHP is reasonably fast. The performance issue comes with loading source
files on every request:
[http://talks.php.net/show/froscon08](http://talks.php.net/show/froscon08)

This means that there is a conflict between performance and having a well
structured object oriented framework.

Demand loaded classes and byte code help a lot with that:
[http://www.yiiframework.com/performance/](http://www.yiiframework.com/performance/)

Best would be a model where a persistent process handles multiple requests
concurrently, but that is not normal for PHP. So you need to make sure that
all the libraries you are using are not leaking, have a nice db connection
pool, and write a PHP framework that handles concurrency. Might as well use a
better language at that point :-)

~~~
toast0
> This means that there is a conflict between performance and having a well
> structured object oriented framework.

What do you need a 'well structured object oriented framework' for? You're
going to build up a huge object graph in memory, to output some HTML, and then
throw away all the objects at the end of the request. Nobody is going to see
your beautiful object tree, so don't bother. A blog entry page should be super
simple.

header, title, content, comments, recent comments, footer.

Header and footer are dead simple echos of the boilerplate, maybe replace in
the html title or something. Read the title and content from disk[1]. Have
another data file for all your articles for the index page.

I prefer not to have comments on my blog, but if you must, you can put them in
a database; limit to something like 100 or 1000 comments per article (because
really) and limit threading, and it's going to be pretty quick to query them
(make sure your webserver is doing reads from a database in the same metro
area, if not on the same box).

Recent comments is across all blog entries; I would probably add a index on
the time in the comments table and just select 2 from there; you could union
that into the earlier comments query if you don't want to make two round trips
to the database.

You don't need to do this with concurrency, each page load has barely anything
to wait for, so more threads doesn't help throughput. Run enough php workers
(php-fpm, or apache children if you're using apache_mod_php) to keep your cpu
busy, and you're golden.

[1] There's four articles on this blog -- it doesn't need a database. PS run
php as a user that can't write anywhere on the disk, and push the blog entries
and the summary datafile with another user.

Edit to add: If you skip comments (or outsource to disqus or some other
comments w/ javascript platform), you can make the whole site just static
html, and leave PHP at home. OTOH, these guys are running Wordpress, because
they like frequent security updates?

------
cloudjacker
wow

From a legal perspective how do companies and hackerone create a binding
exemption from laws used to prosecute hackers?

~~~
Buge
In the US the law is against unauthorized access. If a company agrees to let
people try to hack their stuff, then the access is authorized and legal.

~~~
seanp2k2
To what extent? What if you do something on accident that ends up messing up
their stuff? Just the first example I can think of: you figure out a way to
reboot an instance which lets you exploit a race condition in some auth code,
and don't realize that the instance you're killing is critical for some other
function (let's say billing) and you end up causing some real monetary damage,
even though you had no idea.

Are there any legal precedents for this?

~~~
hueving
It's in the agreement with you and the company. Usually it says if you cause a
side effect like that you are at fault.

------
fencepost
So does Pornhub's bug bounty program include some number of years of free paid
membership along with financial bounties? Kind of a "treat us right and we'll
let you treat yourself right" kind of thing?

~~~
seanp2k2
If you know enough to be able to pull off hacks like this, you surely know
enough to get more of this kind of thing than you'd have time to watch in 10
lifetimes. I doubt that such a "reward" would be very appealing to those who
participate in the bug bounty program, and it'd honestly be a sleazy business
proposition, which would harm the professionalism of operating a successful
bug bounty program. And yes, I'm completely serious.

~~~
fencepost
I'm glad you were serious, because frankly I wasn't. I'm sure there's more
than enough "free" porn out there for just about anyone's taste, so I doubt
that free accounts would be a significant incentive anyway.

But meh, sometimes jokes fall flat.

------
given
Too bad they didn't just go ahead and:

> Dump the complete database of pornhub.com including all sensitive user
> information.

And of course leak the data to expose everyone that participates in this nasty
business. It is such a sad thing that people are even proud to work at
companies like this where humans are not worth more than a big dick or boobs.

And then you get around and say that child porn is so horrible. No, _all_ porn
is horrible and destroys our families and integrity. How can there be any
dignity left if these things are held to be something good?

~~~
Annatar
Righteous much? The most insidious prison one could ever be put into is the
arbitrary restriction in one's own mind. Luckily for the rest of us, we are in
the 21st century and most people are educated enough to not believe in
nonsense like witches any more. Pornography is heading in the same direction,
people are finally starting to realize that sexuality is part of one's natural
self. When you consider that each of us was born with a dick or tits, there is
nothing wrong by accepting that and getting turned on by appreciating the
aesthetics of it. It has been done since antiquity and even before that, and
then we regressed into the dark ages of morality. At the very least, it is
biology. Science? Yes please!

