- Thank you all for coming.
This is Hacking G Suite: The Power of Dark App Script Magic.
A little bit of background on myself, I'm Matthew Bryant,
I go often by my handle mandatory,
I currently lead the Red Team Effort at Snapchat,
and also outside of work,
I also post occasionally about security on Twitter
@IAmMandatory.
And additionally, I also do hacking write-ups
and research posts at my website, thehackerblog.com.
So, to start us off with some context and background
sort of give a base to what we'll be talking about today.
So Google Workspace, for those of you who aren't familiar,
essentially, this is the new name
that they've given to G Suites.
I know it can be tough to keep up
with all of Google's ever changing brand guidelines
and stuff.
I will still be referring to this as G Suite
throughout the talk,
just because I think most people
are more familiar with G Suite than Google Workspace,
but we know what G Suite is essentially,
is it's sort of the suite of Google services
that people use,
things Gmail, Drive, Calendar, all that stuff.
This is available both for regular users,
personal individuals as well as companies, enterprises.
And this allows people to sort of
if it's a company, for example,
they can collaborate online to get work done
using all of the various Google services.
And at the time of this research,
they were boasting over 2 billion users.
So a ton, a ton, a ton of people use this stuff.
So for those of you who aren't familiar with Apps Scripts,
apps script is essentially this,
basically JavaScript language
that is just used to write these server-less JavaScript apps
that run on Google infrastructure.
And it's kind of this custom way to build apps
where it's highly optimized for automating Google services.
It comes with a lot of really useful libraries
when it comes to automating everything
from Google docs, to Gmail,
to any sort of Google service you can think of.
And on top of having all these prebuilt libraries
it has the seamless integration
with Google's app registration system
and sort of their OAuth system.
So normally when you set up a new OAuth app with Google,
you have to set up a callback URI,
and can figure your app to work with it
and all sorts of these, all sorts of these things.
But when you use Apps Script,
that's all sort of magically done for you.
All this authorization stuff is just sort of handled
and it sort of automatically takes care of it.
So it also offers a variety of triggers that you can use
to start your little scripts that you write.
So everything from somebody hits the web endpoint
that kicks off the script
to that they've opened a Google Doc
and something's running at the beginning of that
to schedule a cron, sort of cron-style things.
where you have scheduled execution jobs
and stuff of that nature.
This is an example of a screenshot
of the Apps Script Editor.
You can see it's actually pretty full ID environment.
It has everything from code completion to breakpoints,
debugging, all the stuff that you'd kind of expect
from your regular dev.
So Google's OAuth system
is very similar to a lot of the OAuth systems out there.
Essentially the idea is, it's a system that's built
to sort of allow these third-party apps
built by whatever individuals
to request access to resources that Google users
have in their account.
So for example maybe I have some Google Docs in my account
and I wanna automate something for these Google Docs
using a third-party app.
This allows me to basically delegate access
to my Google Docs to this third party app to do that for me.
So these permissions to these resources,
they're essentially known as scopes
and there're over 250 of them.
And so these are for all of the various Google services
that you can think of, right?
So everything from BigQuery, Gmail, Google Docs,
stuff like that.
The way that it works, right,
is you sort of your app will redirect them
to an authorization prompt
that gives them a brief summary
of what you're requesting permission-wise.
And the user can kind of think it over and decide,
"Yep, I'm gonna allow that"
or "No, I'm gonna reject that".
And if they allow it,
essentially your app gets handed some tokens,
which you can then use to talk to these APIs,
authenticate as the user.
So as I mentioned that prompter,
this is what that looks like.
You have sort of a human-readable little summary here
in this case, this example app,
it has "Hey, this is gonna request access
and if you allow it,
it will have access to your Gmail stuff,
it'll have access to Google Cloud and everything in it."
And also it's asking for permission to sort of run
when you're not present.
So it's not just a one-time thing,
in the future it could just keep running, indefinitely.
So tying all these concepts together
and thinking about things at a higher level,
and this becomes a pretty effective option
when it comes to targeting organizations or companies
that are sort of on the G Suite stack,
Apps Script becomes pretty attractive option
for things like phishing, targeted spear phishing,
as well as say you've already compromised,
an individual employee account in a G Suite org.
It becomes a very attractive option for backdooring
that account as well.
And the reason why it's an attractive option is because,
if you have an Apps Script implant,
it's actually sort of outside
of the eyes of all the regular machine-monitor controls
that run people's end machines and their laptops and stuff
so regular antivirus, their endpoint detection tooling,
and sort of on device monitoring,
none of that's really effective here,
because again it runs completely enclosed infrastructure.
It's like a total service environment,
so that they don't have any visibility into that at all.
And even better,
you have your victim wipes their laptop for some reason,
your implant is completely unaffected,
just totally remains with full access to their account.
So another thing that's interesting,
if you think about some of these companies
that have sort of these extremely hardened environments
Apps Script becomes an interesting option even then.
So when I'm talking, when I say hardened environments,
what I mean is companies with things
like mandatory hardware, U2F on logins,
so places where traditional credential phishing
just isn't gonna work because they have a hardware key
that they actually have to hit in order to login.
Things like they have hardened Chromebooks
with lockdown enterprise policy.
So you don't have things,
you can't get a binary implant running on there.
You got to key in even to get to the Chrome extensions,
potentially if they have lockdown enterprise policy
and they have hardware attestation
and all that other good stuff, right.
So super-lockdown environments.
And so getting around these measures
we've got to think a little bit more clever
than your average attacker.
This isn't like the casual
Windows Networking style pen tests
that are potentially more common.
This is a completely sort of unique environment.
And so we'll have to be a little bit more unique
in how we think about and how we approach these things.
So I'm gonna go into some historical precedent here.
One thing that I think is a particularly interesting example
is the attack that happened a few years ago,
which was essentially basically built around using,
Google's OAuth and API system.
Some of you may recognize this screenshot here,
if you were one of the individuals
that was affected by this,
but essentially this was what was later dubbed
as the Google Doc worm.
So the way that this worked
is it would essentially this worm
would basically send these phishing emails,
looking like this.
And you know, this would be from somebody
you personally knew coming from their actual email address.
And it would say, "Hey, your friends has invited you
to view a document."
And it would give you this button to, sort of like,
"Okay, let's open that document",
but when you actually went and did that,
it would actually present you with this OAuth prompt here.
And it says, "Hey Google Docs
wants to have access to read, send, delete
and manage your email, and also access all your contacts."
Now of course, for security people watching this,
they're like, "I would never approve that prompt",
but for the average user,
they're sort of looking at this
and they're like,
"Okay, Google docs wants access to my Gmail and contents.
Yeah, I mean, I thought they would already have that,
sure, why not?" right.
And they would probably go through
and just go ahead and approve this.
So it's sort of very, very convincing attack
for a lot of the regular computer users.
Of course, if they did do that
and they did authorize this app
to have access to their Google account,
what would it immediately then go do
is it would use the contact access
to essentially get their a thousand most recent contacts.
Their emails, their friends
and coworkers and stuff like that.
And it would send out this exact same phishing email,
as them, to all of their friends and contacts.
And this would basically repeat the cycle
where they would then get that phishing email
that we saw before, right.
The impact of this attack was actually pretty impressive.
It ended up spreading like wildfire
and essentially it actually affected
over a million Google users.
And this is everything from your personal Google users,
like you and me,
to sort of the big enterprise business users,
sort of the G Suite organizations.
And Google sort of rapidly responded to this
actually they had really good response time.
They did everything from like killed the emails
that were spreading around,
killed off all the apps and stuff like that.
And they did all of this in a couple hours
and after doing some post-mortem analysis
on basically the JavaScript
that was used to control and run this attack,
it turns out the coding for it,
was actually pretty amateur, right?
It wasn't this advanced crazy nation state thing
that most people assume.
And it essentially it looked like
it was only collecting email addresses.
So all things considered this attack
could have been, much, much worse.
It almost seemed as if,
you know somebody said it was actually like unfinished.
So yeah, let's break down this attack
into its kind of core components here.
One, I would say fairly advanced trait that they did
was they did think ahead
and they had multiple rotating apps.
They've registered multiple OAuth apps ahead of time
and they sort of randomized them
along with different domains,
to essentially prevent the easy case of Google
just blocking their app or blocking given domain, right.
They had to instead track on all of the apps
and all the domains and block all of them
to prevent this from spreading.
It made use of some Unicode characters.
Yeah, I saw it earlier,
the app name was actually called Google Drive.
That was because they were basically evading some filters,
which no way prevented you from setting stuff like Google
in the name of the app by using Unicode characters,
which look exactly the same as their ASCII equivalents,
so it was like Google with maybe a Swedish O, for example.
And of course, use the social engineering
and the phishing scheme that we saw,
which was quite convincing to people.
And it actually it self-propagated
and sort of the old-school email spam style, right?
So infect somebody, send to all of their contacts,
some of your friends end up falling for it
and then they'd send it to all their contacts as well,
except, unlike all the email worms of old,
this used some of the more modern OAuth-style
authentication and authorization
to actually carry out these attacks,
as opposed to old school credential harvesting
and stuff like that.
So, as you can imagine,
this was pretty shocking to a lot of companies
and a lot of users.
And so Google made some pretty quick changes
and mitigations after this happened.
Around two months later,
they introduced a G Suite Admin Control
for sort of administrators of companies
to essentially lockdown their orgs.
And the way that this would work
is essentially it, they could publish it,
they could basically set a setting
that says none of my employees are allowed to grant access
to any of their Google account data
for their employee account,
unless it's for one of these explicit OAuth apps
that I've explicitly allowed.
So this would allow you to lockdown
to prevent, you know, say this were to happen again.
Their place just straight up,
would not be able to grant these permissions their account
because it would be blocked,
unless it was whitelisted under this policy.
And Google later introduced what are called
sort of Sensitive and Restricted scopes,
they basically labeled a bunch of these permissions,
as I mentioned before,
as either Sensitive or Restricted,
depending on the kind of data that they would grant.
And in addition to that,
they introduced what's called
the Unverified App warning prompt,
for some of the smaller apps that require these scopes
and they went and they cracked down
a lot of these other misleading OAuth apps, right.
They beefed up their security
around what you can name an OAuth app
to prevent sort of the same exact attack we saw before.
So they couldn't mimic Google-style names
and stuff like that as well.
So just some quick food for thought here,
this attack really didn't utilize
a whole lot of crazy Zero-Day bugs or exploits apart from,
I guess, some of the Unicode trickery for the name,
it was basically kind of using the system as designed.
But the impact was actually incredibly substantial, right?
So that's something to really think about here
is you don't necessarily have to have one big bug
or one exploit to sort of pull off these crazy attacks.
You can simply abuse the system as it was designed.
And the design itself can just lend itself
to attacks like this.
So just something to sort of think about in general
with this, that kind of stock.
So we talked about the history,
let's go into the latest, right?
So we all have mitigations in place,
what can we bypass and what can we do
in this sort of modern age?
So, I talked earlier about the Unverified App prompt.
This is for apps, of course, that ask these sensitive scopes
and there's quite a few of them.
So what essentially, this is not kind of a light warning.
This is a really serious prompt
that actually would dissuade users from continuing.
It kind of takes, it looks a sort of takes some tips
from Google Chrome's UI for in data as a cell,
you know, sites that you visit.
And so the way that the user can actually continue
is they have to click this little text that says
Show Advanced and they have to go down to the bottom
and click through and for the regular user,
this is just not gonna be a tenable thing,
they're just not gonna be able to get through this.
And so it actually poses significant barrier for us
as attackers and our, if we want to phish or use OAuth here.
So what is a Sensitive or Restricted scope?
So that just means any API with the potential to access
sort of private data.
This is everything from Gmail, BigQuery,
Google Cloud, Drive, Calendar it's basically,
it's actually a large percentage of the scope.
So it's over 120 APIs.
And the way that works is essentially if it's a small app,
if it has less than a hundred users,
you have this Unverified App prompts
and if the app is bigger than a hundred users,
you need to go through an even more strict process
where you undergo
sort of this intense manual review process.
And this process is like no joke,
there are companies that you have to use these scopes
legitimately for real-world services that they provide.
And they have written entire postscripts saying,
"It's so hard for us to get past this review process",
So this is the real deal.
And it's definitely not something that we could really cross
if we were an attacker trying to publish a malicious app,
it's just not a tenable route for us,
but there are some exceptions to this policy.
So you take a look at the documentation around this,
essentially if you have,
if it is the case where you have some Apps Script,
or an app, and you use a Sensitive scope
and you fall into any of these categories,
then either the normal OAuth flow
without the Unverified App prompt will happen
or the unverified OAuth flow will happen.
So one of these is particular,
which is the intersection of these two.
And essentially what this says is it says
Hey, if the publisher of this app is in the same G Suite org
as the user who's authorizing it and running it,
then there'll be no Unverified App prompt.
And this sort of makes sense, right?
you can imagine you've got an employee
who works with you,
they've created this app and they then share it with you
and you wanna run it, it doesn't really,
you trust them and it's an internal action.
So it wouldn't really make sense to have this scary prompt,
cause it's sort of used internal
and somewhat implicitly trustworthy.
So that's something interesting
if we could abuse that
we could essentially get around this.
So one other thing to note about Apps Script
is when you have an Apps Script app,
it can be either a sort of standalone project,
a standalone script that runs,
or they can be with what's called
bound to a container,
and by container this means basically
you can bind it to a Google Doc, or a Sheet, or a Slide.
And when you do this, this allows you scripting
to basically you can manipulate the document,
customize the UI, stuff like that.
And the way that works is essentially
the regular triggers I talked about before,
they'll run for any user
who basically has edit access to the Docs,
so they have to have edit access to the Doc
and then they can kick off any of these Apps Script triggers
and sort of run this app.
Keeping in mind, of course,
they still have to accept the OAuth prompts
if they're requesting any scopes.
So if you imagine
sort of our average OAuth phishing scenario, right?
Say we have a Google Doc with some Apps Script
attached to it and we send our victim this link
who's inside of this G Suite org.
When they go to actually they open the Doc
and they trigger it and prompt spawns,
they of course get the
"Hey, Google, hasn't verified this app
suppress the Sensitive scopes.
And so likely the victims would be like,
"Nah, this isn't for me,
I don't even know how to get through this"
and so our attempt is probably gonna fail here, right?
So one interesting thing about Google Docs
and Sheets and Slides and all this stuff,
is that if you change the average URL
that you get from edit to copy,
instead of just directly opening to this document interface,
you'll actually get this prompt instead,
and so this essentially this prompt here says,
"Hey, do you wanna make a copy of, in this case,
Confidential Org-wide Comp & Promo Details?"
And they get a little button that says
Make a copy and when they click this,
what ends up happening is,
it copies the the document, the sheet
into their own Google Drive
and then they're immediately taken
to the the full UI interface for working with the sheet.
And so, going back to the attack I mentioned earlier,
so now if we're an attacker and we send our victim,
this copy link, instead of the regular link,
when they go through this link,
and they click to make a copy of it.
They'll essentially, like it copies into their Google Drive
and then when they trigger
the Apps Script that's attached to it,
they will get the regular prompt
without this Unverified App screen.
And the reason why they get this
is because if you look at the app itself,
you'll notice that the actual developer
behind the app is the victim.
And the reason why it's the victim
is because when they copied that doc,
what they ended up doing
was essentially they became the creator,
because they copied the doc,
they're now the creator and owner of the script.
And so they'll actually see that they themselves
are requesting the permission from themselves.
So there is one problem though, so when you actually copy,
a document with Apps Script attached to it,
the triggers don't come along for the ride.
So they don't really have a way to trigger this thing
to get this prompt to display.
So that's kind of a pain,
so one way that we can get around this problem
is Google Sheets have what are called macros.
And this is sort of something made to compete
with Microsoft Excels VB script style stuff
to manipulate and automate spreadsheets.
But what's useful about the Google Sheets version
is they can call out arbitrary Apps Scripts.
And what's even more useful, is you can actually,
if you have an image or an item in your Google Sheets,
you can assign a macro,
so when somebody clicks on the image,
it will automatically run this macro,
which by proxy runs any arbitrary Apps Scripts
that you want.
So this basically it's a great way
to sort of trigger your Apps Script to payload.
So I've got a little demo here
where you can see the victim
and they go in here and they click, Make a copy,
of this Google Sheets and after they've clicked that button,
you take them directly to your copied sheets.
And you see this beautiful image of this goose
with this butter knife
looking totally not threatening at all.
And when they go to click on that,
they get the authorization prompts
and when they click Continue,
you can see they have the regular OAuth prompt,
no warnings at all.
So essentially bypass that whole restriction
around Unverified Apps,
but that's not actually all that we bypass.
So in addition to bypassing the Unverified App screen,
we've also, I mentioned earlier this,
a little bit earlier in the talk,
but that G Suite Admin setting
that allows you to basically lockdown your organization
to prevent third party OAuth apps
from requesting permissions on your employee's accounts.
This actually gets around that as well.
This entire system is essentially bypassed.
And the reason for that is exactly the same reason
as the reason for bypassing the Unverified App prompts
because the app is owned by,
it's basically when the copy is made into the Google Drive
of the the victim and they're inside the org,
essentially it means that the OAuth app itself,
instead of the new owner, it's an internal app.
So it's not a third-party app. It's actually first-party,
it's inside the org and so this doesn't apply.
This block on all third-party API access,
it doesn't apply, so this is bypassed as well.
So another fun tip for sort of defeating
both the third-party app restrictions
and the Unverified App prompt
is that if you go through the Docs,
you realize that the doc that's attached to the Apps Script
and vice versa, they have the same owner.
And so what's interesting about this
is saying you have somebody who's created
a new Google Sheets or Doc or whatever,
inside of their G Suite domain,
when they've created that
that's actually a kind of a bypass wanting to happen,
because if they share edit access
with anybody outside of the organization,
that person where their edit access can actually go in
and they can then create some Apps Script for that document.
And the owner is still the person
that created the doc, the sheet in the first place, right?
So since that sticks,
now you can essentially use that
to start off your phishing or whatever attempt, right?
Because that will bypass all of the third-party
and Unverified App restrictions
that we talked about previously,
'cause it will be owned
by the employee that first created this document.
So if you can find one of these,
this is a great starting place,
where you can sort of skip the whole copy style attack.
We talked about how to sort of pierce the perimeter.
Now let's go into sort of once you've got some access,
you've maybe a compromised one employee, a G Suite account,
where do you go past then, right?
What can you pivot to,
how can you escalate privileges?
So likely, most companies
I'd say probably the most interesting data they have
is in Google Cloud and so pivoting to Google Cloud
from Apps Script implant seems pretty important.
So accessing Google Cloud through Apps Script
is not super documented,
but you can do it by basically
requesting the scope cloud platform.
And that actually gives you access to all GCP APIs.
So everything from BigQuery to Google Cloud functions,
GCE, all of it, as the user
who basically authorizes access to your app, right?
So the way that you essentially authenticate to these APIs
is you use the Apps Script function, ScriptApp.getOAuthToken
You take that value
and put it in the authorization bearer header,
and you can use that to authenticate to all of the APIs,
but when you do this, there's kind of a gotcha.
So you'll notice that when you try to use this
for the Google GCP APIs,
you're gonna get this warning that says,
"API that you're trying to access,
it's not been used in this project ID,
you know, this number before,
either it's not been used or it's disabled".
So this request is failed.
What's your more strange
is the product number that's displayed.
It's not gonna be for the product
that you're even trying to access.
So what's the deal with this here?
Again, not super-well documented,
but essentially when you create a new Apps Script app
upon that creation,
you're allocated a sort of hidden Google call project.
That's immediately attached to this Apps Script app
associated with it.
And so what happens is this implicitly
binds your API requests that you make
from your access token generated by your implant
with this project.
So it just sort of,
that's why you have this arbitrary product number
it's for this hidden project.
And you, unfortunately, for the hidden project,
you can't access it
via the Google Cloud Control Panel or anything that.
You can't enable services on it, use programmatically,
like you normally would be able to.
And so this is kind of a big problem, right?
Well, it turns out that you can actually get around this
by specifying the x-goog-user-project header.
And you simply specify the product name
that you're trying to query, right?
So if you're going for, you wanna modify a project example,
you do this header and then set it to that value.
That basically looks this, set your product ID
in your API calls and set it in the header.
And then you put your authorization bearer header
to that script,
to the script app that get OAuth token value
that I mentioned before.
And you can go on and you can talk to all the GCP APIs
to your heart's content, right?
It's the data you're looking for, it doesn't happen to be,
the good stuff isn't in Google Cloud,
then it's probably in Google Drive, right?
Maybe more financial, different companies,
all their stuff is in Sheets and Drive.
And so let's talk about sort of mining Google Drive
for the good stuff.
We'll begin with kind of the general overview
of how sharing works in Google Drive.
So by default in G Suite,
there's essentially these three permission levels,
the most restricted sharing settings for a file is that,
only people who are explicitly added to the ACL
are allowed to access the documents.
You've just got to go one by one
and add other users, and to give them access to it,
and if they aren't on the list,
they cannot view the document, right, they can't access it.
So, the second level
is anybody who has a link to the document or the file,
they can access it, so you said you're sharing by link.
So if they have a link, they can access it,
but if they don't, they can't, right.
And then the widest most open setting
is you can even make it so that,
hey, anybody who just searches
inside of the Drive web page,
they can find your internal doc by doing that, right,
if they're also in the company.
So yeah, these are the defaults,
essentially by default,
it has the strictest sharing settings
where you have to explicitly add people,
one click away from that, the most restrictive settings
is share my link with everybody who has the link,
they can access the document
and then if you do more clicks,
you can get it searchable by everybody, right.
And of course once somebody view,
if it is shared by link, right,
and somebody else views it once,
it becomes searchable in the future,
because the assumption is you have the link,
you should be able to find it again,
because you were able to visit it once.
These unique document URLs are outside of the range
of brute forcing.
So if somebody does share my link,
you're not gonna be able to brute force
the actual link itself,
you're gonna have to actually have it.
So we talked about sort of what the default
and what the setting system is,
but real world usage tends to be quite different
than sort of the strictly technical bits, right?
So what actually ends up happening?
So in my experience, usually what ends up happening is,
if a file is important, almost kind of by definition, right?
It's gonna be shared with other people, right?
Other people are gonna view this document.
They're gonna maybe make changes, do adjustments to it.
And so in the strictest security setting
that we mentioned previously the owner of the doc
is gonna have to add into individual users one by one.
And that's a very tedious process,
especially when you have say you're doing it 40 people,
that's very time consuming.
And you can use Google Groups
and sort of put together ACL groups
that can be added in bulk together,
but it's still very tedious process, right.
So what often ends up happening
is people get to a point where they're just like,
they share it with so many people
that they're just like, "Ah, forget it".
Right and they just share by link
with a large,
anybody who has the link, they're good to view it.
So in practice that tends to be pretty, pretty common.
And only a tiny portion ended up being
that wide searchable mode that we talked about before,
just because of the amount of user interaction required.
So, how do we get access to these this big area,
which is stuff that's shared by link?
So of course there's the basic method,
which is just a search all the internally shared systems
inside of a company, let's check the chat,
let's check internal forums.
You got Internal Q&A sites, your ticket management queues,
zero whatever, bug trackers, and try to mine out
and try and look for all this Google Doc Drive links.
And you can do that, but there's also another way to do it,
which is actually the same way that we do it on the web.
How we index and make documents searchable on the web.
And so the way this works essentially is, yeah,
you can have a script which will simply take some seed,
Google Drive links, Google Sheets/Docs links.
It will essentially it'll go through each one of them,
so say you give a Google Sheet,
it'll go through that, it'll parse it.
It'll find all the links inside of a document.
And it will recursively crawl
all of those documents as well,
and look for links inside them and so forth and so on.
Until it essentially is able to enumerate
all of these other documents,
which are sort of indirectly linked
to all these other documents, right?
So I've written an Apps Script Spider
that does exactly this,
which you can essentially do what I just described, right.
Take some seed links, plug it in,
it uses a starting point
and recursively crawls all this stuff
until it's exhausted all the paths
and it gives you along the way it collects metadata
about sharing, document context,
the authors and stuff like that,
so you can essentially, let it run,
gather up all these documents
and you can then look through the results
to see if it has the data that you're looking for.
This is available at this GitHub link here,
so feel free to take a look.
Another useful thing to do
is to basically request Google backaccess
for the people API and so what this is essentially
a G Suite, it ships with this really neat ability actually,
it comes with an internal employee directory.
And so with the people API,
if you request the directory.readonly scope
at a minimum you can access,
you can figure out all the other employees
in the G Suite org, and you can get everything
from names, emails, titles, whatever it is.
And it's becomes extremely useful.
Something that you probably wanna collect early on,
so say you first compromised the G Suite employee.
You wanna use this, to immediately mine all those data out,
because say you get revoked by an administrator
who catches you, or they basically figure out
that you did this phishing campaign and revoke your app,
delete all of your implant stuff.
So having this data is very, very useful for reentry,
because you can make a much, much more well-planned attack
now that you have a good idea of their entire organization,
via this API, so highly recommend this as an avenue.
So let's talk about escalating our privileges, right?
Let's sort of talk about
how we can increase what privileges we have
and get access to more things.
So, one thing that is a very good source
of privilege escalation
is legitimate internal Apps Script apps
that are developed by people
inside of a G Suite organization
that are attached to Google Docs/Sheets/Slides,
stuff like that.
So recall earlier we talked about Apps Script
as being able to be,
we talked about being bound to a doc or a sheet or a slide.
And this file that a script is bound to
is called its container.
And so one of the things we have to ask ourselves
is say you have some Apps Scripts attached to a doc, right?
So in this case, do they have separate ACL?
So, can you make it so they can only edit the script,
but not the doc?
How does that, how does that work exactly?
So if you read the Google documentation,
they actually share their ACL exactly with this container.
So if you have a Google Doc with some Apps Script attached,
and somebody has edit permission on a doc,
they by proxy have edit permission to the script as well.
So this leads to some more interesting questions, right?
So you recall the edit access is required
as I mentioned earlier, to even run the Apps Script,
that's attached to a doc.
So they can't even use your application
unless they have edit access to your doc.
But if they have edit access
to the doc or sheet or slide or whatever,
then they also have access
to be able to edit the Apps Script that's attached to it.
So how does this work?
We have a bunch of people that all sharing the same doc
or sheet or slide and using the Apps Script attached to it.
So in this given situation, right, you have one app
say, this is access to these employees,
like Google Drive, BigQuery, stuff like that,
it's automating some process for them.
They all have to be granted editor access on the doc
in order to be able to use the Apps Script.
And they're all sort of sharing it together.
So they've all authorized this thing,
to access their services on their behalf.
And then you have one user that's malicious,
and of course they have editor access in the doc.
They go in and use their editor access
to modify the Apps Script attached to the doc,
to contain instead of the legitimate script,
a malicious payload that does something nefarious, right?
Maybe it like exfiltrates the docs
that they have access to, that the attacker
doesn't have access to something like that.
And then when the regular users come along
and they trigger the Apps Script, like they regularly do.
The malicious code now runs them, so this becomes
it's basically very, very hard to write an app
like this securely,
because just in the way that the system is designed,
you have to get people edit access and when you do that,
then you have access to edit the Apps Script
and so any shared documents with scripts attached to them,
become very exploitable.
So we can do actually even do one better than this.
So this piece of tech kind of implies
that you have to wait around for these people
to trigger this Apps Script, that's attached to the doc.
And as attackers, we're often quite impatient.
We'd rather force this to happen right now,
so this can be done essentially by,
you can force a re-trigger
by basically going to the Apps Script
and you can publish a web endpoints.
And when you publish this, you essentially get a URL.
And that URL, if it's visited by any of these users
that have authorized this app,
it will immediately trigger the script to execute us then.
And this is actually really nice because it doesn't,
it's not just they have to visit it, in their web browser,
they can visit a web page that simply has an image in it
that links to this URL.
And it will completely, that works completely fine,
it will execute the script as them,
just from an image that links to this.
So the way that you do this
is you just go to the Deploy menu in your Apps Scripts,
you do New Deployment,
you do a deployment type of web app.
And you simply say, "Hey, when people hit this endpoint,
I want to run as the user who's accessing the web app
and deploy it.
When you do that, you get this nice little URL back,
and this is what you can basically do
you can put this inside of a image tag or something,
or somehow get the victim to visit this
in their web browser.
And this will trigger this script
to automatically run as them.
So another useful technique for lateral movement
inside of a G Suite organization
is enumerating and joining open Google Groups.
So to talk about Google Groups, right,
Google Groups are used for ACL and both Google Cloud
in GCP/IAM settings
and for a variety of G Suite style services, right?
So they're used extensively in ACL.
But in addition to that, they're by default,
when you create a Google Group instead of a G Suite org,
they're openly joinable by everybody internally.
So by themselves, neither is an issue,
but when you put them together,
this is actually not so great, right.
something that's used extensively for ACL's
being by default widely open and insecure.
So anybody inside the company can join
and basically grant the permissions of this ACL
just by joining your group.
This is a being kind of basically a factory
for endless privilege escalation, right?
So oftentimes searching and joining Google Groups
is a great way to just escalate your privileges
inside of a Google G Suite organization.
So what all can be gated by Google Groups?
So we mentioned Google Cloud
and all the services under it, right?
I've mentioned Google Cloud functions,
but it's also stuff like Google Drive,
Docs/Sheets, whatever things like Google Calendar
Data Studio and even G Suite Admin ACL groups.
And it could even use for stuff
like publishing Chrome extensions.
So most Google services have some sort of ACL integration
with Google Groups.
So tons of places to escalate your privileges.
So talking about this in the context of like,
if you have an Apps Script implant,
unfortunately modifying Google Groups via Apps Script
is not as easy as it sounds.
For some reason,
unlike all the other sort of Google services,
the Google Groups API is,
which is known as the directory API
it's restricted only to admins.
So only G Suite admins can actually utilize the API,
but there is another API which is called
the cloud identity API, and that is available to all users.
So your Apps Script implant could make use of it.
And this allows some access to Google Groups via the API.
So there's some stuff that you can do with this
is you can list all the Google Groups,
they give an organization,
you can list the members of the Groups, their roles.
And you can also, you can create your own Google Groups.
You can update them, delete members, stuff like that.
And you can manage stuff that you create.
But unfortunately,
the one thing you cannot do via this API,
is you can't join an open Google Group,
which is super unfortunate.
But, if you did have that,
if you did have a full level access to the G Suite account,
joining open Google Groups
is a great way to sort of escalate your privileges.
So now we talked about escalation, let's talk about,
sort of stealth and persistence, right?
When you get access to a victim,
you don't want point in time, you want persistent access,
so you can keep fooling around inside of the organization.
We'll start off by talking about some Gmail trickery.
One things that recommend with your Apps Script implant
using your API access to Gmail
is create filters in Gmail
to essentially hide security notifications.
So things like the emails that say,
"Hey, you just granted access to a new Google App",
those kinds of notifications,
you can hide them from the user.
You can also create a bunch of filters
to hide password reset emails.
So you can basically
when somebody gets inbound password reset email,
you can hide it in either their trash
or some other folder so that they don't see it.
And since people's email accounts
tend to be the center of all their security,
you can then basically,
later on, you can essentially do resets
for all these sub-accounts,
use the Apps Script to pull the password reset email
on them and thus get access to them.
Unfortunately,
when it comes to creating an forwarding addresses
and stuff like this in Gmail, you can't do this via the API,
but we will talk about
if you have the full access to their account,
if you have the full UI access to Gmail,
you can do something that's called
adding a forwarding address.
This is super useful for persisting access.
Essentially, the way that it works
is you can set it so that you have an external mailbox,
something@yahoo.com or whatever the external email is,
and you can make it so that anything
that matches a given filter,
or even just every email they receive,
a copy of that email will automatically be sent
to this other email box, right?
So this way you can basically get a copy of all their stuff
that's coming in to them.
And you can set this to either delete the email
or just make a copy and not make any changes.
So this is a super good way
to sort of keep persistent access to their stuff.
Even if you end up getting revoked or ripped out later on.
So one of the things we talked about
with this historical campaign
where they used an app name of Google Drive,
having a deceptive app name is quite useful.
So you can tell that you can see here in this little demo,
if I try to set my Apps Script app name to Google Docs,
when you actually go to the permission prompt there,
it shows it won't actually do it for you, right.
It says it'll basically deny us as still on type of project.
It won't send it to Google Doc,
because that's a misleading name.
It knows you're trying to do something fishy there.
So essentially prevents you
from setting a app name like that.
But and if you look into some of the stuff
that they've implemented after this Google Doc worm came out
all of the sort of like,
when they were doing the tricks with the Unicode characters
to essentially get the same looking name,
to an official Google product,
all of that has been pretty well stripped out.
they have a good system for preventing you
from setting G-Swedish O-O-G-L Docs, all that's prevented.
None of the, no-width-space tricks, any of that works.
But I did find that you can use
with the magic of what's called
the Right-to-Left Override character.
So for those of you that aren't familiar,
what this is,
it's a Unicode character that you can paste in.
And when you paste it, all the characters that come after it
end up getting put in reverse.
And so in this case, you can see,
I basically paste the character in
and I go on to type in Google Docs backwards.
And because this is reversed from right to left
instead of left to right.
It actually appears in the prompt as Google Docs, right?
So we've completely bypassed this protection by using this.
And when the user actually goes to approve this,
they will just see a Google Docs just as they did
with the initial sort of Google Docs worm.
So in our thing we wanna do
right is likely perpetual Apps Script execution.
So we want our script to continually have access
to their account, we don't just want like,
we authorize it, it runs once, that's it.
We wanna keep access, keep persistence and keep around
so we can figure out what's inside the org and do our thing.
So Apps Script has a really useful feature,
which is time-based triggers instead of cron-style stuff
that I mentioned earlier.
And this allows for background execution on a schedule,
and this can be run as often as every minute.
And it executes, of course,
as whatever user was running the script
that ended up programmatically creating this trigger, right?
So you can see some example code here.
We've got ScriptaApp.newTrigger.
It creates one that runs every minute
and this we'll run our some function call
every minute or so.
Now, if you read the documentation on this,
it says in order to do this
in order to run these background scripts,
you need to request the specific scope,
which is Script.ScriptApp.
And this will cause this little thing
to come up in your OAuth prompt that says,
"Hey, allow this application to run
when you're not present".
So it explicitly warns the user
that this is running in the background.
It will run continuously even after you've approved it once.
So it turns out that this is more of a suggestion
than it is a hard rule.
They say you need to do this, but as it turns out,
it's more of a suggestion, really.
You could still create time triggers programmatically
without declaring the scope.
And as long as you declare some other scope of any type
Google Drive, Gmail, whatever it is,
as long as they authorize those,
you can programmatically create, time triggers all you want,
and they'll execute it just fine.
So you can use those to persist indefinitely
without any of the OAuth warnings to the user.
So more of a guideline than a strict rule.
So great.
We've covered a variety of topics here
around how you can sort of do everything
from pierce the perimeter, escalate privileges,
pivot around, persist and stuff like that.
So thank you all for taking the time to see my talk
and be happy to answer any questions that you have.