-
preroll music
-
Herald: And I'm gonna introduce Netanel Rubin.
-
He has been here last year with a talk
that he got some bashing for.
-
This year he's gonna ensure,
it's not the programmer's fault,
-
it's the language itself. No?
-
Well, here we go, well here we go.
-
Netanel, he is working for
PerimeterX in Tel Aviv,
-
welcome on stage, your talk!
-
Netanel: Thank you very much, applause
-
thank you, thank you!
-
Last year I stood right on this very stage
and I talked about several of Perl's
-
less thought out "features".
-
Now, I got some bashing from the Perl community,
but mainly what happened was,
-
that the Perl community completely rejected my talk
claiming that the language
-
is completely fine and great
and all of this stuff are just improvements.
-
It was clear I had to give another talk.
-
This is why I'm very proud to present
"Perl Jam 2 – The Camel strikes back"!
-
applause
-
Thank you
-
At the last talk, I showed that "lists" are expressions,
used in… many confusing ways.
-
I also showed how CGI parameters can create lists,
directly from user input.
-
But most importantly, I showed
that when these two things combine, shit happens.
-
Great
-
But the really interesting part
was the PerlMonks response.
-
The Perl community…
laughter
-
The Perl community had a long discussion
at the PerlMonks forum
-
that started with the words
"Sad news from Germany".
-
A bit dramatic, but who am I to judge?
-
So, after a long, long discussion,
they came to the unavoidable conclusion
-
that my talk was, in fact, a "polemic shit",
and they should all just "piss on it". Wink.
-
They also realized I'm just a
"script kiddie preaching to other script kiddies",
-
and not just any script kiddies, the CCC audience is a
-
"heterogeneous group of chaotic punks
who love to see themselves in the hacker
-
image of Hollywood media".
applause and whistling from audience
-
What hacker image?
What are they talking about?
-
We have no hacker image.
-
Anyway, it got quite surreal, as in some point
they even critized
-
the "crude use of propaganda
in the camel images". WAT?
-
laughing
applause
-
Propaganda in the camel images. Alright.
-
Anyway, they completely rejected the entire talk,
even though the technical points were valid.
-
They rejected it because of
some jokes and camel images.
-
But still, they got so offended they just threw
lame excuses as to why their language sucks.
-
Two of these lame excuses were
repeated over and over again.
-
The first was that I should
read the fucking manual, which is funny
-
because I thought I was the only one who did…
-
laughter
-
…and the second is that
-
I'm using the old, ancient Perl,
and not the new, modern Perl.
-
more laughter
-
Remember these two points carefully
as I'll later break them in the presentation.
-
But, enough with the intro,
let's start with the new madness.
-
So, Perl allows declaring variables
without specifying their data type.
-
Of course, this functionality exists
in many dynamic languages,
-
and is completely fine and very convenient.
-
But, as usual, Perl took it
to a whole different level.
-
Perl went as far as removing
data type declarations from function arguments.
-
You can see that in this example,
-
I'm just receiving two different arguments
without knowing what type they are.
-
Let me be clear about that,
-
you don't get to choose whether you want
to specify argument data types or not,
-
you can't specify
what data types you're expecting to get.
-
So even if I built a function
that only works with strings,
-
I have no way of forcing that
at the function declaration.
-
Now that's annoying.
-
But, the real kicker
is how this feature is used.
-
Apparently, it is very common to write
two completely different blocks of code,
-
one that handles scalar types,
like strings or ints,
-
and one that handles non-scalar types,
like arrays or hashes.
-
Let me repeat that:
-
Writing multiple code, for multiple data-types,
in one function, is a Perl standard.
-
And that's sad. You shouldn't write redundant code
because the language lacks the capability
-
of letting you decide
which cases you don't want to handle.
-
By the way, Python doesn't let you
declare your function argument data types too,
-
but unlike Perl, writing redundant code
to cover that up
-
is definitely not the standard.
-
Anyway, sad as this may be,
this Perl convention is not dangerous.
-
The dangerous part begins
-
when hashes and arrays
are considered as "secure" data types,
-
mainly because they can't be created
by user input.
-
This results in this kind of code,
-
where if the function argument
is a hash, for example,
-
it is used un-escaped in dangerous functions.
-
Hashes, specifically, are considered so secure,
that even if you use "taint mode",
-
which is some kind of safe mode for Perl,
-
hash keys are not tainted, meaning
that, even if you use safe mode,
-
they can be still used in dangerous functions
-
without any validation,
as opposed to other data types.
-
Now this kind of code appears a lot
in Perl applications,
-
and apart from the many bugs
this method can cause,
-
it also makes your code exploitable.
-
So we know function arguments are of unknown data type.
-
And we know developers treat hashes and arrays
as "secure" data types,
-
inserting their values into dangerous functions.
-
But this practices isn't something
-
that was created a long time ago,
and found only on redundant code.
-
Because of how the language is built,
its supposedly restriction-less type of developing,
-
even now it is the natural way to code
when you're using Perl.
-
And that's the real problem:
Perl is like a shotgun,
-
with one trigger you know about
and a dozen that you don't.
-
So for now, we know
that if we'll somehow manage
-
to create these "secure" data types,
with our user input,
-
we could exploit the code.
-
So the only question remaining really
is what are we gonna exploit?
-
And the answer, again,
is Bugzilla.
-
laughter
-
Like every other Perl project,
Bugzilla is heavily using functions
-
that treat scalar and non-scalar
argument types very differently.
-
This is one of them: the load_from_DB function is responsible
-
for extracting object specific data
out of the database.
-
Like I just said, it treats scalars,
and in this case hashes, very differently.
-
If the function argument is a hash,
it takes one of its values
-
and inserts it as is, un-escaped,
into an SQL statement.
-
Again, because hashes
are considered secure,
-
so there's no point of escaping them.
-
On the other hand,
if the argument is a scalar,
-
it converts it into an integer
and only then use it in an SQL statement.
-
Because scalar values are not secure.
-
hashes: secure
-
scalar: not secure
-
This means that if we could control
the function argument entirely,
-
including its data type,
we could control the SQL query,
-
effectively exploiting an SQL injection attack,
-
by inserting a hash
containing that specific value.
-
But…
-
CGI input doesn't allow hashes, right?
-
The whole Perl security module
is built on that assumption.
-
The problem is that, like us,
developers are assuming
-
CGI input is the only input method available.
-
CGI.
-
But CGI isn't the only way to go.
-
Bugzilla developers missed the fact
that their own system
-
is also featuring an XMLRPC and a JSONRPC,
-
both supporting input of non-scalar data types
like arrays and hashes!
-
But I'm not blaming them.
-
Yes, they forgot that there are more ways
for a user to input than CGI,
-
but still, they're just the product
of how Perl programming is taught,
-
filled with false assumptions and inconsistencies.
-
Expecting anything but this kind
of security problems is just naive.
-
But back to the vulnerability.
-
If we'll use one of these RPCs,
-
sending our input parameter with a malicious hash,
-
instead of just a regular numeric parameter,
-
we will be able to exploit the SQL injection!
-
So, if we'll send this regular request,
using the JSONRPC interface,
-
the number 1 will be used
as the ID of a bug to extract,
-
but if we'll send this request,
-
where instead of an integer we'll supply a hash,
-
then suddenly we will be able
to inject any SQL we'd like
-
into that statement, effectively
compromising the entire database.
-
Now when you look at this request, you realize
-
that this is not a sophisticated vulnerability.
-
All I did was just change the input data type
from scalar in this case to a hash,
-
and that's it, the system is compromised.
-
It was so heavily built on the assumption
-
that hashes are secure, that it offered me
-
almost unlimited access security wise.
-
The funny thing about that is, that
although it's so simple,
-
the attack has existed for over 5 years.
-
That's the year I was born in.
-
So, we now proved this "unknown-argument-type" feature
-
is a huge source for problems.
-
We also know writing different code
to handle different data types
-
just causes a lot of false assumptions.
-
But most importantly, treating non-scalar
data types such as hashes as "secure",
-
just because they supposedly can't be created by the user,
-
is very, very, BAD. Just ask Bugzilla.
-
But the shocking part really, is that, again,
this is the Perl Standard!
-
You're not expected to use it, you have to
-
as you don't have any other choice.
-
This security mess
is a fundamental part of the language.
-
The problem is that creating non-scalar data types
is impossible in some cases.
-
We can't rely that some kind of RPC
-
will exist in the code
and support different data types,
-
and we can't create data types
using regular user input… Right?
-
Well, let's have a look at
-
how different CGI modules
handle different kind of input.
-
First, we'll take the most trivial scenario.
-
A single valued parameter,
something that looks like this request,
-
where the "foo" parameter
is assigned the string "bar".
-
In this case, a scalar is created on all three CGI modules,
-
which doesn't really help us,
but is pretty much what we've expected.
-
It is secure.
-
But what happens if instead of
sending a single-valued parameter,
-
we'll send a multi-valued parameter,
like in this request?
-
Now things are starting to get complicated.
-
On CGI.PM, as we already know,
a list is created,
-
which is very useful for us,
but not what we're after.
-
Let's have a look at
what the "new" Perl modules are creating.
-
We'll see that both of them are returning
arrays containing our values.
-
Arrays! WAT?
-
I thought you can't create
these kind of data types with regular input,
-
after all, they're considered safe.
-
But let's continue.
-
What happens if instead of sending a regular value,
-
we'll try and upload a file in that parameter?
-
Now things are really getting out of hand,
-
because CGI.PM now returns a file descriptor,
and Catalyst and Mojolicious returns a hash.
-
WAT?
-
We just exploited
the most popular Perl project in the world
-
because they assumed hashes can't be created by the user,
-
and now we're finding out
that not only we can create hashes,
-
it is a god-damned feature?!
-
That's insane!
-
The whole Perl security standard is built on that assumption
-
that users can't create non-scalar data-types
-
and now suddenly these are features?
-
But let's send a multi-file upload request
as in several files in the same parameter.
-
Watch closely, because this is where it gets ridiculous.
-
Now, CGI.PM returns a list of File Descriptors,
-
Catalyst returns a list of Hashes
-
and Mojolicious returns an Array of Objects! WAT?!
-
laughter and applause
-
Almost any Perl project in the world
-
uses one of these modules
for parsing CGI input.
-
Just think how many developers assumed
the exact same thing Bugzilla assumed
-
and treated hashes and arrays as secure data types.
-
So if you're using CGI.PM,
-
instead of the expected scalar value you could be getting
-
a list, a file descriptor or a list of file descriptors
-
and if you're using Catalyst
-
you could receive a scalar, an array, a hash or a list,
-
which is basically any data type.
-
So expecting your function… yeah
-
audience chuckling
-
So expecting your function arguments
to be of a specific data type is false.
-
Expecting hashes and arrays to be secure is also false.
-
Expecting scalar only user input
-
is a major false.
-
And to be honest, it seems that in Perl expecting is false!
-
laughter and applause
-
You just can't expect anything
-
even the most basic of things
such as what data type your variable is made of.
-
You just don't know.
-
But I felt all of these points will
go un-noticed
-
without an extreme example of Perl's absurdity.
-
So I found an extreme example.
-
One that will clearly show
-
the ridiculous nature of the language.
-
And this is it:
-
All this code does is print an uploaded file's content.
-
And to show you how basic and simple that code is,
I'll explain each line.
-
The first line just creates a new CGI instance,
so we could get the file from the user.
-
The second line checks if a file
has been uploaded in the "file" parameter.
-
The third line gets the file descriptor from the CGI module,
-
while the fourth line loops through the file
and the fifth prints it.
-
That's it. Again: all this code does
is get a file and print it.
-
clapping
That's it.
-
A user has uploaded a file to the server
and the server is just returning its content.
-
It's not saving it anywhere,
it's not moving it anywhere,
-
it just prints its content.
-
There should be absolutely
nothing dangerous in this code,
-
it contains literally five lines.
-
Yet, it's demo time.
-
laughter
-
So trust me, you don't need to see the text,
-
all you need to see is that
when I'm sending a regular request nothing happens.
-
When I send it now, nothing happens,
I'm just getting the file content.
-
We're having fun, you don't see the burp…
-
Now, nice. Okay.
-
So…
…L't me just…
-
…I have no idea where my mouse is, okay.
-
So…
-
I'm sending a regular request,
nothing happens, just getting the content.
-
I know, you can't see the text…
…and…
-
when I'm sending my malicious request,
-
something interesting will pop up.
-
Watch closely! It's gonna be quick.
-
Ready?
-
Oh, you haven't seen it, it's on the different screen.
-
Just a second… oh… duplicate…
-
(from audience): … magnify it!
-
Netanel: I'll magnify you!
-
laughter
-
Alright, so… watch closely.
-
Ohh, uuh? What was that?
-
Let's see it again.
-
mocking Uuuuuh?!
-
laughter and applause
-
Yupp, clearing throat
-
… just a second.
-
Nice.
-
So you're probably asking yourself right now
-
"What the fuck did I just see?"
laughter
-
"Was that a terminal screen?"
-
And the answer is … "Yes"
Yes, it was,
-
specifically the "ipconfig" command output.
-
Or in other words: What you just saw
-
was me exploiting that five lines
with a remote code execution attack.
-
So now that you saw the magic happens,
I think it's time for some explanations.
-
The first line, responsible for checking
-
if a file has been uploaded in the "file" parameter,
-
doesn't exactly do as it says.
-
Instead of checking if the "file"
parameter is an uploaded file,
-
it checks if one of its values is a file descriptor.
-
Let me clarify that, instead of checking
if the parameter is only a file,
-
it checks if the parameter is also a file.
-
laughter
-
Meaning that uploading a file
-
and assigning another scalar value to the same parameter
-
will still work and bypass the check!
-
WAT?
-
more laughter and applause
-
Creative fellows those guys are.
-
So now we can assign the "file" parameter
both a regular file and a scalar value.
-
But what happens when we try to get
the "file" parameter value?
-
In a regular request, it should return
the uploaded file descriptor,
-
but now that we're adding another value to that parameter,
-
param() returns a list containing all the values we sent:
-
the file we've uploaded and our scalar value.
-
But the "file" variable
can't contain two values, right?
-
So instead of converting
the returned list into an array
-
Perl only uses the first element of that list.
-
So if we'll send our scalar value
before we send our file,
-
the $file variable will be assigned
our scalar value
-
instead of the uploaded file descriptor.
-
Which means, that $file
is now a regular string!
-
in high pitched voice: WAT?
-
But what happens to this operator
when we use a string
-
instead of a file descriptor?
-
Well, the brackets operator
doesn't work with strings, right?
-
It works with file descriptors,
why should it work with strings?
-
Well, that appears true
-
unless that string is "ARGV".
-
laughter and applause
-
That's not a crazy part.
-
more laughter
-
In that case the brackets operator, listen closely,
-
loops through the script arguments,
-
which in CGI comes directly from the
query string instead the command line,
-
and it treats them as file paths,
inserting each one into an open() call!
-
again laughter
-
WAT?
-
Yeah, that made sense in some point, I guess.
-
All of this basically means that now,
-
instead of displaying
our own uploaded file content,
-
we can display the content
of any file on the server.
-
But that's not the end,
as we haven't executed code yet.
-
To execute code, we have
to look at the open() function.
-
Again, this is the function being called
with the ARGV values as file paths.
-
open() is responsible for opening
a file descriptor to a given file.
-
Unless a "pipe" character is added
-
to the end of the string,
laughter
-
and in that case instead of opening the file,
-
it executes it…
applause rising
-
…acting as an exec() call!
more applause
-
So … when we send our exploit,
-
containing our uploaded file,
the "ARGV" malicious scalar value,
-
and the ipconfig command followed by a pipe
-
this is what we get.
WAT?
-
WAT?
applause
-
I know, I'm shocked too, but I'm not done yet.
laughter
-
Truth be told, I didn't write that code.
-
Remember that PerlMonks told me
that I should read their fucking manual?
-
more laughter
Guess where that code came from:
-
the official CGI documentation!
big applause and audience whistling
-
But, I'm not blaming CGI.PM developers.
-
Nor am I blaming developers
who copied from CGI.PM examples.
-
After all, who could have known
that this is what this code will do?
-
This is how it could be exploited?
-
There's no exec calls,
the file is not saved anywhere,
-
and we're only using a "print".
-
The sole responsible for this mess,
is the Perl language.
-
Perl is the one silently expanding lists,
-
Perl is the one mixing up your data types,
-
Perl is the one executing user input
with no exec calls,
-
Perl is the problem,
-
not its developers.
applause rising
-
And until this god-damned, bizarre,
dangerous language is fixed,
-
you could only
stop
-
using
-
Perl!
-
Thank you!
more applause
-
Herald: So I guess
we have some time for questions now.
-
laughter
Netanel: Maybe
-
Herald: And I have the funny feeling,
we will have some questions now.
-
Ok, so we have some microphones here.
Please queue up.
-
Please do not shout in, because we need
to record it on the stream.
-
Well, here we go.
-
And we also have some questions
from the internet, don't we?
-
Signal Angel: Oh yes, we do!
laughter
-
Signal: But before we come
to the technical questions,
-
the IRC wants you to know,
what you did to it:
-
it felt like there were explosions
and camels everywhere.
-
Netanel laughing: That's the point
-
Signal: And incidently they want to know,
if you have a list of those camel pics somewhere?
-
Netanel: I think Google has it?
more laughter
-
Just there search camels.
-
Signal: So for the first question.
Opello(?) wants to know,
-
if the take-away is, that Perl project authors
so shouldn't trust input
-
and instead verify types with REF
and always use prepared SQL statements?
-
Netanel: That's a good question. The take-away should be…
laughter
-
well, how will I phrase it …
-
I think I have a slide … somewhere …
more laughter
-
Oh wait, where's my slide?
-
Don't worry, have it right here.
-
But really, trusting user input
is always a bad idea
-
and most developers know it.
-
The problem is, that…
-
well, at least from the code
I saw written in Perl,
-
and that's a lot of code, trust me
-
…is that hashes and arrays
are almost always considered secured
-
as they supposedly can't be
created by user input, as I said.
-
But, when you're expecting your user input
to be a scalar, a string or even a list
-
and instead you get a hash from unexpected
directions, you get confused.
-
And you can't always
live in the fear of not knowing
-
what data type you're trying to handle.
-
Well, not trusting scalar data types
is a wise decision, because it's dangerous.
-
But not trusting your hashes,
as well not trusting your arrays?
-
What's next? Not trusting your own code?
-
You just can't expect anything
to really work as it should.
-
When you're writing Perl,
-
you are constantly attacked
by all these different directions.
-
And even the data type direction is a problem now.
-
I hope that answered the question
beside the slide.
-
Herald: Well, then we're gonna go over
and start with number one.
-
Questioner: So thank you for opening our eyes.
-
Even I use Perl, I would say,
for cooking and yes …
-
Netanel: I remember you
Q: Sorry?
-
N: I remember you from the last talk!
Q: No no
-
N: Oh, you're new? Oh… smirking
Q: I'm new, I'm new…
-
Q: So… I can't say, I'm not guilty of that,
but I still would say yes,
-
Perl is a bit like cooking with my mum.
-
Sometimes I put something into…
the… with the boiling thing…
-
and sometimes she, sometimes I go away,
sometimes she go away
-
and the only thing you can do is always taste.
-
And yes, you're maybe right, Perl is a language
-
where you never know what comes out,
but it's real cool!
-
If you get the right response you can use it,
-
if you use it to write web applications
I would agree.
-
Web applications, the professional ones
at least, are not for cooking,
-
but for doing funny things and
have some fun, I think it's a perfect language.
-
N: I think Perl is a lot of fun.
laughter
-
I completely agree on that. laughing
-
Herald: Then we're gonna go over to two.
-
Question: Was your life ever threatened
while interacting with the Perl community?
-
laughter
N: Could you please repeat that? I …
-
Q: Was your life ever threatened
while interacting with the Perl community?
-
N: Definitely. Definitely,
-
I'm getting hate mail every day,
living in fear …
-
H: And over to the three, please.
-
Q: I think I speak for all of us,
when I thank you for this wonderful talk,
-
N: Uh, thank you. Thank you really! Thank you.
applause
-
Q: Brilliantly executed, but… ehm…
you spoke about Perl 5 I think.
-
N: Yes, you are absolutely right.
Q: As some of you might know, this christmas…
-
laughter
Q: …so tomorrow Ingo Blechschmidt
-
is going to give a talk about how Perl 6
will make everything better
-
and how everyone should start
using Perl 6 and…
-
N: It also craps rainbows
Q: Yeah, of course…
-
Q: My personal comment is:
wouldn't it have happened
-
with a statically typed language?
-
So I think some nice folks at Haskell
in IRC are waiting for you Perl developers
-
to please come, join us … Thank you!
N: smirking
-
Herald and Netanel start speaking simultaneously
-
H: …sorry, to answer first, where am I… sorry
N: Ah, no..., I am not answering, just...
-
just a quick note about Perl 6.
This talk is all about Perl 5, alright?
-
I … Perl 6 came out a couple of days ago and …
-
...from …at least from what I saw,
Perl 6 is to Perl as…
-
C++ is to C. It's the same name,
but it's a whole different language.
-
So yes, this is Perl 5.
Maybe I'll come back next year about Perl 6?
-
laughter
Who knows?
-
Herald: I'm looking forward to that already.
applause
-
Herald pointing to Signal Angel
-
Signal: Yeah… Joerd(?) wants to know:
of course you talked a lot about CGI.PM
-
which you know was removed from repository from Perl
even before your talk last year.
-
So what about it's replacements
from CPAN like CGI::Simple.
-
Netanel: I don't know, I haven't checked it.
When I decided on which modules to check,
-
I took CGI.PM because even though it is old,
it is the most popular in the world as of today
-
and I took Mojolicious and Catalyst because
they were really popular, too.
-
So I didn't take the newest modules,
I take the most popular modules.
-
And I think, that's the important
aspect of … deciding.
-
Herald: And over to one, please.
-
Questioner: Hi… I'm… part of the Perl community, and…
laughter
-
N: Hi!
Q: But I just start with Perl – 5
-
N: Uhh… ehm… uhh… didn't you… nhaa…
laughter
-
Q: We use Perl for almost every module
that we have at work
-
and this worked really fine.
N: …yeah…
-
Q: And I don't know why you're picking Perl as language to attack.
-
It's a really old language, it's also every language
that we can pick, that has problems.
-
But it doesn't mean this has to die or
stop using it. So I don't know why…
-
N: …you're right, you're right.
First of all, you're completely right,
-
because a language shouldn't die, it should improve.
-
C got critized and it improved.
PHP got critized and it improved.
-
Why can't Perl be critized, too?
-
Why is it like a code, when you say
something bad about Perl, then,
-
I don't know, a horde of PerlMonks jumps on you?
-
Why don't improve the language?
Don't use it in your work though,
-
it's dangerous.
laughter and applause
-
H: Then we're gonna jump over to five, please.
-
Q: Hi. I'm not a Perl developer,
but I use a lot of Ruby and Python.
-
Is this really limited to Perl or
-
does this apply to more or less
any dynamic language?
-
N: As I said in one of the first few slides,
-
some of it also applies to Python.
Specifically the thing
-
when you can't specify what data types
your function arguments can get.
-
But, what's unique to Perl is that
writing different code
-
for different data types in one function
is very, very common.
-
You can do it in every language, of course!
-
But it is very common only in Perl!
And that is unique about it,
-
of course besides the thing
that hashes and arrays are secure.
-
That's of course Perls only fault.
-
H: Good, then we're gonna go over to six, please.
-
Q: Hey! Did you say WAT more
while preparing this talk or while holding it?
-
N: Uhm. Both. Laughing.
Did I rant? That was the … right?
-
Q: Did you say it more
while preparing it or while holding it?
-
N: I'm missing your word, man, can you...
-
Ahh, wat… WAT! Ohh… Yeah, both!
laughter
-
H: Ok, do we have another from the internet?
-
Signal: Does your exploit
also work in tainted mode?
-
N: No, I believe not. No, it doesn't.
-
H: And another one...
-
S: Is there any Perl obfuscated code exploits
like this for Catalyst or Mojolicious?
-
someone chuckling in audience
-
N: I've no idea, man, maybe.
I didn't check it of course.
-
I didn't check every module
for every exploit, I ever want to create, but
-
on CGI.PM, which is again
the most popular CGI library, it did.
-
So, maybe the internet
can find more exploits. I know it can.
-
H: Bring it on. That's it?
N: That's it?
-
Thank you!
-
applause
-
Herald: Thank you very much!
Netanel: Thank you!
-
postroll music
-
subtitles created by c3subtitles.de
in the year 2016. Join, and help us!