The first FLOSSHack workshop will be held on July 1st, 2012 from noon to 4pm at Free Geek. The workshop's target will be the Ushahidi platform. An overview of the FLOSSHack workflow can be found on the "FLOSSHack for Participants" page. The primary organizers for this event are Timothy D. Morgan and Wil Clouser.
- 1 Getting Started
- 2 Joining Remotely
- 3 Competition Notes
- 4 Ideas for Attacks
- 5 Suggested Tools
- 6 Other Tips
- 7 Findings
- 7.1 Issue #1: SQL injection in admin area reports editing
- 7.2 Issue #2: SQL injection in Check-in API
- 7.3 Issue #3: Admin User Hijacking
- 7.4 Issue #4: Lack of Authentication in Checkin API
- 7.5 Issue #5: TBA
- 7.6 Issue #6: TBA
- 7.7 Issue #7: TBA
- 7.8 Issue #8: TBA
- 7.9 Issue #9: Lack of authentication report submission
- 7.10 Issue #10: Lack of authentication in deleting email messages
- 7.11 Issue #11: Potential stored XSS via member name
- 7.12 Issue #12: SQL Injection in MY_Countries_Api_Object.php
- 7.13 Issue #13: TBA
- 7.14 Issue #14: Forgotten password challenge guessable
- 7.15 Issue #15: TBA
- 7.16 Issue #16: Multiple SQL Injection Vulnerabilities
- 7.17 Issue #17: TBA
- 7.18 Issue #18: TBA
- 8 Prize Winners
If you want to check out the code separately from the VM, the version of the source code for audit is the latest commit on the master branch. This can be obtained with:
git clone -b master git://github.com/ushahidi/Ushahidi_Web.git
Once the workshop begins, a Google+ Hangout will be created that remote participants may join. To receive an invite, please email
tim . morgan |at|
owasp . org with your Google email address/ID. In addition to Hangouts, the session will be streamed live on YouTube. A URL will be posted here later today for accessing that feed.
UPDATE: Google Hangouts turned out to be too complicated. Please join us instead on IRC. Network: freenode / Channel: #flosshack
You are welcome to start looking for vulnerabilities right now. If you do find any vulnerabilities in the application prior to the workshop, please email them to
tim . morgan |at|
owasp . org. That way you get credit for them if you're the first to find a given flaw. At the end of the workshop, there will be prizes for both finding the "best" vulnerability and for finding the most vulnerabilities. Also, be sure to keep any flaws you find under wraps so that way Ushahidi has some time to correct everything before they are made public.
Ideas for Attacks
The application is designed to gather information about events from the general public and combine them into useful statistical and geographic reports. The following attack scenarios seem relevant (not all-inclusive):
- Cross-site Scripting (XSS): plenty of places to enter data and have it displayed later by other users. Reflected attacks also interesting
- SQL Injection: Using PHP with a MySQL database
- Authorization: supports user-defined roles. These roles can be configured with various sets of built-in access rights as well as an access level feature designed for controlling access to custom forms. Certainly any bypass of this privilege system would be interesting. Try setting up accounts with different privilege levels and see if you can get around any restrictions.
- File uploads: several forms allow file uploads of various types. These are frequently vectors for a variety of attacks, including directory traversal, uploads of executable content (like .php scripts within the web root), XSS via filenames and content, HTTP header injection via file names, and other content-type/file extension shenanigans.
- Privacy concerns: in some deployments, the application is used to gather reports of civil/human rights violations by governments and other entities. If you see a flaw in the application that could leak reporters' identities, this could be devastating for these deployments
- Software deployment: The provided VM is distinctly not security-hardened, so if you see a problem in the web server, database, or filesystem configuration, it may not be very relevant. However, if you find something along these lines and you find that the instructions in the Installation Guide would cause this same problem to come up for normal users, then it is definitely worth noting.
- The provided VM image apparently does not have PHP's GD imaging library packages installed. You'll want to install the
php5-gdpackage. This may cause a packaging conflict with the underlying GD library, but you can resolve it by installing the
libgd2-xpmversion of the GD library. After doing this, then restart PHP with:
- You may find it helpful to turn on PHP error reporting to immediately see in the UI when certain errors could be exploitable. To do this, edit the
/etc/php5/fpm/php.inifile, add the following line, and then restart PHP:
display_errors = On
Good luck and happy hunting!
FLOSSHack One was a great success, particularly in how many issues were identified in such a short period of time. This speaks largely to the quality of skills participants brought to the event and the help from Ushahidi developers who supported us through the process. The following findings were identified, many of which have already been fixed in a new software release on August 1. Here we include details about what the already fixed flaws were and how they could have been exploited, for the educational benefit of aspiring "breakers".
Issue #1: SQL injection in admin area reports editing
credit: Timothy D. Morgan
Issue #2: SQL injection in Check-in API
credit: Kees Cook
CVE-2012-3469 -- Improperly assigned. Should have been associated with CVE-2012-3470.
If checkins are enabled, the API does not perform a parameterized SQL query. Note the injected "KABOOM":
curl -d task=checkin -d action=ci -d mobileid=10 -d lat=1 -d lon=1 \ -d message=Message-data -d firstname=Firstname-data \ -d lastname=Lastname-data -d email="[email protected]' KABOOM" \ -d color=red 'http://localhost/api';
ERROR: Database error: 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 'KABOOM' LIMIT 1' at line 1 - SELECT id FROM users WHERE `email` = '[email protected]' KABOOM' LIMIT 1;
$query = 'SELECT id FROM '.$this->table_prefix.'users WHERE `email` = \.$user_email.'\' LIMIT 1;'; $usercheck = $this->db->query($query);
$query = 'SELECT id FROM '.$this->table_prefix.'users WHERE `email` = ? LIMIT 1;'; $usercheck = $this->db->query($query, $email);
Issue #3: Admin User Hijacking
credit: Wil Clouser
- Load /installer/basic_summary.php
- Click through the prompts filling out any data you want. Intercept all requests. Remove any Location headers in the server responses before they hit your browser. It might take a few trips through the wizard to get all the variables into your $_SESSION but by the end I didn't even need to intercept Location.
- /installer/basic_admin_pass.php will reset the administrative password in the database.
- Log in with your new admin account using the password in step 3.
The best idea would be to remove the installation files when installation is complete. The super fast fix (and worth auditing the rest of the site) is to call die() after any Location headers. That way if the client ignores the header they can't load the rest of the page.
Issue #4: Lack of Authentication in Checkin API
credit: Kees Cook
There appears to be no authentication of users beyond knowing a given account's email address and name. This allows unauthenticated API users to create comments on arbitrary incidents as arbitrary users:
curl -d task=comments -d action=add -d [email protected] \ -d comment_author=Administrator -d incident_id=2 \ -d comment_description=comment_description-Data2 \ 'http://localhost/api'
Also anyone can delete arbitrary comments:
curl -d task=comments -d action=delete -d comment_id=2 'http://localhost/api'
The approve and spam actions have a bug that blocks anyone from being able to use those functions ("a" != "approve"), but if that was fixed, then anyone could also query pending comment and approve (or spam) them (if auto-approve was disabled):
curl -d task=comments -d by=pending 'http://localhost/api' ... curl -d task=comments -d action=approve -d comment_id=200 'http://localhost/api'
curl -d task=comments -d action=spam -d comment_id=200 'http://localhost/api'
Issue #5: TBA
Issue #6: TBA
Issue #7: TBA
Issue #8: TBA
Issue #9: Lack of authentication report submission
credit: Kees Cook
There appears to be no authentication for adding reports, so an unauthenticated user can report as an user by specifying person_email in the POST via reports::save_personal_info().
Issue #10: Lack of authentication in deleting email messages
credit: Dennison Williams
There is no authentication for this action. The functionality for this is located in: application/libraries/api/MY_Email_Api_Object.php line 134
Issue #11: Potential stored XSS via member name
credit: Amy K. Farrell
Storing a "Full Name" with HTML special characters is possible and will result in at least one page, the public profile, including these characters unencoded on output. The application does perform blacklist-style HTML filtering of the entered content, but it is likely that there is some way to get around it.
To fix, encode these values properly using HTML entities. Also consider rejecting entered names that include unreasonable characters.
Issue #12: SQL Injection in MY_Countries_Api_Object.php
credit: Kees Cook
The countries API does not perform any parameterized SQL queries, so multiple "by" codes will trigger it. Note the injected "KABOOM":
curl -d task=countries -d by=countryiso -d iso="us' KABOOM" 'http://localhost/api'
ERROR: Database error: 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 'KABOOM' ORDER by id DESC LIMIT 0, 20' at line 3 - SELECT id, iso, country as `name`, capital FROM `country` WHERE iso='us' KABOOM' ORDER by id DESC LIMIT 0, 20
Issue #13: TBA
Issue #14: Forgotten password challenge guessable
credit: Timothy D. Morgan
The forgotten password challenge uses a combination of user email address and timestamp from when they last logged in and then hashes this information using the standard password hash of the application. This challenge is not stored anywhere, since it is possible to verify the hash by repeating the hashing operation after receiving the hash in the URL. The application simply extracts the hash salt, retrieves the email address and last login time, and recomputes the hash. Because of this approach, the hash's random salt does not add to the challenge's entropy in any way. An attacker could simply guess the last time a user logged in along with their email address, select any salt they want, and then generate the appropriate hash.
The only difficulty in implementing this attack is that Ushahidi uses a very unusual hash salt obscurity algorithm whereby the salt and the hash are mixed into a string in an installation-specific way. By simply looking at a hash on a given installation, it would be impossible for an attacker to know which bytes are salt and which are hash. HOWEVER, an attacker could determine these salt offsets by performing password resets on their own account. They would know approximately their own user's login time stamp. They would also know the number of salt bytes used in the hash based on it's length. From there, they could brute-force the offsets of where the salt is stored. Once these are known, attacks on other users would be relatively easy, given knowledge of a user's email address.
It is recommended that the application be updated to use an HMAC rather than a simple hash. Upon installing Ushahidi, a secure random key (128 or more bits) should be generated (using a secure pseudorandom number generator) and stored in the database for the *single* purpose of signing password challenges. Instead of using the password hash algorithm, use the following algorithm for generating challenges (in PHP-like pseudocode):
$salt . SHA1-HMAC($login_time . $email_address, $salt . $key)
Here, the HMAC's key is a combination of the stored random key and the salt. Verification of codes can happen in much the same way without the need to store forgotten password challenges. This is much more secure since an attacker can't generate new HMACs without knowledge of the stored cryptographic key.
Issue #15: TBA
Issue #16: Multiple SQL Injection Vulnerabilities
$request is a plain Array that is populated elsewhere in:
https://github.com/Ushahidi/Ushahidi_Web/blob/master/application/controllers/admin/messages.php line 81 https://github.com/Ushahidi/Ushahidi_Web/blob/master/application/controllers/admin/messages/reporters.php line 54 https://github.com/Ushahidi/Ushahidi_Web/blob/master/application/libraries/api/MY_Incidents_Api_Object.php line 191
Location_Model::get_locations (application/models/location.php line 44) never escapes column or value in:
https://github.com/Ushahidi/Ushahidi_Web/blob/master/application/libraries/api/MY_Locations_Api_Object.php line 50 https://github.com/Ushahidi/Ushahidi_Web/blob/master/application/libraries/api/MY_Locations_Api_Object.php line 68
$user_email is not accepted and is passed request['email'] on line 303 in:
Issue #17: TBA
Issue #18: TBA
Congratulations to our prize winners:
- The prize for "best bug" goes to Michael Freeman
- The prize for "most bugs" goes to Kees Cook