 Before I begin, I have a personal note, this will be my first talk ever, and I wonder if I can take a picture with you all. Is that fine? Yeah, fine by me, fine by me. Just a sec. Everybody say fuck Pearl. That's nice, okay. So, today I obviously gonna talk about Pearl, so let's start. Pearl, its coding style sucks. It's OP sucks. It's data types sucks bad, but it's here since late 87. Many legacy system use it, that's right. Many legacy system use it, most CIS admins use it, and unfortunately, too many security experts use it. And if you wanna summarize it in a quote, it's worse than Python because people wanted it worse. Larry Wall, the creator of the pearl programming language, a lot of pearl enthusiasts in the crowd, so let's talk about pearl data types. At first, we had scalars. Those are just regular scalars. You already know ints, strings, floats, etc. They even look like scalars using this syntax. Then, we had arrays. Those are just regular arrays. They use square brackets and pretty much looks like this. And finally, we had dictionaries. Those are just regular dictionaries. In pearl, they're called hashes. They use curly brackets and looks like this. So far, so good. The syntax is understandable and everything works the way it should. But we forgot something. What about lists? So let's talk about lists. Let's take the following code as an example for a list. The section marked in bright yellow is the actual list. We'll assign the list into an array and then print its first element, which is obviously one. Let's assign the list into a scalar now. We expect the scalar will only use the first element of the list and that one will be printed out, like in every other normal language. But, not in pearl, which uses the last element of a list, in that case, C. Although, that only happens unless we cast the list as a scalar, in which case, instead of printing C, like the previous example, it'll print 5, the number of elements in the list. Now, let's assign the list into a hash. The expected behavior is that this syntax will throw an exception or at least print undefined when we actually use the hash. But pearl managed to treat it as a hash somehow and prints B, even though it's not resembling any sort of hashing syntax and the list even have a fucking uneven number of elements. What? But we'll dive into this behavior later. Meanwhile, it's important that you understand that this happens because a list is not a data type. It's just an expression, obviously created to confuse us all. So, after we saw a list are a potential source for problems we thought, wait, how can we even control a list? Well, one obvious way is to look around the CGI module. It's a core module responsible for processing and preparing HTTP requests and responses. Its data arrives from the user using HTTP parameters, and most, if not all, pearl web applications use it. Also, like any other thing in pearl, it's been there for 15 years. So, let's take the following code that prints the content of the foo and bar HTTP parameters. If we'll send this regular request where one is assigned to foo and A is assigned to bar, we'll see that one and A are printed as expected. But what will happen if we'll send this request that contains the same parameters twice? The logical thing to think is that pearl will only take the first or last occurrence, so you'll probably see the exact same thing happen again. But, as we already saw, pearl and logic aren't mixing well together, and in fact, we'll actually see two different lists being printed. That's right, if you use multi-value in HTTP parameter, pearl just makes a list out of it. But what does the documentation has to say about that? Well, this is a screenshot from the official documentation at pearl doc. Can you see the problem yet? No. How about now? Still no. How about now? That's right, according to the documentation, you can ask to receive an array. How do you ask for an array? Well, you don't ask for not an array, because the list is the default fucking value in case of a multi-valued parameter. What? But what does all this has to say about that? According to them, pearl CGI module only takes the first occurrence only, while in reality it returns a list of occurrences. That makes both the documentation and NOASP blind to the idea of an HTTP parameter pollution attack, and as a follow-up mislead every programmer who reads them. So, let's start abusing lists. Let's create a list and a hash. As you can see, the value of the key E is the list we've created. We'll print the hash, we'll expect something like this to happen, where the key E is assigned the array we've created. But in reality, the hash actually looks like this, with the second element used as a key named lol, and the third element as a value assigned what? That happens because a list in hash is considered an extension to the hash. These arrows are just pretty comas. Although that's actually known since 2006, yet it got no attention and no vulnerabilities were released using this quirk. No vulnerabilities with such an easy to miss quirk. So, let's recap for a sec. We know already lists are fucked up because they are just plain expressions that's considered a sedata type. We know CGI parameters can become lists if we'll send multi-valued parameters. And we know that if we'll take a list and place it inside a hash, it'll expand and become part of that hash. And finally, and most importantly, all of this is barely known and is super easy to miss when coding. So, what the fuck are we gonna exploit? בגזילה. That bugzilla. The one that manages bugs for the Linux kernel, Mozilla Foundation, Reddit, MediaWiki, KDE, Nome, Eclipse, OpenOffice, and tons of other companies. In bugzilla, some privileges are given via a regex performed on the email address. For example, a user under mozilla.org gain privileges, allows it to view confidential Firefox bugs. A new user gets validated prior to the actual registration using an email sent to its mailbox containing a token used for continued registration in order to validate the address. Right? Makes sense. After the user enters the token, it's asked to provide a password and a real name for its new account. Then, this code happens. This is the code for the user creation. It uses the create function from the bugzilla user package and inserts a dictionary containing the login name, which is the user email address after it's already validated, the password as a scalar from the user, and as you probably guessed, the real name from a CGI parameter. Bingo. So, if we send this regular request, it will be created with a real name field set to lolzo. But do you remember that the list inside the hash just expands the hash? So, if we send this request, when the real name is a list containing the string lolzo, login name and bugzilla at an admin at bugzilla.org, then suddenly we'll create a new key and value pair and could override the value of login name, even though it has been already set, thus controlling the email address. This vulnerability worked on mozilla's bugzilla and granted us privileges reserved only for mozilla's employees. Yet, it's a super simple vulnerability. Thanks, thank you. This is a super simple vulnerability that's been there for over seven years. So, let's recap again. Lists are fucked up. But those list quirks I showed thus far were already public. Hashes, though, can't be the only place vulnerable, right? So, let's leave hashes aside and take list expansion behavior to the next level so we could really fuck things up with some bizarre undisclosed vulnerabilities and behaviors. So, this is a function. It takes three arguments, A, B, and C, and just prints them. Do you remember the previous ones? There are plenty more to come. So, in a regular call with A, B, and C's values, we expect A, B, and C to be printed out, which is exactly what happens. But what happens if instead of just the string B, we'll enter a list containing it? We expect the second argument to be inserted into an array and display that way. Don't forget Perl is that special kid in class that shit his pants whenever something he didn't expect happens. So, Perl actually takes the single-valued list and treat it as a string in the second parameter. What? Okay, you know what? Let's allow this one to slide. After all, maybe Perl just expands single-valued list into the single-value. Maybe it made sense to the developers at some point. Let's force the list to be a multi-valued with B and C as element, so it has to be an array. We expect it to print the second argument as an array containing B and C, right? After all, that's exactly what we've coded. But again, Perl says fuck off and it actually treats the string B as the second argument and the string C as the third. What? That's insane. We actually created another argument using only a list. Look at the syntax. It's the exact same syntax you will have used to create a regular array. Let's try to defend against this kind of behavior and hard code the third argument SD. Now Perl can't just ignore it and it has to treat our list as an array with the third function argument SD. Right? Well, no. In reality, Perl overrides the third argument we've hard coded into the function with the content inside the list. What the fuck? What the fuck, Perl? Perl just expands our list as if it were containing more arguments for the function. That's completely mind-blowing. But the Perl documentation says this fuck type behavior is not a bug. It's a feature. Is it? Thank you. Let's look at DBI quotes. DBI is a core module since 1994. I was born that year. It is the most common way to communicate with databases and almost everyone uses it to do so. It has only one function for defending against SQL injections. Quote. Let's see how this function works. If we'll send a regular string, the function will just place it inside two apostrophes. But if we'll try to inject something like this string, quote, we'll escape it for us so it'll be safe to use inside the query. So let's see a regular example for using the function. In this code, we'll quote the user CGI parameter and insert it into our query. We use the dbh variable as our db connection and the CGI variable as our CGI instance. If we'll insert a regular user string, a regular query will be printed out. But if we'll try to inject an apostrophe, quote, we'll take care of it and escape it so we can't inject any malicious SQL. Looks like you're right. After all, it's been there for more than two decades. Well, I think it's time for the demo. So what we have here, just a sec. Right. This is a code I've created. You can all see it, magnify it. Right. Just a sec. How can I magnify something in another monitor? Wow. See? Oh, sorry. Sorry about that. No. Okay, fuck it. So do you see the code? So we just create the variables and then connect to the dbh and then print a query that exact same query we used in the presentation. So if I open a barb for just a sec, let's see what it is. There you go. Oh, oh. Something happened. Something happened. פרל קרשט מי פי סי. No. פרפ סי כן. Inlarget. Nope. I'll copy it to Notepad. So what I'm sending now is this request. Okay? Look at it. See? I'm sending this request. Where user equals admin. Okay? Let's see what the output of that request will bring us. So it brought us this. It can zoom in, zoom it, doesn't work. I don't know why on two monitors. Can't enlarge the phone. Sorry. Wait, you know what? Maybe I can. Let's see. Such an intuitive editor. Yeah, it doesn't work. It just goes back to the presentation if I scroll. Oh, no, it does work. Yeah. And this is how you scroll. So it just printed select all from user as well as user name equals admin, right? Everything is well. And now we'll send admin apostrophe. Okay? We'll try to inject an apostrophe. So we got back this. Okay? And the apostrophe has been escaped. So we couldn't inject anything. And now I'm going to send this request. I'm going to type it in Notepad. And we'll send this request. And we'll see what happens. Good luck, Perl. And this is what came back. No escaping. This is our bypass quote. Yeah. Ask or inject everything. So, back to the presentation. That happens because we could bypass the escaping because quote takes in fact two arguments. The string to quote and its type which defaults to string. I never saw anyone uses the type argument, but if someone did it's supposed to help the function decide what to do with the string entered if and how it should escape it. Quote does that by matching the type against several constants declared in the module. These constants are actually just numbers ranging from the number 2 to the number 8. So when we've inserted the number 2 as the second argument, quote thought the string is actually an integer and decided to return it as is without escaping it. Now, that is the second fail. That is the second fail in this function as he didn't even validate we've inserted an actual number. Who's the feature now, bitch? So you're probably wondering what could be achieved with all that mind-blowing fucked-up shaders in Perl. Well, we could bypass authentication of Godzilla, execute code and upload any file we'd like to T-Wiki, inject a scale into movable type, and they're just a small portion of what could really be achieved if someone took the time and effort for exploiting stuff with it. By the way, IMDB is written in Perl, just saying. For example, just search CGI and quote at Github and consider what you can do with it. So let's sum up. Lists are hazardous bizarre expressions. Perl is a hazardous bizarre language. Now is the time to stop using it. Yeah. Stop using it. Stop the right only code. Stop. Yeah, fuck Perl. Yeah, fuck Perl. Stop the misfunctional and complicated OOP and most importantly stop the security breaches that are all over the place. And if you do end up writing Perl, at least know your goddamn language features. Thank you. Viseniel agreed to Q&A, so please line up on the microphones and Viseniel would take a few questions. Do you have questions? The internet has questions. Oh, we have a question. Okay. The internet has one question right now. Can you avoid this with proper user validation and use of strict end-end warnings? Use strict doesn't do anything in that case. CGI just returns at least. It doesn't have anything to do with strict. For the second part after we released the Bakzila vulnerability the author of CGI-PM released a new version for CGI-PM that tries to restrict the use of this list behavior but in reality all it does is when you send multi-value in an HTTP parameter it just warns you you did. So if I use it it just warns me I attacked the system. So thanks for the info but yeah. Microphone 2? Yeah, I'm going to be the one asshole here who really loves Pearl. I've been waiting for you. I've been waiting for you. Could you go back to the summary you gave? To the previous slide with the summary. Yeah, sorry about that. What you say lists are hazardous in bizarre expressions. What you really need to see is that arrays and lists are two completely separate constructs and if I look at the examples you gave about using lists and argument calls it really looked like you were really trying for lists to be Python arrays I want them to be Python arrays but if you want Python arrays go and use Python then don't use Pearl. So I know it's only an opinion, it's not a really question but what this talk boils down is that you've found two functions that are designed very badly. For example, the quote that takes a second argument that shouldn't happen. Yeah man, blame the programmer. That's what you guys do. Blame the programmer? No, no, no. Wait, wait, wait. For a serious tone why do we even have lists if you already have arrays? What's the point of lists? You know? What? You can assign them to an array they're not a data type, they're expressions why have them from the first place? I don't know. Seriously. My call from five. First of all, thank you for the talk this was entertaining. Do you have any idea why it took so long for somebody to actually notice this? I don't know. I don't know. Because it's what? Right, probably. Probably. Microphone number three. Yeah, thanks for the awesome talk. Long time, no pearls or I don't know if it's a stupid question but your code there was no warnings enabled no use strict does this change anything I was wondering. use strict doesn't change anything and warnings just warns you when you program an application and program it to use a single value parameter it doesn't warn anything but it actually warns you because when I first learned pearl use warnings and if there's a single warning you have a huge problem. A warning is a huge problem I can now enable warnings and this script will work just fine the script I showed previously do you want me to enable a warning? I believe you, I was just wondering because I can. Thanks again, no props. Internet. One other question from the internet how to avoid or fix these errors in applications already written in pearl? So in order to avoid this stuff you actually have to treat every CGI parameter as a scalar if you actually intend to use it as a scalar like if you don't want to pass an array into a function or a hash and that the hash or array will actually treat it as another array you have to backslash the reference to that list you have to backslash a variable so that's how you overcome that I'll just discuss it as a scalar Microphone 4 The example with dbi I use the manual quote function I usually use prepared statements Have you checked if that's safe or is it working there as well? Prepared statements are safe I did check them but you can inject more values to the prepared statement as a result from this you can inject anything into any function if you insert it into a list once you gained an argument that it's a list you control you control every other argument in the function that follows it Do you understand? Microphone 5 Yeah, I just want to ask you if you know what references are and if you're at the dbi man page then you should know that you use prepared There's like 3 preparing to the artist Yeah, I did read the manual for the dbi This is obviously bad programming But again, blame the programmer Seriously, it's it's that basic You can say anything you want about the reference and that the language isn't supposed to work that way but if we're looking at it logically it does supposed to work that way I don't think so It's documented, learning pearl Yeah, it's documented dbi is in the first chapter Sure thing Okay, nice to know Microphone 2 Yeah, this is an asshole microphone 2 I just can repeat Can we explain about it? Flattening lists in arguments and references passing errors for reference, it's basic documentation it's basic design of the language So what? The error reference thing is completely fine but the problem is in the CGI Do you understand? I completely agree that the two modules the bugs you found, those are bad I blame the programmers of those modules Exactly That's the point That's not good programming That's bad programming That everyone does Unless you're like programming 20 years Even if you program 20 years in pearl that still worked on bugzilla they maintained it from I don't know, 2008, 98 something like that and they still haven't figured it out yet that this is what CGI program does There's one last question on Microphone 3 So my impression of what's going on here is that basically you have a weird type of value that allows you to mess with the structure of the syntax tree at runtime Are you aware of any other languages that do that Because if there are it's very likely that they're going to be exploitable in a very similar fashion because nobody's going to understand If there are more languages I'll give more presentation I guess Sorry, man, I don't know of anyone any language So thanks, Nathaniel No problem Thank you