Show Notes

183 - CSS Injection and a Google Cloud Project Takeover Bug

Fun little CSS injection turned full-read SSRF thanks to an (imo) overly powerful PDF generator.

Getting into it, the CSS injection was straight forward, there was a configuration option for the color of text, this color was reflected directly into the page’s CSS (for the PDF). The value was reflected into the color property with minimal sanitization. The sanitization was enough to prevent breaking completely out of the CSS <style> tag though, but they could inject other properties. Playing with that they first discovered a blind SSRF, any url(...) directive would be fetched by the PDF generator allowing them to cause a request but not get much information back.

The PDF generator in use had useful feature though, prince-pdf-script a CSS property intended to be used to include JavaScript to be run when the PDF was opened. They didn’t actually have much luck getting JavaScript to run, but it supported using the url(...) directive to specify the location of the JavaScript file. The file’s contents would then be included as a JavaScript object inside the PDF, even if it wasn’t JavaScript. This allowed for reading local files, and making requests to remote hosts with full disclosure of the body. They used this to to find and query internal APIs and have the bug triaged as a critical.

I also want to shout out their first failed attempt to use the blind SSRF. They tries to disclose whether or not domains were up/down by doing a sort of timing attack based on the image loading time and time between requests. It turned out to inconsistent to use, but was a cool idea.

BBCode XSS chained with an admin panel SQL injection for potential for code execution.


The XSS uses a trick we’ve talked about before (episode 109) which is the idea of unexpected nesting.

[email][email= onpointerover=alert()//]text[/email]

in this case nesting an [email] tag within the email attribute of the [email] tag. When rendered, you get the normal HTML rendering of the inner [email] tag reflected inside of the href attribute. Since that normal rendering would include " it is able to breakout of the href attribute and inject a new onpointerover attribute containing JavaScript.

I’m not sure if the missing [/email] from the above payload is essential or just a side-effect of the fact it was fuzzer generated.

SQL Injection

The user search functionality is able to search custom profile fields, to accomplish this a set of key/value pairs are sent in as an array named profile_fields each key in this array is a column name, and the value is the value to be matched by the search. Unfortunately for MyBB the column names are not properly escaped before being used in the final query.

$userfield_sql .= ' AND '.$db->escape_string($column)." != ''";

It uses the escape_string method, but the value is not going into a string inside of the SQL statement. So one can easily inject other SQL keywords and change the semantics of the query.

Code Execution

If the SQL engine being used supports sending multiple queries then it becomes possible to turn this SQL injection into command execution. The template for a profile signature is passed into eval. So by sending a query update the member_profile_signature template one could inject into the eval call and have their own PHP executed when the template is evaluated.

Service had a proxy. You would go through the oauth flow to get access to Google data, then it had an endpoint that would proxy requests adding the Authorization: header to them to the google backend. Had some whitelisting so it should only proxy to Google API but https://{INSTANCE-ID}{}/ it could get around that by including the computer url after the attacker url.

Getting the SSRF to hit the attacker page would disclose teh Authorization header, which had the Cloud-Platform permission, so highly privileged. Since this is a GET request with no CSRF protection, the only requirement is knowing the instance-id.

Starts off with an exposed activity in the KAYAK app, ends up with session hijacking.

The exposed activity was the ExternalAuthLoginActivity it could be called from any application/website. That isn’t necessarily a problem, but one of the things this activity does is it will attempt to read an EXTRA_REDIRECT_URL from the intent, append a parameter to the URL containing the user’s KAYAK session cookie value.

So any malicious website could launch this intent, and recieve a callback with valid session cookies for KAYAK.