Best security questions in April 2011

Android Game Keeps Getting Hacked

59 votes

So we've been through this several times now, we release a game (for cheap) and someone hacks it and puts it up on a mirror. We setup Google Alerts for all our apps, so we get told daily who's doing the hacking. So far, we have implemented the licensing service as Google has suggested, our salt is randomly made each time the license is initiated with the unique device ID. We run the check service once, when the application is started for the first time. We then generate a 512 character hash for the key and the stored value that is compared against in SharedPreferences from there on out.

Now, I know that checking once is probably where the application is being blocked. Our bytecode has most likely been looked at and recompiled without the line that initiates the check.

From here, I don't want to obfuscate our code as I have seen it broken before. I want something a little more solid, and I also want to learn how to do this properly. I am more interested in learning than making money at this point since only 2% of people will ever look for a hacked version.

So far, on my own, I have come up with a random number generator that is placed in several startup areas of the game. When initiated (say, 1 out of 50 times) the license is checked. I know this would make it harder to hack because the cracker would have to eliminate each case, compile, eliminate, compile. This method however, is still crackable...so what do you guys suggest? Again, I am really interested in this process of security, so please educate, don't turn this into a discussion on obfuscation or checking periodically based on a timestamp.

Thanks

My idea isnt hacker proof, but might remove some of the interest for hacking the game.

Freemium model

1) Make the first 5-10 levels free so people can learn the game and have some fun without paying. Less will want to hack the first level and the game will spread even further by Freemium model.

Shareware/clustered levelpacks

2) Let part of the game levels or logic stay online. Eg. when reaching for level 5 or 10 or 15, then download small parts for the game, and every time submit the progress-log from the game and validate this against possible values + hashcodes. This could perhaps make it possible to automatically close down of hacked accounts.

Stealth cheater protection

3) You could also just count "small warning flags" that you place around in the game. Dont just check for the "validation" in the beginning, no build these flags into the game logic itself. Dont make it break the gameplay, because then noone will look for it. Then when the user reached the end of level monster, check if there were any logged warning flags. These will not show up inside the game, so the unknowing user with a hacked edition could be playing for hours/days and suddently realize that he/she couldnt finish the game or advance to next level, because the game had a "bug". What the user didnt know was that this bug only occures on hacked clients.

Conclusion

Be smarter than the crackers. Fool them into thinking the job was done. Make a copyprotection and know that the more advanced crackers will be able to remove it. But they probably dont want to play 50 levels to check if the crack also works all the way.

Once they realize this problem, they might start to crack it too. But if you break the game up into level-packs, you can still validate between each pack download. So once you receive hacked client hash data, then just execute an exeception and crash the game on the client. Whoops the game crashed. Dont tell its because its hacked. A program error can happend. :-)

Again, its not hacker proof. But it might annoy them enough to move on to the next game. Lastly, you could also put out regular updates for the game and only the latest version should be able to "post the records" etc. so the active users would have to update to keep in the loop.

Is Javascript/jQuery DOM creation safe until it's added to the document?

28 votes

Please read this statement carefully: let's assume before ANY elements are added to the document all unsafe elements in $dom have been removed. But they were initially created. Ok let's continue....


If a piece of user text is processed and can possiblity be loaded like so:

var comment = 'I\'m a naughty person!!' +
              '<script src="http://blah.com/some_naughty_javascript.js">';
var $dom = $('<div>' + comment + '</div>');

Is this by itself dangerous in any way? My point being, can just the simple act of creating a DOM somehow inject anything, or is it just simply processed and the structure is created?

For example:

var $dom = $('<script>alert("hi");</script>');

Obviously the message hi does not pop up until it's added to the document. But:

  • Can any tag or anything created in this manner be dangerous?
  • Can any functions in javascript/jquery "watch" for elements being created in this manner and act on it BEFORE it's been stripped of bad elements and put on document?

Bounty Edit

So as outlined in the answers below, it seems this method isn't very safe, particularly for one reason:

  • var $dom = $('<img src="blah.jpg"/>') -- this will request for the image straight away, regardless of if the object was added to the document.

This creates a major problem for dealing with HTML ajax requests. For example if we wanted to get the values from the inputs of the form:

$.ajax({
  url: 'test.php',
  success: function(responseHTML) {
    var inputs = $(responseHTML).find('form input');
  }
});

This will involuntarily cause all images to be requested for by the browser.

