1 00:00:13,740 --> 00:00:16,300 Hey, welcome back to AppSecVillage. 2 00:00:16,300 --> 00:00:18,860 Hope you're having a great time here at DEF CON 2020. 3 00:00:19,120 --> 00:00:21,260 Get ready for another wonderful talk. 4 00:00:21,260 --> 00:00:23,100 We've got Jared Overson. 5 00:00:23,560 --> 00:00:28,160 And he's going to talk about Hackium, a browser for web hackers. 6 00:00:28,160 --> 00:00:29,460 Okay, let's be honest. 7 00:00:29,480 --> 00:00:31,920 With a name like Hackium, you've got to kind of check it out. 8 00:00:31,920 --> 00:00:33,660 It's like the coolest name ever. 9 00:00:33,660 --> 00:00:35,500 I know I'm going to be watching this one. 10 00:00:35,620 --> 00:00:44,160 Jared is the Director of Engineering at Shape Security, now F5, where he designed and led the development of Shape's enterprise web security platform. 11 00:00:44,280 --> 00:00:51,640 Jared is a frequent speaker on modern web threats and has been quoted by Forbes, The Wall Street Journal, and CNET, along with many others. 12 00:00:52,060 --> 00:01:03,180 He co-authored O'Reilly's Developing Web Components book, delivered dozens of analysis and reverse engineering tools, and frequently writes about web development and fraud. 13 00:01:03,180 --> 00:01:07,740 Please welcome Jared to the AppSec security stage. 14 00:01:09,500 --> 00:01:10,700 Hey. 15 00:01:10,880 --> 00:01:11,740 Hi. 16 00:01:11,900 --> 00:01:12,980 Thank you. 17 00:01:13,440 --> 00:01:15,180 Thank you for being here. 18 00:01:15,600 --> 00:01:16,880 Thank you. 19 00:01:16,880 --> 00:01:17,880 This is awesome. 20 00:01:17,880 --> 00:01:19,960 This is so cool. 21 00:01:19,960 --> 00:01:22,320 This is strange. 22 00:01:22,320 --> 00:01:23,200 This is strange. 23 00:01:23,200 --> 00:01:24,560 I can't lie. 24 00:01:24,560 --> 00:01:25,780 This is strange. 25 00:01:25,960 --> 00:01:27,460 I can't see you. 26 00:01:27,460 --> 00:01:30,040 You're not actually here with me. 27 00:01:30,040 --> 00:01:36,860 And I was going to have slides and then it started feeling like a webinar with my little picture in the corner. 28 00:01:37,200 --> 00:01:42,080 And a webinar is the last thing I think of when I think of DEF CON. 29 00:01:42,080 --> 00:01:43,640 And I just I couldn't do it. 30 00:01:43,640 --> 00:01:46,820 I just physically could not do it. 31 00:01:46,960 --> 00:01:49,560 So we're just going to we're going to do this live. 32 00:01:49,780 --> 00:01:53,340 It's a prerecorded with a whole bunch of cuts and whatever. 33 00:01:54,800 --> 00:01:56,940 But it is it is what it is. 34 00:01:56,940 --> 00:01:58,880 This is this is a strange time. 35 00:01:58,880 --> 00:02:04,980 But anyway, I'm excited to talk to you about what I'm going to talk about. 36 00:02:04,980 --> 00:02:06,560 But first, who am I? 37 00:02:06,600 --> 00:02:08,460 I'm I'm Jared Oberson. 38 00:02:08,460 --> 00:02:11,820 I talk a lot about credential stuffing and automated attacks. 39 00:02:11,820 --> 00:02:14,120 And I'm just a web hacker. 40 00:02:14,120 --> 00:02:16,680 I've been hacking the web for a million years. 41 00:02:16,680 --> 00:02:26,240 I work at Shape Security, now part of F5, director of engineering, where I built Shape's enterprise web application security platform. 42 00:02:26,240 --> 00:02:35,900 And it was it was an awesome opportunity because it gave me the chance to basically make a product that would defeat me. 43 00:02:36,220 --> 00:02:38,400 And that was fun. 44 00:02:38,660 --> 00:02:43,440 I thought like, well, I could do this, but then I could beat me by doing this. 45 00:02:43,440 --> 00:02:45,640 And then if I did this, then I could do that. 46 00:02:45,640 --> 00:02:47,560 And if I did that, I could do this. 47 00:02:47,560 --> 00:02:52,120 And it was it was just a cool, fun game against myself. 48 00:02:52,120 --> 00:02:56,140 I ended up building something pretty cool, but I'm no longer building that anymore. 49 00:02:56,560 --> 00:03:02,140 And I'm building other things, which is what I'm going to talk to you today about. 50 00:03:02,140 --> 00:03:03,920 But enough about me. 51 00:03:04,080 --> 00:03:05,720 You, let's talk about you. 52 00:03:05,720 --> 00:03:07,920 I mean, everybody knows who you are. 53 00:03:07,920 --> 00:03:09,740 It's really awesome to have you. 54 00:03:09,740 --> 00:03:11,220 Thank you very much. 55 00:03:12,220 --> 00:03:14,360 So let's get started. 56 00:03:14,360 --> 00:03:28,840 So I am I am really excited to to introduce three major tools, but really a whole suite of tools that I guess I've been working on for my entire life. 57 00:03:28,940 --> 00:03:40,610 Every six to 12 months, I seem to rebuild part of these tools in order to do something with the Internet and the Web that I want to do, but can't given the way the Web works. 58 00:03:40,610 --> 00:03:50,230 So over the course of the past 20 plus years, I've been crafting and honing my strategy for manipulating Web stuff. 59 00:03:50,230 --> 00:03:59,530 And over the course of the past year, year and a half, I've started to to to to focus those into a few projects to see how good I could make it. 60 00:03:59,550 --> 00:04:02,610 And I'm really happy with what I've got. 61 00:04:02,610 --> 00:04:07,150 So today I'm talking about three major projects. 62 00:04:07,570 --> 00:04:13,510 Hackium is the one that's going to be most interesting to most people because it feels like a browser. 63 00:04:13,750 --> 00:04:26,470 But Shift Refactor and Shift Interpreter are much more technically complex and give you the ability to to to mold and twist JavaScript like you're a magician. 64 00:04:27,570 --> 00:04:36,730 JavaScript, I know, is not always the most well-respected language in security circles, but you can't get away from it on the Web. 65 00:04:36,730 --> 00:04:39,030 JavaScript is what you got and you have to deal with it. 66 00:04:39,030 --> 00:04:53,550 And when more and more business logic is showing up in websites, you have to understand more of it because what is transmitted from a Web page to a server is becoming less and less understandable on its own. 67 00:04:53,550 --> 00:05:07,130 So all these tools together give you the ability to manipulate Web stuff, understand Web stuff and transform Web stuff so that you can just control it better, which is awesome. 68 00:05:07,130 --> 00:05:12,070 So this session, I'm going to be going over three or four major topics. 69 00:05:12,070 --> 00:05:15,250 I'm going to be talking about what Hackium is. 70 00:05:15,290 --> 00:05:21,590 I'm going to be going over the REPL and the initialization command and configuration so you can get started. 71 00:05:21,590 --> 00:05:37,890 And then I'm going to be going over how to use Hackium with external services like 2CAPTCHA to solve CAPTCHAs and also how Hackium generates human behavior to make it bypass trivial defenses more easily. 72 00:05:37,890 --> 00:05:48,940 And finally, going to be going over how to use Hackium with Shift Refactor and Shift Interpreter to automatically programmatically deobfuscate JavaScript. 73 00:05:48,940 --> 00:05:51,500 Hackium is a command line tool. 74 00:05:51,500 --> 00:05:53,060 It can act as a browser. 75 00:05:53,060 --> 00:05:55,080 It's an automation framework. 76 00:05:55,120 --> 00:06:01,260 It is a foundation for building Web hacking stuff. 77 00:06:01,620 --> 00:06:03,540 So Hackium is a Node.js library. 78 00:06:03,540 --> 00:06:06,120 It is installable via NPM. 79 00:06:06,560 --> 00:06:15,640 You can install it via npm install-g hackium, which will install the Hackium library and the command line tool globally. 80 00:06:16,540 --> 00:06:18,460 Install Hackium. 81 00:06:18,840 --> 00:06:22,080 npm install-g hackium. 82 00:06:24,780 --> 00:06:28,760 NPM will do all of the stuff that it needs to do. 83 00:06:28,760 --> 00:06:32,920 It's downloading Chromium R782078. 84 00:06:33,080 --> 00:06:40,740 So Chromium is downloaded via Puppeteer right now, and it's a bundled Chromium that is guaranteed to work with that particular version of Puppeteer. 85 00:06:40,740 --> 00:06:50,980 Hackium started as a bunch of Puppeteer scripts that grew and were extended and copied over and over again over the course of a long period of time. 86 00:06:51,580 --> 00:06:59,480 And for the time being, Hackium extends a lot of Puppeteer's functionality and reuses the bundled version of Chromium. 87 00:06:59,480 --> 00:07:10,160 And it will continue to do this for as long as possible until the code bases of each diverge in a way where code reuse is no longer possible. 88 00:07:10,160 --> 00:07:14,300 All right, so now we have Hackium installed locally. 89 00:07:14,300 --> 00:07:16,900 Version 1.0.4. 90 00:07:16,960 --> 00:07:22,500 We start that up, we get what looks like a normal Chrome browser. 91 00:07:22,500 --> 00:07:27,000 Since we have Hackium running, we can use it just like we would any browser. 92 00:07:27,000 --> 00:07:34,740 Comes with one extension pre-installed as the Puppeteer extension bridge, one of the dependent projects for Hackium. 93 00:07:34,740 --> 00:07:41,900 This allows Hackium to communicate to and from the Chrome extension API. 94 00:07:41,900 --> 00:07:59,680 So Hackium also exposes all the Chrome extension API to Node.js scripts and automation scripts, so that you have access to a lot of additional functionality that is normally inaccessible from command line scripts. 95 00:07:59,680 --> 00:08:06,280 So Hackium also includes an in-page client for plugins and functionality to hook onto. 96 00:08:06,280 --> 00:08:16,680 So there's a consistent way to share and communicate between the extension and the automation script behind Hackium. 97 00:08:16,680 --> 00:08:21,780 So we can use the event bridge to communicate with the extension. 98 00:08:21,780 --> 00:08:26,440 We can post messages back to our automation script. 99 00:08:26,440 --> 00:08:31,780 And if we had anything else on here, we'd be able to access them. 100 00:08:31,780 --> 00:08:35,980 So Hackium also exposes a REPL to the command line. 101 00:08:35,980 --> 00:08:40,400 Let's see, we have access to page, which is our active page. 102 00:08:40,400 --> 00:08:49,800 page.gotoHPSexample.com Let's go back to Google. 103 00:08:53,930 --> 00:08:59,030 So you can use the REPL to do everything that you would normally do within a Puppeteer or Hackium script. 104 00:08:59,030 --> 00:09:07,010 Here we are typing into the input that has the attribute aria-label="search". 105 00:09:07,010 --> 00:09:18,190 We're typing Hackium with a new line at the end to basically just search for the term Hackium in Google's website. 106 00:09:18,230 --> 00:09:21,010 So this is a good way to experiment with automation. 107 00:09:21,010 --> 00:09:29,790 And you can also get out of here and use the REPL history to get a recording of everything that you've typed. 108 00:09:29,790 --> 00:09:37,010 So you can just copy and paste these directly into a Hackium script and share these with other people. 109 00:09:37,010 --> 00:09:49,750 The shareability was a very, very high priority for Hackium because historically it's been pretty difficult for people to share their work manipulating websites. 110 00:09:49,750 --> 00:10:04,590 If I were to make something neat that manipulated Google.com or change the functionality of Spotify or Twitter or whatever else, it would be fairly difficult for me to just quickly share that with somebody else. 111 00:10:04,590 --> 00:10:10,510 There are two main ways that people have historically manipulated websites. 112 00:10:10,510 --> 00:10:17,210 And that's either via the embedded browser dev tools or with a proxy or both. 113 00:10:17,210 --> 00:10:28,370 So a proxy would give you access to intercept and manipulate and change any transactions for the web, which is very, very powerful. 114 00:10:28,430 --> 00:10:43,310 But if you've worked with proxies extensively in the past, you know that they can be somewhat of a pain to install, especially if you're talking about different platforms, Windows, Mac, Linux, or whatever. 115 00:10:43,310 --> 00:10:48,930 And if you do go this route, then chances are you have a favorite proxy. 116 00:10:49,050 --> 00:10:59,830 And if you try to share it with somebody else, they've got a different favorite proxy or a different configuration for the same proxy or something that makes it difficult to just quickly share your work with somebody else. 117 00:11:00,450 --> 00:11:14,410 Now, if we do a lot of our work within the embedded browser developer tools, which are extremely powerful and fantastic, definitely, we have no way really whatsoever to share that with anybody else. 118 00:11:14,470 --> 00:11:16,370 A lot of the work is manual. 119 00:11:16,370 --> 00:11:19,990 It's difficult to automate if it's possible to automate at all. 120 00:11:19,990 --> 00:11:28,910 There are like content snippets and other little things that you can use to repeat repetitive work. 121 00:11:28,910 --> 00:11:30,470 But those aren't easily shareable. 122 00:11:30,470 --> 00:11:33,810 They're not easy to really configure in the first place for yourself. 123 00:11:33,810 --> 00:11:36,690 And all in all, it's kind of a pain. 124 00:11:36,690 --> 00:11:45,030 When you do this work, you get all set up yourself, and it becomes difficult for anyone to use your stuff. 125 00:11:45,170 --> 00:12:03,590 So with Hackium, it was a priority for me to get everything as self-contained and bundled into one project as possible, so that if you wanted to, you could share just a small configuration implementation to anybody, and they can see what you've done. 126 00:12:03,590 --> 00:12:19,090 One of the important aspects of shareability is making sure that the user this is destined for doesn't have to know anything secret or magic about your configuration to get up and running. 127 00:12:19,510 --> 00:12:31,670 So we take care of that with Hackium by making a lot of the base configuration stored in a configuration file that is just JSON or JavaScript and is portable so that you can deliver it to anyone else. 128 00:12:31,670 --> 00:12:35,930 You can initialize one easily just by using Hackium init. 129 00:12:36,370 --> 00:12:40,670 You can set up the URL you want to go to by default. 130 00:12:40,730 --> 00:12:47,690 You can configure whether or not you want DevTools to open automatically, which might be important for your script if you're communicating with DevTools. 131 00:12:47,730 --> 00:12:50,150 We are not going to do that here. 132 00:12:50,150 --> 00:12:53,470 We can create a blank JavaScript injection. 133 00:12:53,470 --> 00:13:18,230 One of the other top priorities for Hackium was to make sure that it was as trivial as possible to inject JavaScript before anything else is loaded, which is the only way that you can guarantee a pristine, stable environment for your code, and to also make it trivial to intercept and manipulate content coming in so that you didn't need a proxy at all. 134 00:13:18,230 --> 00:13:26,270 Hackium makes that possible with just generic injection files and interceptor modules. 135 00:13:26,270 --> 00:13:27,430 We're going to say no to that. 136 00:13:27,430 --> 00:13:33,590 We will create a boilerplate interceptor and, sure, a boilerplate Hackium script. 137 00:13:33,590 --> 00:13:44,590 We do not want to run headless, so now we have our hackium.config.js, which is a simple JavaScript file with the configurations that we set up. 138 00:13:44,590 --> 00:13:49,210 We can see that we have a boilerplate interceptor. 139 00:13:49,210 --> 00:13:54,870 An interceptor is just a standard Node.js module that exports two properties. 140 00:13:54,870 --> 00:14:06,410 One is the intercept property, which is an array of request patterns that this interceptor will be configured to intercept. 141 00:14:06,410 --> 00:14:18,310 So here, by default, you can see that we have just a wildcard asterisk for the URL pattern, and we are matching script resource types, and we are doing it at the response stage. 142 00:14:19,270 --> 00:14:31,970 And the second thing that an interceptor needs to export is the interceptor property, which takes a synchronous or asynchronous function that can just do something with a request. 143 00:14:31,970 --> 00:14:35,210 So to share this work, we can just archive this directory. 144 00:14:35,210 --> 00:14:36,590 We can upload it to GitHub. 145 00:14:36,590 --> 00:14:40,770 We can publish it to whatever publishee service you want. 146 00:14:40,770 --> 00:14:48,570 And anyone can download that and run Hackium with just the command hackium and see what you did. 147 00:14:48,570 --> 00:15:01,370 So now that we have gone over the REPL and the getting started, we can jump into what makes Hackium different than other browsers and how to use its APIs to connect to external services. 148 00:15:01,370 --> 00:15:10,290 So if you follow me at all, you know that I talk a lot about automated attacks, things like credential stuffing, scraping, and the trajectory of tools looking more and more human. 149 00:15:10,290 --> 00:15:33,030 Now, since this is a browser that is controlled partially by scripts or extensions or power tools that do stuff, it's important for the behavior that is being generated to look plausibly human so that it doesn't interrupt your browsing and your usage. 150 00:15:33,030 --> 00:15:40,910 So one of the extensions onto Puppeteer that Hackium provides is automatically generated simulated human behavior. 151 00:15:40,910 --> 00:15:51,150 Now Puppeteer and a lot of other automation tools have the ability to slow down behavior so that it doesn't come all puking out on the page all at once. 152 00:15:51,150 --> 00:15:55,930 You don't type large, large blocks of text within a fraction of a second all at once. 153 00:15:55,930 --> 00:15:57,250 You can slow it down. 154 00:15:57,250 --> 00:15:59,530 But still, that's not quite human enough. 155 00:15:59,530 --> 00:16:08,050 Humans don't have consistent durations between key presses or mouse movements that all take a certain number of steps. 156 00:16:08,050 --> 00:16:19,570 So one of the things I did with Hackium was to make sure that things like keyboard events happen at different intervals and durations all within a minimum and maximum expected human behavior. 157 00:16:19,590 --> 00:16:27,010 And things like mouse movements follow non-direct paths and sometimes make mistakes like this. 158 00:16:27,010 --> 00:16:29,110 So this is a slow, meandering move. 159 00:16:29,110 --> 00:16:33,510 You can see down over here, I kind of have to curve up to get to the point we're looking at. 160 00:16:33,830 --> 00:16:34,930 Refresh again. 161 00:16:34,930 --> 00:16:36,750 A random, larger curve. 162 00:16:37,050 --> 00:16:38,510 Much slower this time. 163 00:16:38,510 --> 00:16:40,830 We also overshoot and have to backtrack. 164 00:16:41,210 --> 00:16:42,290 Do this again. 165 00:16:42,290 --> 00:16:44,030 Overshoot and backtrack. 166 00:16:44,030 --> 00:16:50,510 Now things that, where if you're looking at it, it would not definitely be automated behavior. 167 00:16:50,750 --> 00:17:00,910 This is important because just naive automation detection techniques will check to see whether or not you're clicking consistently at like a 0, 0 position on every element. 168 00:17:00,910 --> 00:17:06,070 Or if you're zipping from one point to another with no mouse move events in between. 169 00:17:06,110 --> 00:17:09,650 Or if you're moving all on a straight line or at the same velocity. 170 00:17:09,650 --> 00:17:10,910 Things like that. 171 00:17:10,910 --> 00:17:19,910 So we have to account for that so that we can generate behavior that is not automatically blocked by everything that's out there. 172 00:17:19,910 --> 00:17:27,270 Now another thing that you'll probably know if you follow me is that I hate CAPTCHAs. 173 00:17:27,430 --> 00:17:30,110 CAPTCHAs are just such a pain in the ass. 174 00:17:30,110 --> 00:17:33,050 Most of them are really, really, really bad. 175 00:17:33,050 --> 00:17:40,850 And things like ReCAPTCHA, Google's ReCAPTCHA, seem like they've gotten much, much worse over time. 176 00:17:40,850 --> 00:17:47,990 Things like the little grid of pictures where you have to determine what a fire hydrant is or what a bus is, crosswalk, things like that. 177 00:17:48,410 --> 00:17:49,630 They're a pain. 178 00:17:50,010 --> 00:17:56,570 And CAPTCHAs are things that will pop up in the way of automation all the time. 179 00:17:57,070 --> 00:18:03,490 And it's an arms race back and forth trying to make an automated tool that bypasses CAPTCHAs. 180 00:18:03,490 --> 00:18:08,130 Then CAPTCHA makers get that tool, figure out how to block it, blah, blah, blah. 181 00:18:08,130 --> 00:18:23,810 Now rather than build in any CAPTCHA solving within Hackium, it's much easier to delegate that responsibility to services and companies whose core purpose is solving and bypassing CAPTCHAs. 182 00:18:23,810 --> 00:18:36,090 So you can wire up services like 2CAPTCHA very easily within Hackium scripts just by using standard node libraries and node modules to make requests and parse JSON responses. 183 00:18:36,090 --> 00:18:39,370 So this is a script that I put together. 184 00:18:39,370 --> 00:18:44,630 I am sucking in my API key here just so you don't see it. 185 00:18:45,230 --> 00:18:50,930 And next we're going to go to HTTPS old.reddit.com slash login. 186 00:18:50,930 --> 00:18:56,550 We are going to initiate a CAPTCHA request with our API key. 187 00:18:56,670 --> 00:18:58,450 We get a request ID. 188 00:18:58,450 --> 00:19:03,270 And then we type in our username into the user reg input. 189 00:19:03,270 --> 00:19:05,730 Samuel Clemens 90210. 190 00:19:06,110 --> 00:19:10,230 We type in our password twice on the password inputs. 191 00:19:10,430 --> 00:19:12,550 Ctechastronomy is our password. 192 00:19:12,690 --> 00:19:16,170 And then we pull for request results. 193 00:19:16,170 --> 00:19:19,430 So the way these CAPTCHA solvers work is that you send a request. 194 00:19:19,430 --> 00:19:21,050 It's like, hey, solve this CAPTCHA. 195 00:19:21,050 --> 00:19:25,110 And then you pull for a response for when that CAPTCHA is done. 196 00:19:25,110 --> 00:19:26,590 So you're just not sitting there waiting. 197 00:19:26,590 --> 00:19:33,170 You can do additional work while that CAPTCHA is being solved. 198 00:19:33,490 --> 00:19:43,610 So after we have solved that, we input the CAPTCHA response to an element on the page, g-recaptcha-response, and then we submit. 199 00:19:43,610 --> 00:19:51,610 Now we can run this script, hackium-e-index.js. 200 00:19:53,550 --> 00:19:55,250 It'll pop up in Hackium. 201 00:19:55,250 --> 00:19:58,230 Go to reddit.com's signup page. 202 00:19:59,110 --> 00:20:05,030 Notice how the keyboard typing is not instantaneous, but it's not consistently slow. 203 00:20:05,030 --> 00:20:06,790 It's kind of a blah blah blah. 204 00:20:07,170 --> 00:20:10,630 That's the technical term for that. 205 00:20:10,630 --> 00:20:12,870 So now that we're done, we're going to pop over to the console. 206 00:20:12,870 --> 00:20:19,770 See that we're waiting an initial timeout for two CAPTCHA. 207 00:20:19,770 --> 00:20:21,270 And then we are done waiting. 208 00:20:21,270 --> 00:20:24,530 So now we're pulling for our response. 209 00:20:25,310 --> 00:20:31,250 And now that we're done, pop over to the web page and bam, Samuel Clemens 90210. 210 00:20:31,250 --> 00:20:32,750 We are on Reddit. 211 00:20:32,750 --> 00:20:39,610 We are able to, I don't know, prop up whatever political candidate we are interested in this election cycle. 212 00:20:39,610 --> 00:20:45,630 And this is just one technique for getting by all the different defenses out there. 213 00:20:46,010 --> 00:20:48,010 And I want to make this clear. 214 00:20:48,010 --> 00:20:50,390 I do currently work at Shape and F5. 215 00:20:50,390 --> 00:20:54,490 Hackium is not a tool designed to bypass security defenses. 216 00:20:54,490 --> 00:20:59,670 Security defenses for things like credential stuffing or spamming or scraping. 217 00:20:59,670 --> 00:21:06,510 Those operate at high volumes. 218 00:21:06,890 --> 00:21:16,470 And the type of work that a legitimate and curious hacker using Hackium would do is much, much smaller volume. 219 00:21:16,470 --> 00:21:22,470 So that you can bypass things at small volume, but you'd be caught at high volume. 220 00:21:23,930 --> 00:21:26,390 Cover my ass. 221 00:21:26,390 --> 00:21:26,970 All right. 222 00:21:26,970 --> 00:21:33,730 So, so far I've talked a bit about just basic usage of Hackium with the REPL and other stuff. 223 00:21:33,730 --> 00:21:43,830 I talked about the extensions it has in order to make it look more human driven, as well as showed an example of how to tie it to other services. 224 00:21:43,830 --> 00:22:04,630 And I haven't even touched at all on the other parts of the suite of tools, Shift Refactor and Shift Interpreter, nor have I talked really much about the whole point I made at the start, which is about manipulating website content, which leads me into Hackium Interceptors. 225 00:22:04,630 --> 00:22:16,670 So Interceptors, like we've already gone over, are just basic node modules that intercept a particular URL or request pattern and just do something with it. 226 00:22:16,670 --> 00:22:23,370 You can use the Hackium init command to initialize some basic interceptors. 227 00:22:23,370 --> 00:22:26,030 I'll call ours interceptor.js. 228 00:22:26,030 --> 00:22:35,870 We can use a basic interceptor template, which just doesn't really do all that much, just gives you the boilerplate. 229 00:22:35,870 --> 00:22:40,550 A pretty printer, which uses Prettier to format JavaScript. 230 00:22:40,550 --> 00:22:45,090 So we're going to start a basic transformer using Shift Refactor. 231 00:22:45,310 --> 00:22:55,270 So Shift Refactor is a library I created that makes it easy to query and transform nodes of a JavaScript AST. 232 00:22:55,270 --> 00:23:02,870 An AST, an abstract syntax tree, is just a data structure that represents something that was parsed. 233 00:23:02,870 --> 00:23:10,510 So the AST I'm talking about is just a big old JavaScript object that represents JavaScript source code. 234 00:23:10,510 --> 00:23:18,410 You can use a tool like AST Explorer to just paste JavaScript in and see what AST it generates. 235 00:23:18,410 --> 00:23:25,090 So you can pop through each of the nodes and see what types they are, see how they're structured. 236 00:23:25,090 --> 00:23:32,230 And if you change any of those and regenerate source from that AST, then you change the JavaScript source. 237 00:23:32,230 --> 00:23:48,290 So Shift Refactor takes JavaScript source, parses it into an AST, and then analyzes the scope tree, creates parent mapping, basically does a lot of legwork that makes it easy to do queries and translation on it. 238 00:23:48,290 --> 00:23:56,350 It also leverages Shift Query, which allows you to query a JavaScript AST with CSS-like selectors. 239 00:23:56,350 --> 00:24:01,130 And I modeled Shift Refactor based off of the jQuery API. 240 00:24:01,130 --> 00:24:06,090 So it actually feels very, very similar to navigate and traverse and replace large trees. 241 00:24:06,930 --> 00:24:14,410 So we have a script object based around our parsed response body. 242 00:24:14,890 --> 00:24:21,350 This expression replaces all console log expressions with alert calls. 243 00:24:21,350 --> 00:24:28,110 So we make a query for call expressions that have an object name of console and a property of log. 244 00:24:28,110 --> 00:24:33,690 And we replace those with call expressions for alert. 245 00:24:33,690 --> 00:24:38,330 And we translate the arguments from the console to the arguments for the alert. 246 00:24:38,330 --> 00:24:50,350 As I'm breezing through this, I know that I am glossing over some fairly complex topics, if you haven't played with JavaScript ASTs before. 247 00:24:50,370 --> 00:24:53,450 But I can't stress this enough. 248 00:24:53,450 --> 00:25:07,070 Despite all the crazy terms and syntax like call expression and callee and identifier expressions and some more that you'll see, those are just nodes of a JavaScript tree. 249 00:25:07,070 --> 00:25:14,910 And all you're dealing with is a gigantic JavaScript tree in a similar way that you would navigate or traverse the DOM. 250 00:25:14,910 --> 00:25:24,230 So it might look foreign at the start, but don't let that dissuade you from jumping into this because it's not difficult to get a hold on it once you get the practice in. 251 00:25:24,230 --> 00:25:35,030 So here we've got a basic web page that exists only to simulate a real world scenario, because I'm going to be jumping into programmatically de-obfuscating JavaScript. 252 00:25:35,030 --> 00:25:39,010 And there are plenty of real world examples out there. 253 00:25:39,010 --> 00:25:44,910 And you probably have seen a few of those if you've been looking through a web page source. 254 00:25:45,130 --> 00:25:55,030 But we run into some sketchy legal ground if I'm de-obfuscating that live in front of people. 255 00:25:55,030 --> 00:26:11,970 So we've got a nice little sample website here that I've crafted to look like a payment form that has a, conveniently, an obfuscated bit of JavaScript just floating around on it. 256 00:26:11,970 --> 00:26:28,070 This is a sample of obfuscated JavaScript that was obfuscated via obfuscator.io, which is a pretty common JavaScript obfuscation website because it's the first URL that pops up when you search for JavaScript obfuscator. 257 00:26:28,070 --> 00:26:31,210 It actually does a pretty good job at obfuscating JavaScript. 258 00:26:31,210 --> 00:26:32,630 It can inject dead code. 259 00:26:32,630 --> 00:26:35,850 It can shuffle things. 260 00:26:36,210 --> 00:26:42,430 But it is extremely difficult to protect JavaScript. 261 00:26:42,950 --> 00:26:51,970 And obfuscation really doesn't actually put all that much of a barrier in front of an adversary trying to understand the JavaScript. 262 00:26:52,870 --> 00:27:01,550 So we're going to go through and show how this can be completely reversed and sent to the browser before the browser even gets it. 263 00:27:01,550 --> 00:27:06,610 So it looks as though you are browsing the web with de-obfuscated JavaScript. 264 00:27:06,610 --> 00:27:09,430 So this is using Firefox's DevTools. 265 00:27:09,430 --> 00:27:13,250 Even if we pretty print this, it's not all that much more readable. 266 00:27:13,490 --> 00:27:20,590 You see here that we start off with a list of encoded strings, clearly encoded strings. 267 00:27:20,690 --> 00:27:27,410 We are followed by a variable declaration that, I don't know, does stuff. 268 00:27:27,410 --> 00:27:30,910 It has an alphabet here. 269 00:27:30,910 --> 00:27:36,870 And given that these are encoded, this is probably the decoder. 270 00:27:36,910 --> 00:27:43,590 I would go down here and we see references to that function all over the place. 271 00:27:43,590 --> 00:27:50,930 So 0x227, 0x227a, 227a, 227a, 227a, 227a. 272 00:27:50,930 --> 00:28:03,850 This is a common method of making it more difficult for somebody to immediately understand what is going on with JavaScript. 273 00:28:03,850 --> 00:28:12,850 So I've created a complete interceptor here so that I don't have to code in front of all of you because that's not very exciting, is it? 274 00:28:13,370 --> 00:28:19,850 So we've set our URL pattern to the vendor file that I had on my local server. 275 00:28:19,850 --> 00:28:35,430 And we have fleshed out the interceptor so that we are running it through refactor and also loading up our interpreter via shift interpreter and massaging some JavaScript. 276 00:28:35,630 --> 00:28:37,930 So refactor, we already went over a little bit. 277 00:28:37,930 --> 00:28:42,890 We are sending it the response body and we're also adding a common methods plugin. 278 00:28:42,890 --> 00:28:54,570 Next, we are creating our interpreter instance and we're loading the scripts AST and we are passing it a context that we are requiring in from here. 279 00:28:54,570 --> 00:29:01,090 So the context is like the set of global variables that are accessible by JavaScript. 280 00:29:01,190 --> 00:29:07,530 And by default, this interpreter doesn't have anything in its global context. 281 00:29:07,530 --> 00:29:14,130 So if we want to expose things that the interpreter needs, then we're going to have to explicitly set them. 282 00:29:14,130 --> 00:29:15,090 And we can do it ourselves. 283 00:29:15,090 --> 00:29:17,290 It's just a plain old JavaScript object. 284 00:29:17,470 --> 00:29:29,530 I've put together a fairly basic and simple DOM lookalike context that uses JS DOM in order to simulate a browser DOM. 285 00:29:29,530 --> 00:29:44,410 So if you're interpreting browser side JavaScript, it'll have access to things like image elements, A to B, B to A, URL, URI decode something, whatever, all those things. 286 00:29:44,410 --> 00:29:52,770 One of the interesting things about this interpreter is that it was designed so that it can take statements or expressions piecemeal. 287 00:29:52,770 --> 00:30:02,990 So you don't have to execute a script statement by statement, expression by expression in the flow that a script would expect to be executed in. 288 00:30:02,990 --> 00:30:12,990 You can take any statement or expression out of the AST and pass it to the interpreter and interpret it as if that was the next expression or statement. 289 00:30:12,990 --> 00:30:22,990 This is very, very handy when you're dealing with JavaScript like the way I'm dealing with it, because sometimes we don't want to execute all the JavaScript. 290 00:30:22,990 --> 00:30:33,810 And we want to just execute only the pieces that we want to reuse so that we don't have to write our own decoder functions or copy and paste anything. 291 00:30:33,810 --> 00:30:41,430 We can just grab it, interpret bits and pieces of it, and then use that to deobfuscate the rest of the script. 292 00:30:41,430 --> 00:30:45,030 So it's like using JavaScript against itself. 293 00:30:45,450 --> 00:30:54,430 So here we're going to run the first statement in the script, which is this. 294 00:30:54,430 --> 00:31:03,660 So this basically primes this variable with these values so that anything else that we execute can access that variable. 295 00:31:04,460 --> 00:31:09,780 Next, we're going to be getting the decoder, which is the second statement there. 296 00:31:09,980 --> 00:31:14,220 Rather than run it directly, we're going to assign it to a variable so we can play with it later. 297 00:31:14,260 --> 00:31:21,240 And we're going to run that decoder statement, which is a variable declaration statement that assigns a function expression to a variable. 298 00:31:22,060 --> 00:31:33,800 Next up, we're going to query the innards of that decoder statement in order to get the first binding identifier. 299 00:31:33,920 --> 00:31:42,140 Now, a binding identifier is an identifier, like a variable name or something like that, that is basically being assigned to or having a value bound to it. 300 00:31:42,140 --> 00:31:48,740 And what that means here is basically we want to get that because we want to know how this function is referenced. 301 00:31:48,740 --> 00:31:51,600 So we're looking for this binding identifier. 302 00:31:51,700 --> 00:31:58,240 See, it's not that complicated once you start poking through and playing around with things. 303 00:31:58,240 --> 00:32:03,280 It sounds weird and scary to some people, but it's not that bad. 304 00:32:04,980 --> 00:32:09,040 Next up, we want to get all the references to that name. 305 00:32:09,040 --> 00:32:11,900 So that binding identifier is called throughout the script. 306 00:32:11,900 --> 00:32:15,780 We want to get all the references, the places where it's called, so that we can do stuff with it. 307 00:32:15,780 --> 00:32:22,000 And we're going to map those references and grab the node of that reference. 308 00:32:22,000 --> 00:32:36,680 So a reference is an object that has a node property in it, which is an AST node, an accessibility property, which tells you whether or not the reference is being read to, written to, or is read right. 309 00:32:36,840 --> 00:32:41,460 So then with those references, they're all going to be like an identifier expressions. 310 00:32:42,040 --> 00:32:44,060 So like, let's see down here. 311 00:32:44,060 --> 00:32:49,080 So an identifier expression is just this bit of code right here. 312 00:32:49,080 --> 00:33:00,920 So we want to get this bit of code, which is the reference where it's being used as an identifier expression as the child of a call expression. 313 00:33:00,920 --> 00:33:09,160 So here we're getting all of the parents of our references, and we're filtering out all of those, looking for call expressions. 314 00:33:09,160 --> 00:33:14,680 That just makes sure that we don't catch any references that aren't call expressions. 315 00:33:14,720 --> 00:33:20,000 I think almost all of them, if not all of them, are in the script, so it's not a big deal, but it's good to be safe. 316 00:33:20,000 --> 00:33:30,220 And we're going to replace all of those with the stringified result of the interpreter value executing those functions. 317 00:33:30,220 --> 00:33:32,260 So we need to JSON.stringify. 318 00:33:32,260 --> 00:33:38,080 So it's a string that contains a string, which is the return value of these functions. 319 00:33:39,520 --> 00:33:41,660 You still with me? 320 00:33:41,760 --> 00:33:46,260 Basically, what we're getting are the decoded values of these strings. 321 00:33:47,020 --> 00:33:50,340 So we've done a lot without actually seeing the effect yet. 322 00:33:50,340 --> 00:33:58,740 Let's comment out these statements so we can see our transformations take effect before we do too much magic. 323 00:33:58,740 --> 00:34:05,120 And then after that, we are printing out the refactored script to the response.body and returning the response. 324 00:34:05,120 --> 00:34:08,540 And bam, we are just about done. 325 00:34:08,540 --> 00:34:11,980 All right, we go automatically to our payment page. 326 00:34:11,980 --> 00:34:13,720 Let's check our resources. 327 00:34:13,960 --> 00:34:15,060 Here's our script. 328 00:34:15,060 --> 00:34:19,940 Still looks mostly the same, mostly because we didn't change those top two statements. 329 00:34:19,980 --> 00:34:26,660 But everything afterward, you'll notice that it no longer has those function calls anymore. 330 00:34:26,660 --> 00:34:31,940 Now you see those computed member access blocks right there? 331 00:34:33,020 --> 00:34:39,440 JavaScript still works, but they're not as easily parsable by at least my brain. 332 00:34:39,440 --> 00:34:46,360 And now that we've translated all the function calls to strings, we no longer need them to be computed anymore. 333 00:34:46,360 --> 00:34:49,460 We can translate them back to static properties. 334 00:34:49,460 --> 00:34:53,880 So instead of blah, square, string, we can do blah, dot, string. 335 00:34:53,880 --> 00:34:55,580 Well, not string, but the actual thing. 336 00:34:55,580 --> 00:34:57,280 You know what I'm talking about. 337 00:34:57,300 --> 00:35:01,520 And this is where those functions that we deleted come into play. 338 00:35:01,520 --> 00:35:06,760 Script.convertComputerToStatic is part of the Common Methods plugin. 339 00:35:06,820 --> 00:35:14,360 And the next two statements there, just delete the two statements above our main script because we don't need them anymore. 340 00:35:14,360 --> 00:35:19,240 The strings have been decoded, and since all the strings have been decoded, we no longer need the decoder function. 341 00:35:19,240 --> 00:35:23,500 So let's get rid of those and clean up our unobfuscated script. 342 00:35:23,580 --> 00:35:24,780 Deobfuscated script? 343 00:35:27,940 --> 00:35:28,820 Undeobfuscated? 344 00:35:29,040 --> 00:35:30,480 I don't know. 345 00:35:32,080 --> 00:35:36,380 So now let's load up Hackium again and check our script. 346 00:35:36,440 --> 00:35:38,880 And nothing's there. 347 00:35:38,880 --> 00:35:40,520 Oh, it is there. 348 00:35:40,580 --> 00:35:42,600 We actually had scrolled down. 349 00:35:42,600 --> 00:35:43,180 We were too low. 350 00:35:43,180 --> 00:35:44,620 But now this is our script. 351 00:35:44,640 --> 00:35:53,580 This is basically very close to the original script, minus some still the identifiers that are still wonky, but not much we can do about that. 352 00:35:53,860 --> 00:35:55,760 But you can see what it's doing. 353 00:35:55,760 --> 00:35:58,180 There's no sort of misdirection anymore. 354 00:35:58,460 --> 00:36:00,240 And it's real code. 355 00:36:01,200 --> 00:36:02,560 That's it. 356 00:36:02,560 --> 00:36:09,260 There's just a few lines of JavaScript that can just completely deobfuscate obfuscated JavaScript. 357 00:36:09,260 --> 00:36:18,720 Now, I'm talking a lot about deobfuscation, but there is a lot you can do with all the JavaScript across the web. 358 00:36:18,720 --> 00:36:38,720 Even a site like Twitter.com has a huge array of user-friendly, intuitive methods that could just provide you with an API to all of Twitter, but it's hidden away in the JavaScript so you can't touch it via the console or anything else. 359 00:36:38,720 --> 00:36:50,700 Now, all you have to do is find out where those beautiful little functions are and just expose them to the global namespace so that you can access them via the console or via hackymscripts or whatever. 360 00:36:50,880 --> 00:37:10,500 And if you're not a JavaScript expert, by exposing to the global namespace, all I'm saying is take a chunk of JavaScript and prepend to it like a window.myExposedVariable equals the stuff you want to expose. 361 00:37:10,700 --> 00:37:11,520 And that's it. 362 00:37:11,520 --> 00:37:26,060 You have an exposed API that you can access easily with hackymscripts, which then allows you to basically tweet via Node.js without using a developer API key or anything like that. 363 00:37:26,060 --> 00:37:28,480 Well, that's about all I can cover in the session. 364 00:37:28,480 --> 00:37:34,760 And we actually smashed a whole lot of content in a very, very short period of time. 365 00:37:35,040 --> 00:37:39,780 But because I was so excited and there's still so much more to talk about. 366 00:37:39,780 --> 00:37:41,580 This is just the tip of the iceberg. 367 00:37:41,580 --> 00:37:46,720 And I just barely dove into what shift refactor and shift interpreter can do. 368 00:37:46,720 --> 00:37:50,300 And I didn't even talk about any plugins. 369 00:37:50,300 --> 00:38:03,440 And I didn't talk about the Chrome extension API, talking with the Chrome DevTools protocol, and all sorts of stuff that I could just talk about for days or hours or so much time. 370 00:38:03,460 --> 00:38:12,240 I'm going to be putting more of this content on YouTube because that's, I guess, how people consume content nowadays. 371 00:38:12,680 --> 00:38:14,660 And I'll probably write some stuff up. 372 00:38:14,660 --> 00:38:18,580 But if you like anything I've talked about, you can follow me on Twitter. 373 00:38:18,580 --> 00:38:20,320 It's at JSOverson. 374 00:38:20,320 --> 00:38:22,800 There's probably a link somewhere nearby. 375 00:38:22,820 --> 00:38:26,560 Actually, I think I should be talking to somebody in Discord. 376 00:38:27,380 --> 00:38:28,720 Talk to me. 377 00:38:28,980 --> 00:38:30,640 But yeah, I like this stuff. 378 00:38:30,640 --> 00:38:36,320 I like making the web do things that I want it to do. 379 00:38:36,580 --> 00:38:39,120 And this is why I built this stuff. 380 00:38:39,120 --> 00:38:41,280 And I hope you enjoy it. 381 00:38:41,280 --> 00:38:42,500 And thank you. 382 00:38:42,500 --> 00:38:44,940 Thank you, AppSec Village. 383 00:38:44,940 --> 00:38:46,460 Thank you, DEF CON. 384 00:38:46,460 --> 00:38:49,500 Thank you, all of you, for watching this. 385 00:38:49,500 --> 00:38:50,860 This has been awesome. 386 00:38:50,860 --> 00:38:52,340 Thank you very much. 387 00:38:52,340 --> 00:38:53,220 Bye.