SoftwareSecurity2014/Group 5/Verdict

Uit Werkplaats
< SoftwareSecurity2014‎ | Group 5
Versie door Erik Poll (overleg | bijdragen) op 29 jun 2014 om 15:07 (Registration captcha)
(wijz) ← Oudere versie | Huidige versie (wijz) | Nieuwere versie → (wijz)
Ga naar: navigatie, zoeken

Overview

For the manual check we decided to focus on the user's profile, since manually scanning the entire code is massive job. We verify the input validation on all the pages related to the user's profile. Our findings in the individual pages are described below. The final results are as follows:

Level Result
V5.1 Verify that the runtime environment is not susceptible to buffer overflows, or that security controls prevent buffer overflows. (1B,2B) Pass The forum runs on a standard PHP webhost. The PHP language itself protects you against buffer overflows[1]. We therefore assume that SMF is not susceptible to buffer overflows. On the client side they use JavaScript which also is a safe language.
V5.2 Verify that a positive validation pattern is defined and applied to all input. (1B,2B) Fail Not every input validation is done using a positive pattern. For example, the source of images for avatars is checked for php and html code with a regular expression. Any image with a source that does not match this regular expression is rejected. (Erik: Not so clear from your description here that this example shows no positive pattern was used. THis is not a criticism of your work - I can well believe that it was not a positive pattern - just the way you phrase things.) Another example is that the username is also checked with a blacklist, the username is rejected if it matches a certain pattern. With whitelisting you only accept a certain username that matches a pattern.
V5.3 Verify that all input validation failures result in input rejection or input sanitization. (2B) Fail The notifications page has a select box where you can choose how fast you want to be notified about topics or boards you have requested notifications on. The browser sends a number (0,1,3 or 4) to the server and the server sanitizes this input to an int. (Erik: I realise that it is no so clear if this is now a violation of V5.2 or V5.3. I think I'd call this too loose input validation a violation of V5.2. Indeed, come to think of it, the ASVS does not say anything about input validation being too "loose") When storing it in the database, the database will give an error when the int is out of range. The problem is that the server also accepts and stores a value like 99 which is not a valid option.
V5.4 Verify that a character set, such as UTF-8, is specified for all sources of input. (2B) Pass SMF supports two character sets: UTF8 and ISO-8859-1. ISO-8859-1 was the default during installation so we used that. The default template prints the character set in the <head> tag of the page. By default, the browser submits the form data using the same character coding that was used to transmit the page[2]. Although the character set is specified, we still got some errors with special characters (see Username in our account settings page analysis).
V5.5 Verify that all input validation is performed on the server side. (2B) Fail Not every input validation is performed on the server side. When entering personal text in the forum profile page, the length is only checked on the client side.
V5.6 Verify that a single input validation control is used by the application for each type of data that is accepted. (2B) Fail The code that handles the ignore list changes is a copy of the code that handles the buddy list changes. The main difference is how they name the variables they read/write. So the code that removes quotes and splits the input by comma, retrieves user ids etc. is copied. (In Modify-profile.php, the editBuddies and editIgnoreList function).
V5.7 Verify that all input validation failures are logged. (2B) Fail Most of the incorrect input is sanitized and is not logged. If the user enters an invalid email address or an invalid website url it gives a warning but nothing is logged. Database errors are logged though, so things like out of range integers that the database reports are logged and give you an error when it happens.
V5.8 Verify that all input data is canonicalized for all downstream decoders or interpreters prior to validation. (3) Not in scope of the assignment
V5.9 Verify that all input validation controls are not affected by any malicious code. (4) Not in scope of the assignment

Profile -> account settings

The account settings page allows a user to change the following information:

  • Name
  • Email
  • Password
  • Secret question
  • Secret answer
  • Allow users to see online status
  • Allow users to email

Username

When trying to register as a new user, we tried entering a username with special characters. This yielded a database error. This error is logged in the database with the following message: Incorrect string value: '\xE9";s:1...' for column 'url' at row 1 > and another error: Incorrect string value: '\xE9' for column 'member_name' at row 1 Which means that both the live validation of user names and insertion of the name crash with special characters. This effect was noticed on a linux server. When SMF was hosted on windows we could register with special characters in the name. We expect that some configuration setting is different. It is remarkable though that SMF allows using special characters in your name, you could then create an account with the user name aԁmin[3] to impersonate the admin account. {{(Erik: Interesting idea! I've never seen or thought about attacks like that. I'd be interested to see if there are real attacks on websites that have tried things like this - I only know these glyph attacks in URL obfuscation. An obfuscation of a name like admin is maybe not so easy to directly exploit - I guess it would have to be part of a phishing/social engineering attack on users of the website.)}} The attacker would use homoglyphs so the name looks the same to the user but for the system the characters are different and thus allows the user to create such account.

Edit name input validation

Name

At the moment it is possible to enter any kind of name or symbol into the name input field. The page simply says "Your profile has been updated succesfuly", where you would actually expect some kind of error message stating that the name that was provided is not valid. A regular expression is used to check this field, where the name is checked with a blacklist regular expression check(preg_replace instead of preg_match). As far as we understand this regular expression only checked for special characters like backspaces and tabs.

Email

If you enter an email address with more than 255 characters, the SMF still considers it as a valid email address. Only the first 255 characters will be saved, trimming the rest of the email. The function used to validate the email address only checks if the characters are valid, not the length. Since it can only save 255 characters in the database, it is possible to store an invalid email address. The validate function also checks if the new email provided is unique.

Allow users to see online and email

There are 2 checkboxes which you can check to allow other users to see when you are online and if they can email you. Both of these checkboxes can only save a 0 or a 1 to the database, the input is well validated. This is not the case for all checkboxes (see below).

Change and Verify Password

If you want to change your password, you have to enter it twice. SMF checks if both passwords entered are equal to each other and then correctly validates the password, hashes it with sha1 and saves it in the database. The validation first checks the length of the password. The password has to be at least 4 characters long if the password strength is not set by the admin, otherwise it should be at least 8 characters. It then checks if the password contains restricted words. The restricted words per user are the user's real name, username and email. If the password strength requirement is set to hard, it also checks if the password contains at least one uppercase character, at least one letter and at least one number.

Screenshot database with empty question and empty answer

Secret Question and Secret Answer

It is possible to enter any kind of symbol as a secret question and secret answer. This is the same problem that the name field has. When inspecting the code we noticed that the security question and answer are not validated at all in any way. Another problem is that it is possible to have a security question with a blank answer or have an answer to a blank security question. The screenshot to the left shows two database records, one with a security question with no answer and one with an answer and no question.

Profile -> Forum profile

Forum profile page

The Forum profile page allows a user to enter the following information:

  • Avatar
    • Select from gallery
    • Enter url
    • Upload avatar
  • Personal text
  • Birthday
  • Location
  • Gender
  • ICQ number
  • AIM username
  • MSN Email username
  • YIM (Yahoo messenger) username
  • Signature
  • Website
    • Title
    • URL

Avatar

There are 3 possibilities for setting the avatar. The user can select an avatar from a gallery, specify a URL with the avatar or upload an avatar. This choice is made with a radio-group input field. With JavaScript the correct input fields are shown. When submitting the form, the system assumes that the correct fields are entered. If we enter a different combination or a value in the radio-group input field that is not a valid option, the system will simply ignore it and show the message "Your profile has been updated successfully". The avatar will not change and no error will be logged.

Select avatar from gallery

Selecting an avatar from the gallery makes use of JavaScript to select a category (i.g. "Musicians", "Actors") and a select field to select the avatar. The value of each option is the literal string to the avatar (i.g. "Musicians/Bob_Marley.jpg"). The input is verified correctly with a regular expression and checks whether the file exists and is located in the allowed locations (the avatars folder). If however this verification fails, the avatar is set to a default image without informing the user (the message “Your profile has been updated successfully” is shown) and without logging an error.

Specify URL

The only restriction on the URL is that it starts with "http://". An avatar hosted on a https server is thus not allowed. Apart from that, a sub-string "action=[something]" is replaced with "action-". Probably because the forum uses this in its URLs. If the verification fails, the avatar is set to empty, the success message is shown and no error is logged.

Uploading avatar

Uploaded avatars are checked for the correct file type. Larger images are cropped to a minimal size. It is possible to enter PHP code inside an image as shown here and upload it but we could not find a way to execute the image as a script.

Personal text

The personal text is a text that is displayed on the users profile. The input is properly escaped (Erik:for HTML, I presume?). The length of the input is only checked on the client side. If this check is turned off, it is possible to enter larger text.

Birthday

It is possible for users to enter their birth of date. Basically any date is accepted. It does not matter if the entered date is greater than the current date. It is not possible to enter a birth date 0-0-0000. This date is transformed to 01-01-0001 which is represented as "n/a" in the user profile. It is also not possible to enter a year less than or equal to 4. If the year is less than or equal to 4 it is set to 0. The system automatically creates the date with wrong input without informing the user. Nothing of the invalid input is logged. (Erik: Btw, I always think this ASVS is a bit too paranoid when it comes to insisting that all input validation failures are logged. It is debatable whether you really want it to be logged whenever someone make a typo when entering a birthdate.)

Location

A user may enter a location as text. There are no restrictions for the input but the input is properly escaped. It is possible to enter a very large text but it is cut down to 255 characters when it is stored in the database. With long text there are no errors or logged errors.

Gender

The gender can be set with a select field. The valid input is 1 (=Male) or 2 (=Female). It is possible to set this to 3. This input is not checked and the 3 is stored in the Database. This is not a big issue because any value that is not 1 or 2 is considered "n/a" when being displayed. Invalid input is not logged.

ICQ number

Input for ICQ numbers only checks whether the value is a number. ICQ numbers should have at least 5 characters. This is not checked. It is possible to enter 1 digit numbers and even negative numbers. It also seems that ICQ uses email addresses nowadays to identify users. None of us use ICQ and we decided not to investigate this any further.

AIM username

The aim username accepts the same input as the personal text except that it also automatically replaces spaces with a '+' character. It is again possible to enter larger text than the database field size. Wrong input is never logged or shown as error.

MSN Email username

The input for the msn email is properly checked for a valid email address. The length of the input is not checked. It is possible to enter a 255 character text and append something like "@email.com". This will pass the PHP validation but the database only stores the first 255 characters (cutting off the "@email.com").

YIM (Yahoo messenger) username

The input validation for a Yahoo messenger account is the same as the input validation for personal text. It is allowed to have spaces in the username except trailing or leading spaces. We don’t know if this is indeed allowed for Yahoo usernames, it is currently not possible to register a username with spaces or special characters in it. We don't know if the username had different requirements in the past.

Signature

The signature field is the only field where the length of the input is checked. It is checked on both the client and server side. If the length does not match the system will give an error but it is not logged. It is also possible to enter BBCode in the signature. Unclosed tags are automatically closed. There are no checks performed on [img] and [url] tags for valid urls.

Website

A user may enter a personal website by providing a title and a URL. The input validation for the title is the same as other text fields (such as personal text). (Erik: so this is validation for HTML, incl. javascript?)This again means that larger text can be entered and will be cut off in the database. The input validation for the URL is very limited. The entered value must start with "http://" or "https://" otherwise "http://" is prepended to the input. The final value must have at least 8 characters. URLs such as "http://i" and "https://" are allowed.

Profile -> look and layout

Look and layout edit page

The look and layout page allows you to change how the forum looks. For example, you can change your theme and the way dates are displayed.

Change theme

At the top of this page you can open another page to change the theme. On that page is a list of available themes and from there you can either preview a theme or apply it. Both options are a GET request, the difference is the way they pass the theme id. When you want to set the new theme, they use &th=themeid and when previewing it is &theme=themeid. We tried to exploit it by placing an image tag with the following URL: index.php?action=theme;sa=pick;u=2;th=2;eb80fd48b9=0ee06a7c389a9c0942872c92851818b5. The forum changes the action=theme to action-theme. A link to the page was not changed but we found out that you need to supply the correct session id which makes this attack harder as you need the user's session id and have him to click on your link. Incorrect session and theme id's do not get logged. There is also no log of the URL change in my forum post, it was changed without any message at all.

We tried to use Fortify to see what happens with the theme id the user supplied. We ran the query tracenode:sources/load.php|1337| but it returned 945 issues which is quite a lot. A lot of issues did not have anything to do with the theme but their traces had this line in them. We saw that in the loadTheme function it checks the user input against the $modSettings['knownThemes'] variable. It only checks this when the expression (!empty($modSettings['knownThemes']) && !allowedTo('admin_forum')) holds. We didn't search for places where this variable can be changed.

When you choose a theme as your preferred one the input is cast to an int and saved to the database without validation. If you supply a large number it gives you a database error. SMF then logs the following error in the error log table in the database: Database Error: Out of range value for column 'id_theme' at row 1. Every time you open a page it checks whether the theme id is ok to load. We didn't check whether this happens in all situations.

Time Settings

Below the change theme settings you can change your desired time format and time offset. You can choose some predefined time formats from a drop-down list which simply edits the text field below it via JavaScript. The input of the text field has no validation at all. You can enter any text there and it will be passed to php's strftime function. If the input is too long you get a database error which is also logged and says that the input was too long. The time offset is checked against: ($value < -23.5 || $value > 23.5), when you enter something else it will default to 0. With incorrect input it still tells you your profile has been updated successfully and it does not log the incorrect input.

Theme settings

The last part of this settings page contains configuration settings for the theme you have chosen. The values in this section are posted in the default_options array. So an html element looks like <input name="default_options[use_sidebar_menu]" id="use_sidebar_menu" value="1" class="input_check" type="checkbox">. The values end up in the themes table in the database. That table has the colums: id_member,id_theme,variable,value. When we change use_sidebar_menu and the value to something else it also accepts those and puts them in the database. So the input is not checked at all. We tried to post 100 additional keys/values and they all ended up in the database. Whereas new forum replies are limited to one reply per 5 seconds, the modify profile page does not have such limit. This allows you to fill the database which might lead to a full server hard drive. At that point you cannot insert new things in the database so it will have a a big effect on your forum. (Erik: Of course, trying to rule out rule out all DoS possibilities by users is very hard in general.)

Profile -> Notifications

Notifications edit page

On this page you can manage your notification settings. You can configure whether you want to receive forum newsletters and when you want to receive notifications. At the bottom you can deactivate notifications for the topics or forum boards you previously opted in to get notifications.

Settings

The first and third checkbox are converted to a "1" when some value is set (and "0" otherwise). The second one is passed via the default_options which has been described in the theme settings part. The value you submit simply isn't validated at all.

The first drop-down is converted to an int, so if you change the value of an option to a string by hand the server will convert it to a 0. The value of 0 means Instantly. If you change the value of it to another number it simply accepts it while that number isn't an option you can normally choose. The database makes sure the value is a tinyint(4) and will give and log an error when your supplied number is outside that range.

Like the first drop-down, when you alter it such that it doesn't submit a number but some text it will be converted to 0 by the server. In this case 0 isn't even a option we could choose. In the database the field is also a tinyint(4) and will also log and show an error if the supplied value is outside that range.

It always shows that the settings were saved successfully (except for the cases where it gave a database error).

Unnotify

You can select some boards or topics for which you do not want to receive notifications anymore. The server simply converts the input data to ints and passes them to a delete statement in the database. It does not verify whether you were being notified about the ids in the first place. Effectively that does not matter since there is no point in telling the user that he cannot unnotify himself from an already unnotified topic/board.

Profile -> Personal Messaging

Personal messaging page

Drop-down boxes

All the three drop-down boxes are validated in the same way. They allow you to select one of the available options. The server checks if the integer you submit is in a correct range. If you submit something else (like some text) the database will yield an error about not giving it an integer(and this is logged). So those drop-down boxes are fully validated. Only the case where the database yields an error is logged and shown to the user as error. When you supply an integer which is out of range it is picks the closest legal integer and does not inform you about that.

Checkboxes

The checkboxes are part of the default_options array we described earlier. This means that the input is not validated at all.

Profile -> Buddies list

Buddies list page with some buddies

At the buddies list page you can make a list of other users registered on the forum.

Add To Buddy List

In the input box you can type the username/user's real name and press add to add it to the list. We found in the code that it first passes the user input through htmlspecialchars. After passing the input to htmlspecialchars, the quote characters (") are removed and the input is split by comma separated. You can use the username or/and the real name of the user as input value between the commas.

When you enter a non existing user, yourself or an already added user it does add it or inform you about that. As described earlier, we couldn't use special characters in the username/real name field on our Linux server. When we entered a user with a special character (like é) on our Windows server it does not add that user as buddy. Conclusion: it works fine when you do not use any special characters.

Remove buddy

In the buddies table there is a remove button to remove a user from your buddy list. This button submits an ID to the server. The server casts this ID to int and simply removes that ID from the buddy list. If you don't supply an ID or the ID does not exist it does not tell you that.

Profile -> Ignore list

The ignore list page looks almost identical to the buddies page. You also have a list of users and you can add new / delete them. The code that handles changes to the ignore list looks like a copy of the buddy list with some small changes(basically they replaced buddy with ignore). Due to this, this page behaves the same as the buddies page.

Additional, non input-validation issues

Registration captcha

Registration on the forum requires you to fill in a captcha to prove you are human. The problem is though that you can request a new image but it contains the same characters. (Erik: Haha, that is something new to me :-) - i never saw anything like that. Not very clever, as you are right to observe. So as a bot you can request many versions of the captcha and combine them somehow to get all the characters correctly. There is also an option to listen to the letters. The letters you hear are very clear, there is no background noise added so it might be easy to do sound pattern matching on this.

Deprecated functions

In Subs-Compat.php, fortify found:

if (!function_exists('mysql_real_escape_string'))
{
	function mysql_real_escape_string($string, $connection = null)
	{
		return mysql_escape_string($string);
	}
}

Which is not secure since mysql_escape_string is not a safe replacement for mysql_real_escape_string. The mysql_real_escape_string is available since PHP version 4.3 [4]. Since PHP 4 is old and unsupported you can get lots of other security issues if you are still using PHP4 nowadays. There are more cases like this in the SMF code, for example we saw code that checks if the user is using Internet Explorer 4. It would help if SMF removed all this legacy code as it is not relevant annymore.