Bounty is awarded to anyone:

  • Who can provide a nice, safe way of dealing with ajax requests without the above issue.
  • Ideally doesn't provide a regex answer... i.e. what if we wanted to do $(responseHTML).find('img') -- removing image tags with regex can't be an option, so an unobtrusive way would be needed to stop the src from loading, but still have the same attributes, structure, etc.

Is this by itself dangerous in any way? My point being, can just the simple act of creating a DOM somehow inject anything, or is it just simply processed and the structure is created?

Simply creating an element without appending it to the dom will not cause any script to run since it is purely an object at this point (HtmlScriptElement). When it is actually appended to the dom the script element will be evaluated and ran by the browser. With that being said I suppose it is possible that an extremely crafty person could exploit a bug that is present in some framework or browser you might be using to cause an undesired outcome.

Consider this example:

<p>
    <input type="button" value="Store 'The Script' In Variable" id="store"/>
    <input type="button" value="Append 'The Script' To Dom" id="append"/>
</p>
<br/>
<p>
    <input type="button" value="Does nothing"/>
</p>
<h1>The Script</h1>
<pre id="script">
    $(function(){
        function clickIt(){
            $(this).clone().click(clickIt).appendTo("body");
        }
        $("input[type='button']").val("Now Does Something").click(clickIt);
    });
</pre>

var theScript;

$("#store").click(function() {
    theScript = document.createElement('script');
    var scriptText = document.createTextNode($("#script").text());
    theScript.appendChild(scriptText);
});

$("#append").click(function() {
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(theScript);
});

When you click on store it will create the HtmlScriptElement and store it into a variable. You will notice that nothing is ran even though the object is created. As soon as you click append the script is appended to the dom and immediately evaluated and the buttons do something different.

Code Example on jsfiddle


Can any functions in javascript/jquery "watch" for elements being created in this manner and act on it BEFORE it's been stripped of bad elements and put on document?

jQuery sort of does that for you already as it does some internal script eval


From Karl Swedberg post on .append()

All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM. ...

You could alter the behavior of jQuery to remove all <script/> and sanitize other elements with inline javascript onclick, mouseover, etc when calling append() however that will only affect jQuery as someone could easily use vanilla javascript to append the <script/> element.

Dom Mutation Events

Dom Level 2 does defined some Dom mutation events to capture elements that are added to the dom one would look towards the event, DOMNodeInserted. However it is fired after the element has already been added. note, per Raynos these are currently deprecated.

DOMNodeInserted Fired when a node has been added as a child of another node. This event is dispatched after the insertion has taken place. The target of this event is the node being inserted. Bubbles: Yes Cancelable: No Context Info: relatedNode holds the parent node

In the end it appears there is no totally stop a <script/> being appended to the dom via some other javascript. (at least not that I can find).

The best way I can suggest is to never ever trust user input as all user input is evil. When you do dom manipulation double check to make sure there are no forbidden tags, be it <script/> or even plain <p/> elements and sanitize all input before it is persisted.

Also as John points out you need to worry about any element that can attach a onclick event or any inline javascript event handler.

Storing PHP(/PHP-FPM/Apache)'s temporary-from-upload files in RAM rather than the filesystem (or encrypted only)?

26 votes

Thread overview

I can unfortunately only accept one answer - but to anyone reading this, the entire thread is extremely valuable and contains the collective insights of many people. Depending on what you are hoping to achieve, the accepted answer may not be interesting to you. If you've come here through a search engine, please take a moment to read the whole thread.

Here is a compilation of usecases as I see them for quick reference:

Re: PHP's temporary files

  • RAM instead of disc (e.g. due to I/O concerns) → RAMdisk/comparable (plasmid87, Joe Hopfgartner)

  • Immediate (per-filesystem-user) encryption → encFS (ADW) (+ a gotcha as per Sander Marechal)

  • Secure file permissions → restrictive native Linux permissions (optionally per vhost) (Gilles) or SELinux (see various comments)

  • Process-attached memory instead of filesystem (so a process crash removes the files) (originally intended by the question)

    • don't let the file data reach PHP directly → reverse-proxy (Cal)

    • disable PHP writing to the filesystem → see PHP bug link in this answer (Stephan B) or run PHP in CGI mode (Phil Lello)

    • write-only files → /dev/null filesystem (Phil Lello) (this is useful if you have access to the data as a stream additionally but cannot turn off the file-writing functionality that runs in parallel; whether PHP allows this is unclear)

Re: your files, post-upload


Original question

So the project I'm working on is deathly paranoid about file uploads.
In the scope of this question, I'm not using that term in regards to payloads; I'm talking confidentiality.

