>>Alright everybody. Thanks for coming here. Um… 10 AM is early. I could barely convince myself to wake up for this talk so I don’t know how you’re doing it. Uh.. I’m Lee Holmes. I’m the, uh, lead security architect for Azure Management and Microsoft. I’m the, uh, author of the Windows Powershell Cookbook and also I’ve been a developer of Powershell since it’s early versions, so you may know me from such parameters as ExcecutionPolicy Bypass or, uh, other such things. So let’s, uh, do some context right here. So you’re an engagement, you, uh, fish somebody. You get inside the network. You find some creds and you got some code execution. So you do a little bit of recon. You find out that the some-somebody has been connecting up to a machine. That machine has one port open. Recognize that one: five nine eight five. There you go. That’s WSMan Powershell. So you got Powershell, you got creds, this is going to be a good day, right? You connect up using Powershell to that machine they’re connecting to. I don’t know, fifteen, twenty commands, that seems a little bit off… but you plow on, you plow on. Who am I? You run that thing, you see that you’re the DNS Administrator. DNS is almost always co-located with active directory, so you’re good. You got creds. You got Powershell. You run a DC as the DNS Admin. Decide to burrow yourself a little bit deeper. You add in another account here but you get- you get an error. That’s kind of weird. So you move on. You try to run kind of one of those traditional download cradles. It doesn’t work either. You get an error that, that you’re in constrained language mode and that you’re not allowed to run that kind of stuff. You’re like, “This is weird.” So I, I’m a DNS Admin. Let me see if I can restart the DNS Server. That works just fine, but then you try to restart WinRM and that doesn’t work. So what’s going on here? Your against, obviously, a target of a completely different category than you’ve run into before. You, my friends, have run into “just enough administration.” Just enough administration is the idea that admins are your attack surface and you cannot treat them as your buddies anymore. So you may say, “Lee, are you saying that we get rids of Admins?” No, no no no. Of course we need admins, but here’s the issue. People make mistakes. Sometimes they’re just bad actors, but the big thing to realize is that everything they can do, an attacker can do as well. All the stuff you see about Powershell is just unauthorized administration, so if you’re worried about Powershell attacks, you gotta be worried about your administrators. So wouldn’t it be great if people didn’t need these huge Admin privs to do their jobs? What if you popped a machine, and you didn’t get all these high value creds that people are leaking everywhere? And what if you didn’t need to give them full domain admin to just manage DNS? What if you could just give them the stuff they needed to do their actual jobs? And, of course, logging. What if everything that happened on a machine got logged and when a bad thing happened you could always go back and take a look. So the answer there is just enough administration. This is based on the security features that have been in Powershell since 2008, so exchange online uses this really, really heavily. They are putting just enough administration based principles to the entire internet. So it’s based on three simple concepts. One is role capabilities. So this is making sure and defining what people are allowed to do when they connect. Then there’s the endpoint which is the configuration that happens when they connect to the machine itself. And then you’ve got the identity. So this is, when they connect, what is the identity that runs the commands that this person is running. So these three things together are what let’s you lock down a machine like crazy. And a good way to think about this, you know your security exposure on a given machine is kind of two things. It’s- it’s the time that somebody has access to the machine, but it’s also the capability of what they can do. So we’ve done a pretty good job as an industry of starting to lock down the time. We’ve got all sorts- sorts of PAM modules and all that kind of stuff that will say, “hey, your - this is just in time admin. You’re only allowed to do, uh, a certain task once you ask for privilege and then your only allowed to do it say between nine and five...” Something like that. So we’re starting to see some good stuff to do this kinda lockdown. Just enough administration is all about the capability. So yeah, sure, if somebody’s got access for a given amount of time, but why do you need to give them full access to the domain controller once a service ticket is open? So combining the two - this is what your attack surface reduction can look like. So it seems like it’s kind of a cool thing, being able to reduce your attack surface by this much. I even, I was talking to this guy on Twitter about it. Um, it was kind of going very slow and it made me realize that some people... are very slow learners. At risk noting. You think you might realize the danger of, uh, admin running amok but obviously not. This thread didn’t make it much further. Now how does somebody actually go through and do one of these “just enough administration lockdowns.” The first part is defining role capabilities. So this is what can a person do? And it really is this simple. You can say that when they connect you import the DNS server module and here are the five cmdlets that they’re allowed to run. But what you could also do is declare your own function so if a built in cmdlet isn’t good enough you can define a function, let’s say “who am I,” and this is the example you saw before. So this is a custom written function that you want to expose. Then you’ve got the endpoint itself. So this is, defining what happens when somebody connects. The key point with just enough administration is that you say the session type is “restricted remote server.” Of course you want to log all the things so you set up a transcript directory. Everything that you do comes and goes through this transcript directory. So you can audit this at all times. I’ll get into the “run as virtual” account in a second. That’s your definition of what identity you want these things to run as. So the run as virtual account is the best one you want to use here. And then you configure the role definitions. So this is me saying that when the DNS admin connects, this can be either a principle or a group. When they connect they get the role capability of, let’s say, DNS maintenance. And that’s really just a reference to what you saw in that last slide. Identity is the big one here. So by default when you connect up with Powershell, the- the identity that you use is the connecting user. So when Lee connects up to a machine, well then that process runs as “Lee whatever.” You can do a named identity. That’s being able to configure a- a very specific domain account. You might need this for some specific reasons. A danger with a named identity, if that endpoint gets popped, then you do have an issue of, well then somebody can steal the creds of that named identity and do stuff with it so you want to be very, very careful with that named identity. A virtual account, that’s kind of what happens in IIS. When you can have a temporary local administrator. Windows handles all the password maintenance. You don’t need to worry about rotating these, nothing else. When DNS Admin connects up, this now runs as a local administrator but just without a password that you have to worry about rotating. And then you have group managed service accounts. These are the same thing as a named identity, but this is the kind of identity that active directory will automatically rotate and manage passwords for you so this a very, very strong option if you don’t want to have to deal with that kind of password maintenance. And what makes things super cool is you can even get really really deep in defined grained proxy control. So you saw there before somebody was able to run and they were able to restart the DNS service but they weren’t able to restart the WinRM service. So here’s an example of somebody restricting restart service and using some parameters that says, “The named parameter, I’m going to lock this down to only the DNS or the DNS cache services.” So you can get super, super hardcore on this. So you might say here, “This is Fort Knox. This is like, what am I gonna do.” This is the impenetrable wall. Somebody’s actually got their stuff together. They’re not a whale. They’re not just, deploying a server with no patience. What can they actually do to start getting some, what can you do if your on an engagement trying to attack one of these things. Turns out there’s a couple things and, uh, I guarantee you everything I- I’m gonna show you next I could be pulling up CallE. I could show you some shells writing, but we don’t have the time for the applause in twenty minutes so I’m gonna skip on that. The first thing is porous, right? I showed you this wonderful world of connecting where machine all you’ve done is exposed Powershell remoting. But realistically you’re going to run into systems where somebody’s still doing things like exposing RDP or Tellnet or something like that. So if you’ve got creds and there’s also letting you use those creds for RDP, well then yeah you just RDP in and whatever. So just enough administration, all it can do is lock down Powershell access. So there’s the first kind of misconfiguration you’re gonna see. But here’s another example. I showed you locking down, you know, a handful of cmdlets. But some cmdlets, they’re not immediately obvious what’s going on. So here’s an example from, uh, “Matt Weeks Script Junkie” where if you expose something like hey I’m gonna give an endpoint where I can join systems into the domain, well hey, if you’re an attacker and you got access to that cmdlet, you don’t have to pick it. You don’t have to add it to the domain that- that the enterprise wants. You could also add it to your own domain and start pu-pushing out malicious group policies or something like that. So the commands are not always obvious. Language mode is another huge one. I showed you back there a- trying to run any script and that didn’t work. Well, here’s an example of somebody trying to make it a bit more friendly and using a version of Powershell called Constrained Language Mode. So constrained language mode at first blush looks like it’s pretty cool. I can’t do arbitrary dot net scripting or anything like that. But the big thing with JEA. This is why constrained language is a bad idea. If you take a look on the right hand side, the way that JEA controls the access, is it places a very big distinction between the functions that you expose to the user and then the capability that you’re allowed to run as part of one of those functions. So if you do constrained language, in constrained language you’re allowed to create new functions, and so all you gotta do is create a new function and that function now can run anything you want. That i-is no longer restricted and so you create a new one and then you’ve completely bypassed anything somebody’s put in when it comes to- to a georestriction on commands. So “no language mode,” if you ever see anything but that - this - they have a complete RCE and, uh, that’s your way in. But, by far, by far, your biggest danger is vulnerable functions. Code, y’know, i-if you saw the- the- the session before and all that, the theory of vulnerabilities is all about the code, right? When you’re letting people expose any sort of functions to untrusted input, they’re gonna make mistakes. Command injection is nothing new about command injection in our industry. It turns out if someone is writing a Powershell function, they can just as easily write a command injection vulnerability when it comes to their functions. So here’s an example of somebody taking user input and then for some reason deciding to call Powershell directly and injecting that user input. Like anything you’re used to in the past, you can put a semi-colon in there and run arbitrary commands. And it’s not just Powershell of course. If they’re calling CMD for some reason you can also input that user input there and get arbitrary CMD injection. By far the biggest thing that you’re going to see though are vulnerable functions. So this is someone doing invoke-expression. And invoke-expression is almost never needed in Powershell itself. Here’s an example of somebody thinking they want to take some user input and then, for example, a process name, and call getprocess with that name and what you’ll normally see is that- that they’re used to doing things from Python r whatever where you do an execcall or a systemcall. So this is somebody trying to do that with getprocess. That’s a bad idea. Invoke-expression says “Powershell I’m gonna give you a chunk of script. Run whatever I give you.” User input can contain semicolons or any sort of download cradle and you’re done there. There’s a bunch of obscure forms of script injection coming here from InvokeScript, CreateNestedPipeline, add script, so make sure to keep your eyes on those. But here’s an example of it being done correctly. It turns out you almost never need invoke-expression in Powershell. Of course in- in Powershell I can do arbitrary user input and just provide that as a variable to a parameter name. If I don’t know the parameter name beforehand I can also dump things into a hash table, the parameters and their values, and do something then called “splatting” that on a command like, that’s the a- at- at sign parameters there. So this is a way to invoke a cmdlet with no parameters that you don’t know beforehand, still without any sort of injection vulnerabilities. And even if you don’t know the cmdlet beforehand you can use the invocation operator and still get the same thing. So this is the- the best approach. This is what people should be moving forward to. But sometimes you’ll see somebody who thinks that there’s aware of the invoke-expression vulnerability and what they decide to do here is, well I’m gonna do giveprocess dash name. I’m gonna escape the user input with single quotes, ‘cause single quotes are kind of the safest kind of thing in Powershell, and the line before that I’m going to escape out single quotes with other single quotes. You see this, people trying to prevent sql injection a lot of times. But here’s the issue. Powershell was raised in a world of Outlook and Exchange and Wordpress where there is all kinds of quotes. There’s curly quotes, there’s back quotes, there’s hanging quotes, there’s like six kinds of quotes in Powershell. The version you see here only escapes one of them. Use any other form of quote and you’re right through this. Sometimes you’ll see script block injection. So script block injection is when somebody wants to take user input and then take that input and run it via Powershell Remoting on another system. So here is somebody who takes that script block at a- based on user input, but they need to create a script block. They do this with a string. That can be injected as well. There’s an obscure form of this as well you see that new script block with the string, that can be injected, so there’s a bunch of ways to make sure you’re not doing that and that’s the approach you want to take. String expansion is another thing that you’ll sometimes see where somebody wants to take a variable and figure out the value of that variable so they use the expandstring API. There’s a couple versions the- of that exposed through execution context as well. That can go through some string expansion vulnerabilities itself and so you don’t have- you don’t want to be using expandstring on user input. The best thing you want to do is use it- the getvariable cmdlet to figure out the current value of a variable. There’s some obscure things here. Method injection if you’re taking user input and using it in the, ForEach cmdlet. You can start running arbitrary methods, arbitrary functions there. Don’t want to make that happen. You’ve got vulnerable functions too. Here’s an example that can really burn a lot of people. If you want to take user input and send it into the addtype cmdlet, well the addtype cmdlet can run arbitrary C Sharp code, so if you ever see anybody taking user input and sending it into the addtype cmdlet, well now you have arbitrary C Sharp, arbitrary access to Win32 APIs and Bob’s your uncle and it’s over. Now that’s a lot to keep in mind. What can you do if you’re actually trying to audit this, or defend against any of these things? Turns out that Powershell is powerful and it’s not just powerful when it comes to all the stuff it lets you do, but every scripting language pretty much goes through two phases when it understands a script. The first thing is tokenizing. So this is an example of tokenizing here, where you give it a command and Powershell actually has an API that let’s you see okay there’s a generic token, there’s a parameter, some left parens, there’s an operator. You could start to do some really smart analysis against the token level of Powershell itself. But on top of every token stream there’s the parse stream which generates an AST. So this is what Powershell has as an AST, which is kind of a tree-like structure of what it interprets the command to be. So you can even do crazy things here like, the value of a parameter, was that a constant expression or was that the result of doing some binary operators on some things. Here’s an example of the powershell AST. There’s a great module on the Powershell gallery that you can just run installmodule on and start browsing through the AST for a different command. So the AST is cool but how is this actually going to get- help you either find issues or prevent issues? And the answer here is there’s a lot of wicked hunting things you can do with the AST. So you see at the bottom here kind of read this one from the bottom to the top. That last line. There’s a method on the AST that let’s you find all things that match a given predicate. So this is doing a tree, a navigation of the tree, looking for anything that matches the predicate that you ask. >>If you want people to read it, we’re going to have to bump the signal for a second because it’s popping up. >>Okay. So hunting with the AST is a really big thing, so that bottom line, just keep it in your- in your mind’s eye. So the bottom line was going through and- the bottom line you can do an AST searcher based on anything that- any predicate that you give. And so the top line... [pause] And so the top line was an example of a predicate that you can do and start to run against all the AST. So this is an example of finding an invokemember AST where the thing being invoked was not a constant expression. Kind of one of those examples. But doing this at scale is a really really hard problem. So that’s why Powershell has the script analyzer. This already is used in things like Visual Studio code and stuff. Everytime you, for example, do an alias or whatever, it can find things like aliases that you could remap to something else. So I can start to take those predicates and write AST rules against arbitrary Powershell scripts but this time based on known script injection vulnerabilities. So, obviously, that’s a great thing to do,so we did it. What we’re releasing now is the Powershell injection hunter that takes every single thing I talked about today and does it for you automatically. So you run Powershell script, uh, script analyzer against these injection rules and then you’re done. This will flag everything that you might be worried about. But even better you’ve got integration with Visual Studio code. You enable this in Visual Studio code and you can see these things while you’re developing your Powershell scripts, anything that might cause an issue when exposed to untrusted user input. [applause] So here’s the thing. If you’re- if you’re on an engagement, make sure you’re testing for administrative complexity, testing for script injection vulnerabilities. But if you’ve got things to defend man up. Use- woman up. Use JEA, use things like that and use script injection hunter to find vulnerabilities. Thanks for your time. Glad you could make it so early. [applause]