WEBVTT 00:00:00.000 --> 00:00:08.755 preroll music 00:00:10.084 --> 00:00:13.459 Herald: And I'm gonna introduce Netanel Rubin. 00:00:14.166 --> 00:00:18.640 He has been here last year with a talk that he got some bashing for. 00:00:19.314 --> 00:00:23.548 This year he's gonna ensure, it's not the programmer's fault, 00:00:23.689 --> 00:00:27.426 it's the language itself. No? 00:00:27.507 --> 00:00:29.883 Well, here we go, well here we go. 00:00:29.949 --> 00:00:33.598 Netanel, he is working for PerimeterX in Tel Aviv, 00:00:33.631 --> 00:00:35.491 welcome on stage, your talk! 00:00:35.521 --> 00:00:37.634 Netanel: Thank you very much, applause 00:00:37.674 --> 00:00:41.134 thank you, thank you! 00:00:44.747 --> 00:00:52.755 Last year I stood right on this very stage and I talked about several of Perl's 00:00:52.755 --> 00:00:56.411 less thought out "features". 00:00:56.411 --> 00:01:04.709 Now, I got some bashing from the Perl community, but mainly what happened was, 00:01:04.709 --> 00:01:10.291 that the Perl community completely rejected my talk claiming that the language 00:01:10.291 --> 00:01:16.357 is completely fine and great and all of this stuff are just improvements. 00:01:17.573 --> 00:01:20.724 It was clear I had to give another talk. 00:01:21.421 --> 00:01:29.049 This is why I'm very proud to present "Perl Jam 2 – The Camel strikes back"! 00:01:29.049 --> 00:01:33.618 applause 00:01:33.618 --> 00:01:36.188 Thank you 00:01:38.065 --> 00:01:45.873 At the last talk, I showed that "lists" are expressions, used in… many confusing ways. 00:01:45.873 --> 00:01:52.921 I also showed how CGI parameters can create lists, directly from user input. 00:01:52.921 --> 00:02:00.165 But most importantly, I showed that when these two things combine, shit happens. 00:02:01.696 --> 00:02:04.066 Great 00:02:04.080 --> 00:02:08.949 But the really interesting part was the PerlMonks response. 00:02:08.949 --> 00:02:16.203 The Perl community… laughter 00:02:19.274 --> 00:02:24.451 The Perl community had a long discussion at the PerlMonks forum. 00:02:24.451 --> 00:02:29.475 that started with the words "Sad news from Germany". 00:02:29.475 --> 00:02:32.231 A bit dramatic, but who am I to judge? 00:02:32.231 --> 00:02:38.931 So, after a long, long discussion, they came to the unavoidable conclusion 00:02:38.931 --> 00:02:47.997 that my talk was, in fact, a "polemic shit", and they should all just "piss on it". Wink. 00:02:49.717 --> 00:02:55.756 They also realized I'm just a "script kiddie preaching to other script kiddies", 00:02:55.756 --> 00:03:01.162 and not just any script kiddies, the CCC audience is a 00:03:01.162 --> 00:03:06.435 "heterogeneous group of chaotic punks who love to see themselves in the hacker 00:03:06.435 --> 00:03:18.091 image of Hollywood media". applause and whistling from audience 00:03:18.091 --> 00:03:24.075 What hacker image? What are they talking about? 00:03:24.075 --> 00:03:26.218 We have no hacker image. 00:03:26.310 --> 00:03:34.281 Anyway, it got quite surreal, as in some point they even critized 00:03:34.281 --> 00:03:41.994 the "crude use of propaganda in the camel images". WAT? 00:03:42.461 --> 00:03:46.015 laughing applause 00:03:46.015 --> 00:03:50.737 Propaganda in the camel images. Alright. 00:03:50.737 --> 00:03:58.348 Anyway, they completely rejected the entire talk, even though the technical points were valid. 00:03:58.348 --> 00:04:03.603 They rejected it because of some jokes and camel images. 00:04:03.603 --> 00:04:12.814 But still, they got so offended they just threw lame excuses as to why their language sucks. 00:04:12.814 --> 00:04:19.622 Two of these lame excuses were repeated over and over again. 00:04:19.622 --> 00:04:24.733 The first was that I should read the fucking manual, which is funny 00:04:24.733 --> 00:04:27.413 because I thought I was the only one who did… 00:04:27.413 --> 00:04:29.184 laughter 00:04:29.184 --> 00:04:30.753 …and the second is that 00:04:30.753 --> 00:04:35.378 I'm using the old, ancient Perl, and not the new, modern Perl. 00:04:35.378 --> 00:04:39.920 more laughter 00:04:40.811 --> 00:04:46.317 Remember these two points carefully as I'll later break them in the presentation. 00:04:46.317 --> 00:04:52.167 But, enough with the intro, let's start with the new madness. 00:04:52.167 --> 00:04:58.788 So, Perl allows declaring variables without specifying their data type. 00:04:58.788 --> 00:05:03.131 Of course, this functionally exists in many dynamic languages, 00:05:03.131 --> 00:05:06.884 and is completely fine and very convenient. 00:05:06.884 --> 00:05:12.773 But, as usual, Perl took it to a whole different level. 00:05:12.773 --> 00:05:19.200 Perl went as far as removing data type declarations from function arguments. 00:05:19.200 --> 00:05:20.854 You can see that in this example 00:05:20.854 --> 00:05:27.760 I'm just receiving two different arguments without knowing what type they are. 00:05:27.760 --> 00:05:29.760 Let me be clear about that, 00:05:29.760 --> 00:05:34.536 you don't get to choose whether you want to specify argument data types or not, 00:05:34.536 --> 00:05:41.053 you can't specify what data types you're expecting to get. 00:05:41.053 --> 00:05:44.764 So even if I built a function that only works with strings, 00:05:44.764 --> 00:05:49.332 I have no way of forcing that at the function declaration. 00:05:49.332 --> 00:05:51.318 Now that's annoying. 00:05:51.318 --> 00:05:57.394 But, the real kicker is how this feature is used. 00:05:57.444 --> 00:06:03.828 Apparently, it is very common to write two completely different blocks of code, 00:06:03.828 --> 00:06:07.675 one that handles scalar types, like strings or ints, 00:06:07.675 --> 00:06:13.217 and one that handles non-scalar types, like arrays or hashes. 00:06:13.217 --> 00:06:15.338 Let me repeat that: 00:06:15.338 --> 00:06:23.796 Writing multiple code, for multiple data-types, in one function, is a Perl standard. 00:06:23.796 --> 00:06:31.782 And that's sad. You shouldn't write redundant code because the language lacks the capability 00:06:31.782 --> 00:06:35.971 of letting you decide which cases you don't want to handle. 00:06:35.971 --> 00:06:40.493 By the way, Python doesn't let you declare your function argument data types too, 00:06:40.493 --> 00:06:45.723 but unlike Perl, writing redundant code to cover that up 00:06:45.723 --> 00:06:49.726 is definitely not the standard. 00:06:49.726 --> 00:06:54.723 Anyway, sad as this may be, this Perl convention is not dangerous. 00:06:54.723 --> 00:06:56.894 The dangerous part begins 00:06:56.894 --> 00:07:02.956 when hashes and arrays are considered as "secure" data types, 00:07:02.956 --> 00:07:07.738 mainly because they can't be created by user input. 00:07:07.738 --> 00:07:10.374 This results in this kind of code, 00:07:10.374 --> 00:07:14.187 where if the function argument is a hash, for example, 00:07:14.187 --> 00:07:18.708 it is used un-escaped in dangerous functions. 00:07:18.708 --> 00:07:25.661 Hashes, specifically, are considered so secure, that even if you use "taint mode", 00:07:25.661 --> 00:07:28.293 which is some kind of safe mode for Perl, 00:07:28.293 --> 00:07:33.532 hash keys are not tainted, meaning that, even if you use safe mode, 00:07:33.532 --> 00:07:36.719 they can be still used in dangerous functions 00:07:36.719 --> 00:07:41.639 without any validation, as opposed to other data types. 00:07:41.639 --> 00:07:46.619 Now this kind of code appears a lot in Perl applications, 00:07:46.619 --> 00:07:49.759 and apart from the many bugs this method can cause, 00:07:49.759 --> 00:07:54.635 it also makes your code exploitable. 00:07:54.635 --> 00:07:58.369 So we know function arguments are of unknown data type. 00:07:58.369 --> 00:08:03.073 And we know developers treat hashes and arrays as "secure" data types, 00:08:03.073 --> 00:08:06.603 inserting their values into dangerous functions. 00:08:06.603 --> 00:08:09.140 But this practices isn't something 00:08:09.140 --> 00:08:14.056 that was created a long time ago, and found only on redundant code. 00:08:14.056 --> 00:08:20.341 Because of how the language is built, it's supposedly restriction-less type of developing, 00:08:20.341 --> 00:08:26.688 even now it is the natural way to code when you're using Perl. 00:08:26.688 --> 00:08:31.185 And that's the real problem: Perl is like a shotgun, 00:08:31.185 --> 00:08:36.552 with one trigger you know about and a dozen that you don't. 00:08:36.552 --> 00:08:40.821 For now, we know that if we'll somehow manage 00:08:40.821 --> 00:08:46.051 to create these "secure" data types, with our user input, 00:08:46.051 --> 00:08:49.010 we could exploit the code. 00:08:49.010 --> 00:08:53.997 So the only question remaining really is what are we gonna exploit? 00:08:53.997 --> 00:08:58.185 And the answer, again, is Bugzilla. 00:08:58.185 --> 00:09:02.768 laughter 00:09:03.178 --> 00:09:08.713 Like every other Perl project, Bugzilla is heavily using functions 00:09:08.713 --> 00:09:13.277 that treat scalar and non-scalar argument types very differently. 00:09:13.277 --> 00:09:17.404 This is one of them: 00:09:17.404 --> 00:09:21.541 for extracting object specific data out of the database. 00:09:21.541 --> 00:09:28.945 Like I just said, it treats scalars, and in this case hashes, very differently. 00:09:28.945 --> 00:09:34.146 If the function argument is a hash, it takes one of its values 00:09:34.146 --> 00:09:39.845 and inserts it as is, un-escaped, into an SQL statement. 00:09:39.845 --> 00:09:44.598 Again, because hashes are considered secure, 00:09:44.598 --> 00:09:47.807 so there's no point of escaping them. 00:09:47.807 --> 00:09:50.919 On the other hand, if the argument is a scalar, 00:09:50.919 --> 00:09:55.798 it converts it into an integer and only then use it in an SQL statement. 00:09:55.798 --> 00:09:59.020 Because scalar values, are not secure. 00:09:59.020 --> 00:10:00.680 hashes: secure 00:10:00.680 --> 00:10:03.064 scalar: not secure 00:10:03.064 --> 00:10:06.241 This means that if we could control the function argument entirely, 00:10:06.241 --> 00:10:10.964 including its data type, we could control the SQL query, 00:10:10.964 --> 00:10:14.405 affectively exploiting an SQL injection attack, 00:10:14.405 --> 00:10:17.720 by inserting a hash containing that specific value. 00:10:17.720 --> 00:10:21.234 But… 00:10:21.234 --> 00:10:26.862 CGI input doesn't allow hashes, right? 00:10:26.862 --> 00:10:32.339 The whole Perl security module is built on that assumption. 00:10:32.339 --> 00:10:37.314 The problem is that, like us, developers are assuming 00:10:37.314 --> 00:10:42.487 CGI input is the only input method available. 00:10:42.487 --> 00:10:46.121 CGI. 00:10:46.121 --> 00:10:49.375 But CGI isn't the only way to go. 00:10:49.375 --> 00:10:53.218 Bugzilla developers missed the fact that their own system 00:10:53.218 --> 00:10:57.723 is also featuring an XMLRPC and a JSONRPC, 00:10:57.723 --> 00:11:05.388 both supporting input of non-scalar data types like arrays and hashes! 00:11:05.388 --> 00:11:07.048 But I'm not blaming them. 00:11:07.048 --> 00:11:12.492 Yes, they forgot that there are more ways for user to input than CGI, 00:11:12.492 --> 00:11:16.697 but still, they're just the product of how Perl programming is taught, 00:11:16.697 --> 00:11:20.679 filled with false assumptions and inconsistencies. 00:11:20.679 --> 00:11:25.983 Expecting anything but this kind of security problems is just naive. 00:11:25.983 --> 00:11:28.547 But back to the vulnerability. 00:11:28.547 --> 00:11:30.429 If we'll use one of these RPCs, 00:11:30.429 --> 00:11:34.136 sending our input parameter with a malicious hash, 00:11:34.136 --> 00:11:37.204 instead of just a regular numeric parameter, 00:11:37.204 --> 00:11:39.991 we will be able to exploit the SQL injection! 00:11:39.991 --> 00:11:44.428 So, if we'll send this regular request, using the JSONRPC interface, 00:11:44.428 --> 00:11:48.611 the number 1 will be used as the ID of a bug to extract, 00:11:48.611 --> 00:11:51.272 but if we'll send this request, 00:11:51.272 --> 00:11:53.993 where instead of an integer we'll supply a hash, 00:11:53.993 --> 00:11:57.365 than suddenly we will be able to inject any SQL we'd like 00:11:57.365 --> 00:12:03.016 into that statement, effectively compromising the entire database. 00:12:03.561 --> 00:12:07.048 Now when you look at this request, you realize 00:12:07.048 --> 00:12:11.396 that this is not a sophisticated vulnerability. 00:12:11.396 --> 00:12:20.859 All I did was just change the input data type from scalar in this case to a hash, 00:12:20.859 --> 00:12:24.980 and that's it, the system is compromised. 00:12:24.980 --> 00:12:29.072 It was so heavily built on the assumption 00:12:29.072 --> 00:12:32.223 that hashes are secure, that it offered me 00:12:32.223 --> 00:12:36.676 almost unlimited access security wise. 00:12:36.676 --> 00:12:41.659 The funny thing about that is, that although it's so simple, 00:12:41.659 --> 00:12:45.970 the attack has existed for over 5 years. 00:12:45.970 --> 00:12:48.912 That's the year I was born in. 00:12:48.912 --> 00:12:55.087 So, we now proved this "unknown-argument-type" feature 00:12:55.087 --> 00:12:58.232 is a huge source for problems. 00:12:58.232 --> 00:13:02.901 We also know writing different code to handle different data types 00:13:02.901 --> 00:13:06.953 just causes a lot of false assumptions. 00:13:06.953 --> 00:13:13.534 But most importantly, treating non-scalar data types such as hashes as "secure", 00:13:13.534 --> 00:13:17.354 just because they supposedly can't be created by the user, 00:13:17.354 --> 00:13:22.955 is very, very, BAD. Just ask Bugzilla. 00:13:22.955 --> 00:13:30.145 But the shocking part really, is that, again, this is the Perl Standard! 00:13:30.145 --> 00:13:33.892 You're not expected to use it, you have to 00:13:33.892 --> 00:13:36.645 as you don't have any other choice. 00:13:36.645 --> 00:13:43.829 This security-mess is a fundamental part of the language. 00:13:43.829 --> 00:13:51.777 The problem is that creating non-scalar data types is impossible in some cases. 00:13:51.777 --> 00:13:54.914 We can't rely that some kind of RPC 00:13:54.914 --> 00:13:58.859 will exist in the code and support different data types, 00:13:58.859 --> 00:14:05.031 and we can't create data types using regular user input… Right? 00:14:05.031 --> 00:14:06.937 Well, let's have a look at 00:14:06.937 --> 00:14:10.526 how different CGI modules handle different kind of input. 00:14:10.526 --> 00:14:13.917 First, we'll take the most trivial scenario. 00:14:13.917 --> 00:14:17.807 A single valued parameter, something that looks like this request, 00:14:17.807 --> 00:14:22.210 where the "foo" parameter is assigned the string "bar". 00:14:22.210 --> 00:14:26.819 In this case, a scalar is created on all three CGI modules, 00:14:26.819 --> 00:14:31.198 which doesn't really help us, but is pretty much what we've expected. 00:14:31.198 --> 00:14:32.914 It is secure. 00:14:32.914 --> 00:14:37.846 What happens if instead of sending a single-valued parameter, 00:14:37.846 --> 00:14:42.377 we'll send a multi-valued parameter, like in this request? 00:14:42.377 --> 00:14:46.032 Now things are starting to get complicated. 00:14:46.032 --> 00:14:50.551 On CGI.PM, as we already know, a list is created, 00:14:50.551 --> 00:14:55.013 which is very useful for us, but not what we're after. 00:14:55.013 --> 00:15:01.847 Let's have a look at what the "new" Perl modules are creating. 00:15:01.847 --> 00:15:09.987 We'll see that both of them are returning arrays containing our values. 00:15:09.987 --> 00:15:14.549 Arrays! WAT? 00:15:14.549 --> 00:15:19.278 I thought you can't create these kind of data types with regular input, 00:15:19.278 --> 00:15:22.442 after all, they're considered safe. 00:15:22.442 --> 00:15:24.236 But let's continue. 00:15:24.236 --> 00:15:27.637 What happens if instead of sending a regular value, 00:15:27.637 --> 00:15:31.883 we'll try and upload a file in that parameter? 00:15:31.883 --> 00:15:35.229 Now things are really getting out of hand, 00:15:35.229 --> 00:15:44.409 because CGI.PM now returns a file descriptor, and Catalyst and Mojolicious returns a hash. 00:15:44.409 --> 00:15:46.384 WAT? 00:15:46.384 --> 00:15:54.012 We just exploited the most popular Perl project in the world 00:15:54.012 --> 00:15:58.226 because they assumed hashes can't be created by the user, 00:15:58.226 --> 00:16:02.984 and now we're finding out that not only we can create hashes, 00:16:02.984 --> 00:16:05.477 it is a god-damned feature?! 00:16:05.477 --> 00:16:07.161 That's insane! 00:16:07.161 --> 00:16:11.504 The whole Perl security standard is built on that assumption 00:16:11.504 --> 00:16:14.954 that users can't create non-scalar data-types 00:16:14.954 --> 00:16:19.867 and now suddenly these are features? 00:16:19.867 --> 00:16:27.693 But let's send a multi-file upload request as in several files in the same parameter. 00:16:27.693 --> 00:16:34.183 Watch closely, because this is where it gets ridiculous. 00:16:34.183 --> 00:16:39.426 Now, CGI.PM returns a list of File Descriptors, 00:16:39.426 --> 00:16:42.551 Catalyst returns a list of Hashes 00:16:42.551 --> 00:16:49.282 and Mojolicious returns an array of objects! WAT?! 00:16:49.282 --> 00:16:53.340 laughter and applause 00:16:53.444 --> 00:16:58.105 Almost any Perl project in the world 00:16:58.105 --> 00:17:03.470 uses one of these modules for parsing CGI input. 00:17:03.470 --> 00:17:10.522 Just think how many developers assumed the exact same thing Bugzilla assumed 00:17:10.522 --> 00:17:15.854 and treated hashes and arrays as secure data types. 00:17:15.854 --> 00:17:17.752 So if you're using CGI.PM, 00:17:18.380 --> 00:17:21.268 instead of the expected scalar value you could be getting 00:17:21.268 --> 00:17:25.724 a list, a file descriptor or a list of file descriptors 00:17:25.724 --> 00:17:27.644 and if you're using Catalyst 00:17:27.644 --> 00:17:30.895 you could receive a scalar, an array, a hash or a list, 00:17:30.895 --> 00:17:35.375 which is basically any data type. 00:17:36.320 --> 00:17:39.425 So expecting your function… yeah 00:17:40.089 --> 00:17:44.091 audience chuckling 00:17:45.943 --> 00:17:53.997 So expecting your function arguments to be of a specific data type is false. 00:17:53.997 --> 00:18:00.119 Expecting hashes and arrays to be secure is also false. 00:18:00.119 --> 00:18:02.972 Expecting scalar only user input 00:18:02.972 --> 00:18:06.833 is a major false. 00:18:06.833 --> 00:18:13.156 And to be honest, it seems that in Perl expecting is false! 00:18:13.156 --> 00:18:17.337 laughter and applause 00:18:21.422 --> 00:18:25.923 You just can't expect anything 00:18:25.923 --> 00:18:32.455 even the most basic of things such as what data type your variable is made of. 00:18:32.455 --> 00:18:35.761 You just don't know. 00:18:37.870 --> 00:18:42.934 But I felt all of these points will go un-noticed 00:18:42.934 --> 00:18:48.632 without an extreme example of Perl's absurdity. 00:18:48.632 --> 00:18:52.599 So I found an extreme example. 00:18:52.599 --> 00:18:55.249 One that will clearly show 00:18:55.249 --> 00:18:59.204 the ridiculous nature of the language. 00:18:59.204 --> 00:19:00.898 And this is it: 00:19:00.898 --> 00:19:06.829 All this code does is print an uploaded file's content. 00:19:06.829 --> 00:19:15.077 And to show you how basic and simple that code is, I'll explain each line. 00:19:15.077 --> 00:19:20.993 The first line just creates a new CGI instance, so we could get the file from the user. 00:19:20.993 --> 00:19:27.475 The second line checks if a file has been uploaded in the "file" parameter. 00:19:27.475 --> 00:19:31.909 The third line gets the file descriptor from the CGI module, 00:19:31.909 --> 00:19:37.438 while the forth line loops through the file and the fifths prints it. 00:19:37.438 --> 00:19:44.459 That's it. Again: all this code does is get a file and print it. 00:19:44.459 --> 00:19:45.871 clapping That's it. 00:19:45.871 --> 00:19:52.126 A user has uploaded a file to the server and the server is just returning its content. 00:19:52.126 --> 00:19:55.683 It's not saving it anywhere, it's not moving it anywhere, 00:19:55.683 --> 00:19:58.771 it just prints its content. 00:19:58.771 --> 00:20:03.519 There should be absolutely nothing dangerous in this code, 00:20:03.519 --> 00:20:07.087 it contains literally five lines. 00:20:07.087 --> 00:20:09.830 Yet, it's demo time. 00:20:09.830 --> 00:20:12.332 laughter 00:20:12.412 --> 00:20:15.020 So trust me, you don't need to see the text, 00:20:15.020 --> 00:20:19.820 all you need to see is that when I'm sending a regular request nothing happens. 00:20:19.820 --> 00:20:23.585 When I send it now, nothing happens, I'm just getting the file content. 00:20:23.585 --> 00:20:26.240 We're having fun, you don't see the burp… 00:20:26.240 --> 00:20:30.425 Now, nice. Okay 00:20:30.425 --> 00:20:34.184 So… …L't me just… 00:20:35.085 --> 00:20:37.182 …I have no idea where my mouse is, okay. 00:20:37.388 --> 00:20:38.323 So… 00:20:39.181 --> 00:20:42.780 I'm sending a regular request, nothing happens, just getting the content. 00:20:42.780 --> 00:20:45.713 I know, you can't see the text… …and… 00:20:45.713 --> 00:20:49.519 when I'm sending my malicious request, 00:20:49.519 --> 00:20:52.795 something interesting will pop up. 00:20:52.901 --> 00:20:54.990 Watch closely! It's gonna be quick. 00:20:55.502 --> 00:20:56.684 Ready? 00:20:58.270 --> 00:21:00.520 Oh, you haven't seen it, it's on the different screen. 00:21:00.520 --> 00:21:06.641 Just a second… oh… duplicate… 00:21:07.809 --> 00:21:09.236 (from audience): … magnify it! 00:21:09.236 --> 00:21:11.781 Netanel: I'll magnify you! 00:21:11.781 --> 00:21:14.247 laughter 00:21:14.611 --> 00:21:18.136 Alright, so… watch closely. 00:21:19.184 --> 00:21:22.772 Ohh, uuh? What was that? 00:21:24.797 --> 00:21:26.799 Let's see it again. 00:21:26.799 --> 00:21:29.528 mocking Uuuuuh?! 00:21:30.340 --> 00:21:37.335 laughter and applause 00:21:37.793 --> 00:21:41.082 Yupp, clearing throat 00:21:41.612 --> 00:21:44.650 … just a second. 00:21:45.410 --> 00:21:46.579 Nice. 00:21:46.714 --> 00:21:49.747 So you're probably asking yourself right now 00:21:49.747 --> 00:21:52.951 "What the fuck did I just see?" laughter 00:21:52.951 --> 00:21:55.814 "Was that a terminal screen?" 00:21:55.814 --> 00:22:00.237 And the answer is … "Yes" Yes, it was 00:22:00.237 --> 00:22:04.468 specifically the "ipconfig" command output. 00:22:04.468 --> 00:22:07.414 Or in other words: What you just saw 00:22:07.414 --> 00:22:15.820 was me exploiting that five lines with a remote code execution attack. 00:22:15.820 --> 00:22:20.873 So now that you saw the magic happens, I think it's time for some explanations. 00:22:20.873 --> 00:22:22.917 The first line, responsible for checking 00:22:22.917 --> 00:22:26.221 if a file has been uploaded in the "file" parameter, 00:22:26.221 --> 00:22:29.956 doesn't exactly do as it says. 00:22:29.956 --> 00:22:34.013 Instead of checking if the "file" parameter is an uploaded file, 00:22:34.013 --> 00:22:39.540 it checks if one of it values is a file descriptor. 00:22:39.540 --> 00:22:45.110 Let me clarify that, instead of checking if the parameter is only a file, 00:22:45.110 --> 00:22:48.981 it checks if the parameter is also a file. 00:22:48.981 --> 00:22:51.196 laughter 00:22:51.196 --> 00:22:52.842 Meaning that uploading a file 00:22:52.842 --> 00:22:57.023 and assigning another scalar value to the same parameter 00:22:57.023 --> 00:23:00.147 will still work and bypass the check! 00:23:00.147 --> 00:23:01.460 WAT? 00:23:01.460 --> 00:23:06.435 more laughter and applause 00:23:12.616 --> 00:23:16.165 Creative fellows those guys are. 00:23:16.165 --> 00:23:22.137 So now we can assign the "file" parameter both a regular file and a scalar value. 00:23:22.137 --> 00:23:26.384 But what happens when we try to get the "file" parameter value? 00:23:26.384 --> 00:23:31.183 In a regular request, it should return the uploaded file descriptor, 00:23:31.183 --> 00:23:35.821 but now that we're adding another value to that parameter, 00:23:35.821 --> 00:23:41.176 param() returns a list containing all the values we sent: 00:23:41.176 --> 00:23:44.365 the file we've uploaded and our scalar value. 00:23:44.365 --> 00:23:49.521 But the "file" variable can't contain two values, right? 00:23:49.521 --> 00:23:55.641 So instead of converting the returned list into an array 00:23:55.641 --> 00:23:59.781 Perl only uses the first element of that list. 00:23:59.781 --> 00:24:05.564 So if we'll send our scalar values before we send our file, 00:24:05.564 --> 00:24:09.989 the $file variable will be assigned our scalar value 00:24:09.989 --> 00:24:14.308 instead of the uploaded file descriptor. 00:24:14.308 --> 00:24:20.013 Which means, that $file is now a regular string! 00:24:20.013 --> 00:24:22.114 in high pitched voice: WAT? 00:24:22.618 --> 00:24:26.127 But what happens to this operator when we use a string 00:24:26.127 --> 00:24:29.025 instead of a file descriptor? 00:24:29.025 --> 00:24:32.962 Well, the brackets operator doesn't work with strings, right? 00:24:32.962 --> 00:24:36.958 It works with file descriptors, why should it work with strings? 00:24:36.958 --> 00:24:39.580 Well, that appears true 00:24:39.580 --> 00:24:42.817 unless that string is "ARGV". 00:24:42.817 --> 00:24:47.644 laughter and applause 00:24:55.860 --> 00:24:57.627 That's not a crazy part. 00:24:57.627 --> 00:24:59.763 more laughter 00:24:59.763 --> 00:25:04.953 In that case the brackets operator, listen closely, 00:25:04.953 --> 00:25:07.988 loops through the script arguments, 00:25:07.988 --> 00:25:12.887 which in CGI comes directly from the query string instead the command line, 00:25:12.887 --> 00:25:18.844 and it treats them as file paths, inserting each one into an open() call! 00:25:18.844 --> 00:25:20.497 again laughter 00:25:20.497 --> 00:25:22.655 WAT? 00:25:25.952 --> 00:25:29.485 Yeah, that made sense on some point, I guess. 00:25:29.485 --> 00:25:32.487 All of this basically means that now, 00:25:32.487 --> 00:25:35.874 instead of displaying our own uploaded file content, 00:25:35.874 --> 00:25:40.829 we can display the content of any file on the server. 00:25:40.829 --> 00:25:42.344 But that's not the end, as we haven't executed code yet. 00:25:44.674 --> 00:25:49.168 To execute code, we have to look at the open() function. 00:25:49.168 --> 00:25:56.676 Again, this is the function being called with the ARGV values as file paths. 00:25:56.676 --> 00:26:03.284 open() is responsible for opening a file descriptor to a given file. 00:26:03.284 --> 00:26:06.544 Unless a "pipe" character is added 00:26:06.544 --> 00:26:09.486 to the end of the string, laughter 00:26:09.486 --> 00:26:13.819 in that case instead of opening the file, 00:26:13.819 --> 00:26:16.828 it executes it… applause rising 00:26:16.828 --> 00:26:22.796 …acting as an exec() call! more applause 00:26:23.096 --> 00:26:29.172 So … when we send our exploit, 00:26:29.172 --> 00:26:34.631 containing our uploaded file, the "ARGV" malicious scalar value, 00:26:34.631 --> 00:26:38.045 and the ipconfig command followed by a pipe 00:26:38.045 --> 00:26:42.697 this is what we get. WAT? 00:26:42.697 --> 00:26:46.639 WAT? applause 00:26:49.585 --> 00:26:56.705 I know, I'm shocked too, but I'm not done yet. laughter 00:26:56.705 --> 00:27:01.193 Truth be told, I didn't write that code. 00:27:01.193 --> 00:27:06.159 Remember that PerlMonks told me that I should read their fucking manual? 00:27:06.159 --> 00:27:10.660 more laughter Guess where that code came from: 00:27:10.660 --> 00:27:22.979 the official CGI documentation! big applause and audience whistling 00:27:32.545 --> 00:27:36.867 But, I'm not blaming CGI.PM developers. 00:27:36.867 --> 00:27:41.365 Nor am I blaming developers who copied from CGI.PM examples. 00:27:41.365 --> 00:27:47.443 After all, who could have known that this is what this code will do? 00:27:47.443 --> 00:27:49.657 This is how it could be exploited? 00:27:49.657 --> 00:27:54.961 There's no exec calls, the file is not saved anywhere, 00:27:54.961 --> 00:27:58.493 and we're only using a "print". 00:27:58.493 --> 00:28:07.823 The sole responsible for this mess, is the Perl language. 00:28:07.823 --> 00:28:11.722 Perl is the one silently expanding lists, 00:28:11.722 --> 00:28:14.832 Perl is the one mixing up your data types, 00:28:14.832 --> 00:28:20.064 Perl is the one executing user input with no exec calls, 00:28:20.064 --> 00:28:23.010 Perl is the problem, 00:28:23.010 --> 00:28:26.122 not its developers. applause rising 00:28:26.122 --> 00:28:32.159 And until this god-damned, bizarre, dangerous language is fixed, 00:28:32.159 --> 00:28:34.536 you could only stop 00:28:34.536 --> 00:28:35.629 using 00:28:35.629 --> 00:28:39.867 Perl! 00:28:39.867 --> 00:28:47.005 Thank you! more applause 00:28:59.485 --> 00:29:02.754 Herald: So I guess we have some time for questions now. 00:29:02.754 --> 00:29:04.348 laughter Netanel: Maybe 00:29:04.348 --> 00:29:08.594 Herald: And I have the funny feeling, we will have some questions now. 00:29:08.594 --> 00:29:12.384 Ok, so we have some microphones here. Please queue up. 00:29:12.384 --> 00:29:18.469 Please do not shout in, because we need to record it on the stream. 00:29:18.469 --> 00:29:19.936 Well, here we go. 00:29:19.936 --> 00:29:22.956 And we also have some questions from the internet, don't we? 00:29:22.956 --> 00:29:27.794 Signal angel: Oh yes, we do! laughter 00:29:27.794 --> 00:29:30.413 Signal: But before we come to the technical questions, 00:29:30.413 --> 00:29:33.691 the IRC wants you to know, what you did to it: 00:29:33.691 --> 00:29:37.135 it felt like there were explosions and camels everywhere. 00:29:37.135 --> 00:29:39.915 Netanel laughing: That's the point 00:29:39.915 --> 00:29:44.622 Signal: And incidently they want to know, if you have a list of those camel pics somewhere? 00:29:46.402 --> 00:29:49.843 Netanel: I think Google has it? more laughter 00:29:49.843 --> 00:29:54.336 Just there search camels. 00:29:54.336 --> 00:29:59.224 Signal: So for the first question. Opello(?) wants to know, 00:29:59.224 --> 00:30:04.293 if the take-away is, that Perl project authors so shouldn't trust input 00:30:04.293 --> 00:30:10.437 and instead verify types with REF and always use prepared SQL statements? 00:30:13.616 --> 00:30:20.628 Netanel: That's a good question. The take-away should be… laughter 00:30:24.239 --> 00:30:28.428 well, how will I phrase it … 00:30:29.184 --> 00:30:32.734 I think I have a slide … somewhere … more laughter 00:30:32.734 --> 00:30:36.303 Oh wait, where's my slide? 00:30:38.071 --> 00:30:40.204 Don't worry, have it right here. 00:30:44.644 --> 00:30:49.480 But really, trusting user input is always a bad idea 00:30:49.480 --> 00:30:52.071 and most developers know it. 00:30:52.071 --> 00:30:54.521 The problem is, that… 00:30:54.521 --> 00:30:57.498 well, at least from the code I saw written in Perl, 00:30:57.498 --> 00:31:00.601 and that's a lot of code, trust me 00:31:00.601 --> 00:31:05.154 …is that hashes and arrays are almost always considered secured 00:31:05.154 --> 00:31:09.543 as they supposedly can't be created by user input, as I said. 00:31:09.543 --> 00:31:17.966 But, when you're expecting your user input to be a scalar, a string or even a list 00:31:17.966 --> 00:31:26.256 and instead you get a hash from unexpected directions, you get confused. 00:31:26.256 --> 00:31:31.149 And you can't always live in the fear of not knowing 00:31:31.149 --> 00:31:33.963 what data type you're trying to handle. 00:31:33.963 --> 00:31:40.575 Well, not trusting scalar data types is a wise decision, because it's dangerous. 00:31:40.575 --> 00:31:46.369 But not trusting your hashes, as well not trusting your arrays? 00:31:46.369 --> 00:31:49.901 What's next? Not trusting your own code? 00:31:49.901 --> 00:31:54.754 You just can't expect anything to really work as it should. 00:31:54.754 --> 00:31:57.584 When you're writing Perl, 00:31:57.584 --> 00:32:04.629 you are constantly attacked by all these different directions. 00:32:04.629 --> 00:32:09.029 And even the data type direction is a problem now. 00:32:09.029 --> 00:32:12.962 I hope that answers the question beside the slide. 00:32:12.962 --> 00:32:16.695 Herald: Well, then we're gonna go over and start with number one 00:32:16.695 --> 00:32:20.074 Questioner: So thank you for opening our eyes. 00:32:20.074 --> 00:32:24.354 Even I use Perl, I would say, for cooking and yes … 00:32:24.354 --> 00:32:25.788 Netanel: I remember you Q: Sorry? 00:32:25.788 --> 00:32:27.377 N: I remember you from the last talk! Q: No no 00:32:27.377 --> 00:32:31.028 N: Oh, you're new? Oh… smirking Q: I'm new, I'm new… 00:32:31.028 --> 00:32:36.288 Q: So… I can't say, I'm not guilty of that, but I still would say yes, 00:32:36.288 --> 00:32:39.508 Perl is a bit like cooking with my mum. 00:32:39.508 --> 00:32:46.315 Sometimes I put something into… the… with the boiling thing… 00:32:46.315 --> 00:32:50.864 and sometimes she, sometimes I go away, sometimes she go away 00:32:50.864 --> 00:32:54.374 and the only thing you can do is always taste. 00:32:54.374 --> 00:32:58.514 And yes, you're maybe right, Perl is a language 00:32:58.514 --> 00:33:02.332 where you never know what comes out, but it's real cool! 00:33:02.332 --> 00:33:04.903 If you get the right response you can use it, 00:33:04.903 --> 00:33:09.088 if you use it to write web applications I would agree. 00:33:09.088 --> 00:33:13.464 Web applications, the professional ones at least, are not for cooking, 00:33:13.464 --> 00:33:18.856 but for doing funny things and have some fun, I think it's a perfect language. 00:33:18.856 --> 00:33:22.626 N: I think Perl is a lot of fun. laughter 00:33:22.626 --> 00:33:26.633 I completely agree on that. laughing 00:33:26.633 --> 00:33:29.144 Herald: Then we're gonna go over to two 00:33:29.144 --> 00:33:33.741 Question: Was your life ever threatened while interacting with the Perl community? 00:33:33.741 --> 00:33:36.064 laughter N: Could you please repeat that? I … 00:33:36.064 --> 00:33:39.995 Q: Was your life ever threatened while interacting with the Perl community? 00:33:39.995 --> 00:33:43.145 N: Definitely. Definitely, 00:33:43.145 --> 00:33:47.109 I'm getting hate mail every day, living in fear … 00:33:47.109 --> 00:33:48.928 H: And over to the three please 00:33:48.928 --> 00:33:53.261 Q: I think I speak for all of us, when I thank you for this wonderful talk, 00:33:53.261 --> 00:34:00.436 N: Uh, thank you. Thank you really! Thank you. applause 00:34:00.436 --> 00:34:07.010 Q: Brilliantly executed, but… ehm… you spoke about Perl 5 I think 00:34:07.010 --> 00:34:11.155 N: Yes, you are absolutely right Q: As some of you might know, this christmas… 00:34:11.155 --> 00:34:15.472 laughter Q: …so tomorrow Ingo Blechschmidt 00:34:15.472 --> 00:34:20.047 will give a talk about how Perl 6 will make everything better 00:34:20.047 --> 00:34:24.161 and how everyone should start using Perl 6 and… 00:34:24.161 --> 00:34:27.893 N: It also craps rainbows Q: Yeah, of course… 00:34:27.893 --> 00:34:31.391 Q: My personal comment is: wouldn't it have happened 00:34:31.391 --> 00:34:33.945 with a statically typed language? 00:34:33.945 --> 00:34:39.570 So I think some nice folks at Haskell in IRC are waiting for you Perl developers 00:34:39.570 --> 00:34:44.753 to please come, join us … Thank you! N: smirking 00:34:44.753 --> 00:34:46.456 Herald and Netanel start speaking simultaneously 00:34:46.456 --> 00:34:49.886 H: …sorry, to answer first, where am I… sorry N: I… no thanks… unclear 00:34:49.886 --> 00:34:55.856 just a quick note about Perl 6. This talk is all about Perl 5, alright? 00:34:55.856 --> 00:34:59.478 I … Perl 6 came out a couple of days ago and … 00:34:59.478 --> 00:35:06.848 From … at least from what I saw, Perl 6 is to Perl as… 00:35:06.848 --> 00:35:11.932 C++ is to C. It's the same name, but it's a whole different language. 00:35:11.932 --> 00:35:17.311 So yes, this is Perl 5. Maybe I'll come back next year about Perl 6? 00:35:17.311 --> 00:35:19.051 laughter Who knows? 00:35:19.051 --> 00:35:23.415 Herald: I'm looking forward to that already applause 00:35:23.415 --> 00:35:25.578 Herald pointing to signal angel 00:35:25.578 --> 00:35:31.574 Signal: Yeah… Joerd(?) wants to know: of course you talked a lot about CGI.PM 00:35:31.574 --> 00:35:37.750 which you know was removed from repository from Perl even before your talk last year. 00:35:37.750 --> 00:35:43.729 So what about it's replacements from CPAN like CGI::Simple. 00:35:43.729 --> 00:35:48.505 Netanel: I don't know, I haven't checked it. When I decided on which modules to check, 00:35:48.505 --> 00:35:55.990 I took CGI.PM because even though it is old, it is the most popular in the world as of today 00:35:55.990 --> 00:36:03.561 and I took Mojolicious and Catalyst because they were really popular, too. 00:36:03.561 --> 00:36:08.389 So I didn't take the newest modules, I take the most popular modules. 00:36:08.389 --> 00:36:14.513 And I think, that's the important aspect of … deciding. 00:36:14.513 --> 00:36:20.599 Herald: and over to one please 00:36:20.599 --> 00:36:29.133 Questioner: Hi… uhm… part of the Perl community, and… laughter 00:36:29.133 --> 00:36:33.169 N: Hi! Q: But I just start with Perl – 5 00:36:33.169 --> 00:36:40.715 N: Uhh… ehm… uhh… didn't you… nhaa… laughter 00:36:40.715 --> 00:36:44.829 Q: We use Perl for almost every modules that we have at work 00:36:44.829 --> 00:36:47.314 and this worked really fine. N: …yeah… 00:36:47.314 --> 00:36:51.920 Q: And I don't know why you're picking Perl as language to attack. 00:36:51.920 --> 00:36:59.469 It's a really old language, it's also every language that we can pick, that has problems. 00:36:59.469 --> 00:37:05.027 But it doesn't mean this has to die or stop using it. So I don't know why… 00:37:05.027 --> 00:37:08.881 N: …you're right, you're right. First of all, you're completely right, 00:37:08.881 --> 00:37:11.958 because a language shouldn't die, it should improve. 00:37:11.958 --> 00:37:17.040 C got critized and it improved. PHP got critized and it improved. 00:37:17.040 --> 00:37:20.563 Why can't Perl be critized, too? 00:37:20.563 --> 00:37:24.238 Why is it like a code, when you say something bad about Perl then, 00:37:24.238 --> 00:37:27.684 I don't know, a horde of PerlMonks jumps on you? 00:37:27.684 --> 00:37:32.643 Why don't improve the language? Don't use it in your work though, 00:37:32.643 --> 00:37:37.766 it's dangerous. laughter and applause 00:37:39.896 --> 00:37:41.799 H: Then we gonna jump over to five please 00:37:41.799 --> 00:37:49.273 Q: Hi. I'm not a Perl developer, but I use a lot of Ruby and Python. 00:37:49.273 --> 00:37:51.551 Is this really limited to Perl or 00:37:51.551 --> 00:37:54.169 does this apply to more or less any dynamic language? 00:37:54.169 --> 00:37:58.640 N: As I said in one of the first few slides, 00:37:58.640 --> 00:38:02.483 some of it also applys to Python. Specifically the thing 00:38:02.483 --> 00:38:10.127 when you can't specify what data types your function arguments can get. 00:38:10.127 --> 00:38:16.074 But, what's unique to Perl is that writing different code 00:38:16.074 --> 00:38:20.517 for different data types in one function is very, very common. 00:38:20.517 --> 00:38:23.181 You can do it in every language, of course! 00:38:23.181 --> 00:38:28.686 But it is very common only in Perl! And that is unique about it, 00:38:28.686 --> 00:38:32.881 of course besides the thing that hashes and arrays are secure. 00:38:32.881 --> 00:38:37.016 That's of course Perls only fault. 00:38:37.016 --> 00:38:40.358 H: Good, then we're gonna go over to six please 00:38:40.358 --> 00:38:47.295 Q: Hey! Did you say WAT more while preparing this talk or while holding it? 00:38:47.295 --> 00:38:54.672 N: Uhm. Both. Laughing. Did I rant? That was the … right? 00:38:54.672 --> 00:39:00.911 Q: Did you say it more while preparing it or while holding it? 00:39:00.911 --> 00:39:02.963 N: I'm missing your word, man. 00:39:02.963 --> 00:39:12.018 Ahh, wat… WAT! Ohh… Yeah, both! laughter 00:39:12.018 --> 00:39:14.828 H: Ok, do we have another from the internet? 00:39:14.828 --> 00:39:19.290 Signal: Does your exploit also work in tainted mode? 00:39:19.290 --> 00:39:23.583 N: No, I believe not. No, it doesn't. 00:39:23.583 --> 00:39:26.470 H: And another one 00:39:26.470 --> 00:39:36.487 S: Is there any Perl obfuscated code exploits like this for Catalyst or Mojolicious? 00:39:36.487 --> 00:39:43.729 N: I've no idea, man, maybe. I didn't check it of course. 00:39:43.729 --> 00:39:48.082 I didn't check every module for every exploit, I ever want to create, but 00:39:48.082 --> 00:39:54.675 on CGI.PM, which is again the most popular CGI library, it did. 00:39:54.675 --> 00:40:01.866 So, maybe the internet can find more exploits. I know it can. 00:40:01.866 --> 00:40:06.622 H: Bring it on. That's it? N: That's it? 00:40:06.622 --> 00:40:07.775 Thank you! 00:40:07.775 --> 00:40:09.157 applause 00:40:09.157 --> 00:40:13.084 Herald: Thank you very much! Netanel: Thank you! 00:40:13.084 --> 00:40:23.033 postroll music