Programs can always crash and leave temporary files loafing around in the filesystem. That's normal. The slightly confidentiality-paranoid can write a cronjob that hits the temporary file folder every few minutes and deletes anything older than a few seconds prior to the cronjob call (not everything, simply because otherwise it might catch a file in process of being uploaded).

...unfortunately, we take this paranoid a step further:

Ideally, we'd love to never see temporary files from file uploads anywhere but in process-associated RAM.

Is there a way to teach PHP to look for temporary file as blobs in memory rather than in the filesystem? We use PHP-FPM as a CGI handler and Apache as our webserver, in case that makes it any easier. (Note also: 'Filesystem' is the keyword here, rather than 'disc', since there are of course ways to map the filesystem to RAM, but that doesn't fix the accessibility and automatic post-crash-clean-up issue.)

Alternatively, is there a way these temporary files can be encrypted immediately when they're being written to disc, so that they're never held in the file system without encryption?

Have you considered putting a layer between the user and the web server? Using something like perlbal with some custom code in front of the web server would allow you to intercept uploaded files before they are written anywhere, encrypt them, write them to a local ramdisk and then proxy the request on the the web server proper (with the filename and decryption key to the files).

If the PHP process crashes, the encrypted file is left around but can't be decrypted. No unencrypted data gets written to (ram)disk.

In-App Billing Security and Design questions

13 votes

Hi,

I have a few questions connected to Android In-App Billing:

  1. Is it possible to make a purchase from non-Market app? I understand that it would be a vulnerability, but I have no opportunity to find out if it's possible or not.

  2. How can I get purchase state for a particular product? As far as I understand it can be done using RESTORE_TRANSACTIONS request, but it's not recommended to use very often. That's not a theoretical problem. My application allows users to buy content using in-app billing. Content can be downloaded from a server, and server must allow content downloading only if it was purchased. But it can't check if content was purchased or not without using signed response from Android Market.

  3. How can I get price and description of an item from Android Market? Seems that I know the answer and it's "there's no way it can be done", but maybe I'm wrong. It would be very useful to have a possibility of retrieving item's price.

It's very interesting to me how you solved/are going to solve these problems in your apps. Answer to any of these questions will be appreciated.

In order:

1- Nope. The in-app billing process is part of Market. If the app comes from elsewhere, there's no way for Market to verify the origin/authenticity of the application.

2- It's your responsibility to store the purchase state for a particular product. From the doc:

You must set up a database or some other mechanism for storing users' purchase information.

RESTORE_TRANSACTIONS should be reserved for reinstalls or first-time installs on a device.

3- Unfortunately, at this time you're right. File a feature request!

In the meantime, one option is to set up a website with appengine, store listings of all your content & pricing there, and then manually sync prices listed on your appengine server with the updated prices in Market. Then have your Android app pull the data from the AppEngine server. This is much better than hardcoding price values into the app itself, since you don't need to have everyone update the app immediately to see accurate pricing whenever you change something. The only caveat of this method is that if the user is in a different country, in-app billing will display an approximated price in their native currency, and there's no way for you to determine exactly what price will be displayed to them.

Related, One of the Android Developer Advocates is giving a talk on LVL/IAP at IO, called "Evading Pirates and Stopping Vampires using License Verification Library, In-App Billing, and App Engine." - It would definitely be worth your while to watch when they release the session videos on the website.

Android word dictionary security issue

13 votes

Whenever you type a word on an Android phone, the word gets remembered. This is a security issue when using things such as security questions/answers. Is there a way to turn this functionality off? So that, when you type a word, the word isn't stored anywhere.

P.S. I know that you can turn off 'word suggestions', i.e. by using the flag TYPE_TEXT_FLAG_NO_SUGGESTIONS. I've done this, however the words that you use still get stored in the background.

Thanks in advance

EDIT: This happens with custom keyboards such as AnySoftKeyboard, Swype and SwiftKey. Even though these keyboards are configurable to remember and store commonly used words - you want there to be exceptions for things like remembering your answer to security questions.

On Android 2.2+ you can use InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD to achieve the desired functionality on any security field. Despite this flag being available for older versions of Android (from Google API 3+), it seems to have no effect in Android 2.1 (API 7) and below.

It seems like you have answered your own question. Google only added support for what you are trying to do in Android 2.2 and above.

If you need to do this on earlier versions, maybe you could add some code after they exit the field that would go out to the user dictionary and remove the words that were entered in the field. I know its a kludge that doesn't completely close the security hole but its a start.

Is strip_tags() vulnerable to scripting attacks?

10 votes

Is there a known XSS or other attack that makes it past a

$content = "some HTML code";
$content = strip_tags($content);

echo $content;

?

The manual has a warning:

This function does not modify any attributes on the tags that you allow using allowable_tags, including the style and onmouseover attributes that a mischievous user may abuse when posting text that will be shown to other users.

but that is related to using the allowable_tags parameter only.

With no allowed tags set, is strip_tags() vulnerable to any attack?

Chris Shiflett seems to say it's safe:

Use Mature Solutions

When possible, use mature, existing solutions instead of trying to create your own. Functions like strip_tags() and htmlentities() are good choices.

is this correct? Please if possible, quote sources.

I know about HTML purifier, htmlspecialchars() etc.- I am not looking for the best method to sanitize HTML. I just want to know about this specific issue. This is a theoretical question that came up here.

Reference: strip_tags() implementation in the PHP source code

As its name may suggest, strip_tags should remove all HTML tags. The only way we can proof it is by analyzing the source code. The next analysis applies to a strip_tags('...') call, without a second argument for whitelisted tags.

First at all, some theory about HTML tags: a tag starts with a < followed by non-whitespace characters. If this string starts with a ?, it should not be parsed. If this string starts with a !--, it's considered a comment and the following text should neither be parsed. A comment is terminated with a -->, inside such a comment, characters like < and > are allowed. Attributes can occur in tags, their values may optionally be surrounded by a quote character (' or "). If such a quote exist, it must be closed, otherwise if a > is encountered, the tag is not closed.

The code <a href="example>xxx</a><a href="second">text</a> is interpreted in Firefox as:

<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>

The PHP function strip_tags is referenced in line 4036 of ext/standard/string.c. That function calls the internal function php_strip_tags_ex.

Two buffers exist, one for the output, the other for "inside HTML tags". A counter named depth holds the number of open angle brackets (<).
The variable in_q contains the quote character (' or ") if any, and 0 otherwise. The last character is stored in the variable lc.

The functions holds five states, three are mentioned in the description above the function. Based on this information and the function body, the following states can be derived:

  • State 0 is the output state (not in any tag)
  • State 1 means we are inside a normal html tag (the tag buffer contains <)
  • State 2 means we are inside a php tag
  • State 3: we came from the output state and encountered the < and ! characters (the tag buffer contains <!)
  • State 4: inside HTML comment

We need just to be careful that no tag can be inserted. That is, < followed by a non-whitespace character. Line 4326 checks an case with the < character which is described below:

  • If inside quotes (e.g. <a href="inside quotes">), the < character is ignored (removed from the output).
  • If the next character is a whitespace character, < is added to the output buffer.
  • if outside a HTML tag, the state becomes 1 ("inside HTML tag") and the last character lc is set to <
  • Otherwise, if inside the a HTML tag, the counter named depth is incremented and the character ignored.

If > is met while the tag is open (state == 1), in_q becomes 0 ("not in a quote") and state becomes 0 ("not in a tag"). The tag buffer is discarded.

Attribute checks (for characters like ' and ") are done on the tag buffer which is discarded. So the conclusion is:

strip_tags without a tag whitelist is safe for inclusion outside tags, no tag will be allowed.

By "outside tags", I mean not in tags as in <a href="in tag">outside tag</a>. Text may contain < and > though, as in >< a>>. The result is not valid HTML though, <, > and & need still to be escaped, especially the &. That can be done with htmlspecialchars().

The description for strip_tags without an whitelist argument would be:

Makes sure that no HTML tag exist in the returned string.

What are all the user accounts for IIS/ASP.NET and how do they differ?

8 votes

Under Windows Server 2008 with ASP.NET 4.0 installed there is a whole slew of related user accounts, and I can't understand which one is which, how to they differ, and which one is REALLY the one that my app runs under. Here's a list:

  • IIS_IUSRS
  • IUSR
  • DefaultAppPool
  • ASP.NET v4.0
  • NETWORK_SERVICE
  • LOCAL SERVICE.

What is what?

This is a very good question and sadly many developers don't ask enough questions about IIS/ASP.NET security in the context of being a web developer and setting up IIS. So here goes....

To cover the identities listed:

IIS_IUSRS:

This is analogous to the old IIS6 IIS_WPG group. It's a built-in group with it's security configured such that any member of this group can act as an application pool identity.

IUSR:

This account is analogous to the old IUSR_<MACHINE_NAME> local account that was the default anonymous user for IIS5 and IIS6 websites (i.e. the one configured via the Directory Security tab of a site's properties).

For more information about IIS_IUSRS and IUSR see:

Understanding Built-In User and Group Accounts in IIS 7

DefaultAppPool:

If an application pool is configured to run using the Application Pool Identity feature then a "synthesised" account called IIS AppPool\<pool name> will be created on the fly to used as the pool identity. In this case there will be a synthesised account called IIS AppPool\DefaultAppPool created for the life time of the pool. If you delete the pool then this account will no longer exist. When applying permissions to files and folders these must be added using IIS AppPool\<pool name>. You also won't see these pool accounts in your computers User Manager. See the following for more information:

Application Pool Identities

ASP.NET v4.0: -

This will be the Application Pool Identity for the ASP.NET v4.0 Application Pool. See DefaultAppPool above.

NETWORK SERVICE: -

The NETWORK SERVICE account is a built-in identity introduced on Windows 2003. NETWORK SERVICE is a low privileged account under which you can run your application pools and websites. A website running in a Windows 2003 pool can still impersonate the site's anonymous account (IUSR_ or whatever you configured as the anonymous identity).

In ASP.NET prior to Windows 2008 you could have ASP.NET execute requests under the Application Pool account (usually NETWORK SERVICE). Alternatively you could configure ASP.NET to impersonate the site's anonymous account via the <identity impersonate="true" /> setting in web.config file locally (if that setting is locked then it would need to be done by an admin in the machine.config file).

Setting <identity impersonate="true"> is common in shared hosting environments where shared application pools are used (in conjunction with partial trust settings to prevent unwinding of the impersonated account).

In IIS7.x/ASP.NET impersonation control is now configured via the Authentication configuration feature of a site. So you can configure to run as the pool identity, IUSR or a specific custom anonymous account.

LOCAL SERVICE:

The LOCAL SERVICE account is a built-in account used by the service control manager. It has a minimum set of privileges on the local computer. It has a fairly limited scope of use:

LocalService Account

LOCAL SYSTEM:

You didn't ask about this one but I'm adding for completeness. This is a local built-in account. It has fairly extensive privileges and trust. You should never configure a website or application pool to run under this identity.

LocalSystem Account

In Practice:

In practice the preferred approach to securing a website (if the site gets its own application pool - which is the default for a new site in IIS7's MMC) is to run under Application Pool Identity. This means setting the site's Identity in its Application Pool's Advanced Settings to Application Pool Identity:

enter image description here

In the website you should then configure the Authentication feature:

enter image description here

Right click and edit the Anonymous Authentication entry:

enter image description here

Ensure that "Application pool identity" is selected:

enter image description here

When you come to apply file and folder permissions you grant the Application Pool identity whatever rights are required. For example if you are granting the application pool identity for the ASP.NET v4.0 pool permissions then you can either do this via Explorer:

enter image description here

Click the "Check Names" button:

enter image description here

Or you can do this using the ICACLS.EXE utility:

icacls c:\wwwroot\mysite /grant "IIS AppPool\ASP.NET v4.0":(CI)(OI)(M)

I hope this helps clear things up.

How does AppArmor do "Environment Scrubbing"?

5 votes

The AppArmor documentation mentions giving applications the ability to execute other programs with or without enviroment scrubbing. Apparently a scrubbed environment is more secure, but the documentation doesn't seem to specify exactly how environment scrubbing happens.

What is environment scrubbing and what does AppArmor do to scrub the environment?

"Environment scrubbing" is the removal of various "dangerous" environment variables which may be used to affect the behaviour of a binary - for example, LD_PRELOAD can be used to make the dynamic linker pull in code which can make essentially arbitrary changes to the running of a program; some variables can be set to cause trace output to files with well-known names; etc.

This scrubbing is normally performed for setuid/setgid binaries as a security measure, but the kernel provides a hook to allow security modules to enable it for arbitrary other binaries as well.

The kernel's ELF loader code uses this hook to set the AT_SECURE entry in the "auxiliary vector" of information which is passed to the binary. (See here and here for the implementation of this hook in the AppArmor code.)

As execution starts in userspace, the dynamic linker picks up this value and uses it to set the __libc_enable_secure flag; you'll see that the same routine also contains the code which sets this flag for setuid/setgid binaries. (There is equivalent code elsewhere for binaries which are statically linked.)

__libc_enable_secure affects a number of places in the main body of the dynamic linker code, and causes a list of specific environment variables to be removed.