Fallible Blog Adventures with looking under the hood

The Security Checklist

This is a part of the Security Guide for Developers (in progress)
AUTHENTICATION SYSTEMS (Signup/Signin/2 Factor/Password reset)
  • Use HTTPS everywhere.
  • Store password hashes using Bcrypt with a random salt.
  • Destroy the session identifier after logout.
  • Must have the state parameter in OAuth2
  • No open redirects after successful login or in any other intermediate redirects.
  • While Signup/Login input, sanitize input for javascript://, data://, CRLF characters.
  • Set secure, httpOnly cookies.
  • In Mobile OTP based mobile verification, do not send the OTP back in the response when generate OTP or Resend OTP API is called.
  • Limit attempts to Login, Verify OTP, Resend OTP and generate OTP APIs for a particular user. Have an exponential backoff set or/and something like a captcha based challenge.
  • Check for randomness of reset password token in the emailed link or SMS
  • Set an expiration on the reset password token for a reasonable period.
  • Expire the reset token after it has been successfully used.
  • Destroy the logged in user’s session everywhere after successful reset of password.
USER DATA & AUTHORIZATION
  • Any resource access like, my cart, my history should check the logged in user’s ownership of the resource using session id.
  • Serially iterable resource id should be avoided. Use /me/orders instead of /user/37153/orders. This acts as a sanity check in case you forgot to check for authorization token.
  • Edit email/phone number feature should be accompanied by a verification email to the owner of the account.
  • Any upload feature should sanitize the filename provided by the user. Also, for generally reasons apart from security, upload to something like S3 (and post-process using lambda) and not your own server capable of executing code.
  • Profile photo upload feature should sanitize all the EXIF tags also if not required.
  • For user ids and other ids, use RFC complaint UUID instead of integers. You can find an implementation for this for your language on Github.
  • JWT are awesome, use them if required for your single page app/APIs.
ANDRIOD / IOS APP
  • salt from payment gateways should not be hardcoded.
  • secret / auth token from 3rd party SDK’s should not be hardcoded.
  • API calls intended to be done server to server should not be done from the App.
  • In Android, all the granted permissions should be carefully evaluated.
  • Certificate pinning is highly recommended.
SECURITY HEADERS & CONFIGURATIONS
  • Add CSP header to mitigate XSS and data injection attacks. This is important.
  • Add CSRF header to prevent cross site request forgery.
  • Add HSTS header to prevent SSL stripping attack.
  • Add X-Frame-Options to protect against Clickjacking.
  • Add X-XSS-Protection header to mitigate XSS attacks.
  • Update DNS records to add SPF record to mitigate spam and phishing attacks.
  • Add subresource integrity checks if loading your JavaScript libraries from a third party CDN.
  • Use random CSRF tokens and expose buisness logic APIs as HTTP POST requests. Do not expose CSRF tokens over HTTP for example in a inital request upgrade phase.
  • Do not use critical data or tokens in GET request parameters. Exposure of server logs or a machine/stack processing them would expose user data in turn.
SANITIZATION OF INPUT
  • Sanitize all user inputs or any input parameters exposed to user to prevent XSS
  • Sanitize all user inputs or any input parameters exposed to user to prevent SQL Injection
  • Sanitize user input if using it directly for functionalites like CSV import.
  • Sanitize user input for special cases like robots.txt as profile names in case you are using a url pattern like coolcorp.io/username.
  • Do not hand code or build JSON by string concatentation ever, no matter how small the object is. Use your langauge defined libraries or framework.
  • Sanitize inputs that take some sort of URLs to prevent SSRF.
  • Sanitize Outputs before displaying to users.
OPERATIONS
  • If you are small and inexperienced, evaluate using AWS elasticbeanstalk or a PaaS to run your code.
  • Use a decent provisioning script to create VMs in the cloud.
  • Check for machines with unwanted publicly open ports.
  • Check for no/default passwords for databases especially MongoDB & Redis. BTW MongoDB sucks, avoid it.
  • Use SSH to access your machines, do not setup a password.
  • Install updates timely to act upon zero day vulnerabilities like Heartbleed, Shellshock.
  • Modify server config to use TLS 1.2 for HTTPS and disable all other schemes. (The tradeoff is good)
  • Do not leave the DEBUG mode on. In some frameworks, DEBUG mode can give access full-fledged REPL or shells or expose critical data in error messages stacktraces.
  • Be prepared for bad actors & DDOS - use Cloudflare
  • Setup monitoring for your systems and log stuff (use Newrelic or something like that)
  • If developing for enterprise customers, adhere to compliance requirements. If AWS S3, consider using the feature to encrypt data. If using AWS EC2, consider using the feature to use encrypted volumes (even boot volumes can be encypted now).
PEOPLE
  • Setup an email (e.g. [email protected]) and a page for security researchers to report vulnerabilities.
  • Depending on what you are making, limit access to your user databases.
  • Be polite to bug reporters.
  • Have your code review done by a fellow developer from a secure coding perspective. (More eyes)
  • In case of a hack or data breach, check previous logs for data access, ask people to change passwords. You might require an audit by external agencies depending on where you are incorporated.
  • Setup Netflix Scumblr to hear about talks about your organization on social platforms and Google search.

Common issues with OTP based authentication

This is being published under responsible disclosure policy

Almost every app today uses a 2 factor authentication where the second factor is an SMS sent to your mobile phone. This ensures that even if your password is compromised, you will be safe as long as you have your mobile phone with you.

Problem with OTP

Problem comes when people use just SMS as the only form of authentication. Shortcuts in security are often disastrous. It would still have been okay if they implemented it perfectly. Far from it, OTP based authentications are subject to a lot of risks, sometimes:

  • send OTP API sends back OTP in the API response (funny but true)
  • They use very small OTP (convenient for users?)
  • OTPs don’t expire with time (ah, too much work already?)
  • OTPs don’t change with new generation request
  • unlimited generation of OTP is allowed (brute force)
  • unlimited verification attempts are allowed (brute force)
  • sometimes re-send OTP API sends back the OTP in the API response

This can lead your account to be comprised and hence access all your details which you have saved in your account, access wallets in your account, place order on your behalf etc.

We have built a tool to capture such badly implemented OTP systems. otp_tool.png

One such example was UrbanClap which used to send the OTP back in the response of re-send OTP API : urbanclap_realtime.png

Timeline:

  • 30/3 - Disclosed responsibly to Urbanclap
  • 10/4 - They said they fixed it
  • 11/4 - We checked iOS app, it had same issue with send OTP instead of resend OTP
  • 11/4 - We again told them iOS still has the same issue
  • 1/5 - Still not fixed, sent a mail to check why aren’t they fixing it
  • 10/5 - Still no reply from them, disclosed publicly

This type of bug is more common than one might think. Its also weird to see people use different APIs for Android, iOS and web for the exact same purpose of OTP generation!

Used your credit card online in India? It's probably stolen

During the recent months we have discovered,

  • One of the most popular PCI DSS Level 1 certified payment gateways is leaking complete credit card details. The gateway claims to do more than 15,000,000 transactions on a monthly basis.
  • Another popular payment gateway is leaking partial credit card and user personal information which can be used to engineer a variety of attacks.
  • Yet another popular payment gateway implements its request data integrity protection which can be cracked using a commodity grade gaming PC within a week, thus allowing free access to virtually anything that is being sold online in India and the transaction history of users.

We have already intimated the respective payment gateways and they are working on the fix but, we are afraid we might not be the first to discover these vulnerabilities. As India still doesn’t have something simliar to data breach intimation law in the US and based on our experiences from intimating severe data leaks to more than 15 companies, we do not think the companies will ever make this information known to their end users.

This is a general notice to the public to ensure that their cards are safe. Hackers generally do not attempt to use all the cards as soon as they get access to, so it is requested that you monitor your charges and statements or better disable current cards if possible. Domestic only debit cards which cannot ever work without CVV/ PIN and OTP can be assumed to be safe.

Companies name retracted due to frequent calls.

We will come back with more information regarding these issues once the respective companies have fixed the bugs. We know that no company wants to leak their customer’s payment and personal data and it will be a difficult and time intensive task to fix some of these issues.

At Fallible, we are building products to secure large organizations and startups alike. Contact us at [email protected]

RetireJS port to Python

We have open sourced our port of RetireJS to Python. Feel free to use to test your applications / websites.

Source

FallibleInc/retirejslib

Installation

pip install retirejs

How to use

import retirejs

retirejs.scan_endpoint("http://code.jquery.com/jquery-1.6.min.js")

Sample Output:

[{
	'detection': 'filecontent',
	'vulnerabilities': [{
		'info': ['http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-4969', 'http://research.insecurelabs.org/jquery/test/'],
		'identifiers': {
			'CVE': ['CVE-2011-4969']
		},
		'severity': 'medium'
	}, {
		'info': ['http://bugs.jquery.com/ticket/11290', 'http://research.insecurelabs.org/jquery/test/'],
		'identifiers': {
			'bug': '11290',
			'summary': 'Selector interpreted as HTML'
		},
		'severity': 'medium'
	}, {
		'info': ['https://github.com/jquery/jquery/issues/2432', 'http://blog.jquery.com/2016/01/08/jquery-2-2-and-1-12-released/'],
		'identifiers': {
			'summary': '3rd party CORS request may execute'
		},
		'severity': 'medium'
	}],
	'version': '1.6.0',
	'component': 'jquery'
}]

Automating data leak detection

Update: Overseer Demo Video (Mobile API security)

We are creating a useful data leak detection tool. This article demonstrates what has been done till now.

Data leak is the most notorious bug a consumer facing software company encounters. Data leak may include disclosure of user’s phone number, email, home address, credit cards and other personally identifiable information.

Lot of the software companies fail to ensure that these informations are kept securely in their database. Sometimes they just leak database password. On the other times:

  • Basic authentication or authorisation are often absent in their API calls.
  • On top of that they use enumerable user ids, address ids or order ids.

A typical API will look something like this:

http://www.mewantburger.com/v1/api/getUserAddress?userid=23781

And there would be no secure token in the headers (nor in the body) of the API calls, letting any user to do that API call from anywhere, the user doesn’t even have to be logged in to execute that API call successfully. One can simply run the following command from the terminal and get all the users addresses:

 $ for i in {1..25000}; do curl “http://www.mewantburger.com/v1/api/getUserAddress?userid=$i” ; done

Some people will try to strengthen the security by making the userid longer like :

10000023781

Only that a human like you and me can easily see that first 6 digits are bogus and you only need to iterate from

10000000000 to 10000025000

Anyway, we saw these kinds of bugs too often in various companies, so we decided to try and make the detection of such bugs automated.

The idea

We want to get all the APIs which leak data, so, we will record two different logged-in users activities (all the API calls) done while using the App / website. And then we will use the parameters like email, userid and phone number from user number 2 in the parameters of API calls done for user number 1. If the API call returns a valid response which matches the one for user 2, then it is leaking data, essentially.

For recording the activities one can use a proxy suite like burp or mitmproxy .

A typical users session will comprise of multiple requests and multiple responses:

User 1                           User 2


1. <Request A> <Response A>      1. <Request a> <Response a>

2. <Request B> <Response B>      2. <Request A> <Response A>

..........................       ..........................
..........................       ..........................

63. <Request C> <Response C>     63. <Request B> <Response B>

.......................          ..........................
.......................          ..........................

99. <Request Y> <Response Y>     105. <Request Y> <Response Y>

100. <Request Z> <Response Z>    106. <Request Z> <Response Z>

Problem 1:

We need to match the requests for both users.

The serial order of Requests done for <user 1> is not a one to one match for the Requests for <user 2> since the recording of activities might have some noise in the API calls captured for example, Apple (in case of iOS) might be sending some stats to its server only adding to the noise for us to suffer — bad apple (of course not just Apple). So first, we need to match them 1 to 1.

We have done this matching by using the url and keys of query params and keys of params present in the body (json, form or multipart form) between the API calls listed for those 2 users. So, that works out to be O(n^2) . Yes, it can be improved and done in O(n) too, it is left as an exercise for the reader.

Problem 2:

We need to replay request of <user 1> with parameters from request of <user 2>.

Now that we have one <Request, Response> from <user 1> and one <Request, Response> from <user 2>, we need to take some parameter values from <user 2> and replace it in the request of <user 1>.

What to take and what not to take?

For example if the developer did use the sessionToken to authenticate user but failed to validate the ownership of the userid then how will you confirm data leak? For example in this API:

User 1:
http://www.mewantburger.com/v1/api/getUserAddress?userid=23781&sessionToken=gfbjasjkagaha3hj1syu6werwteio

User 2:
http://www.mewantburger.com/v1/api/getUserAddress?userid=50897&sessionToken=uursnwrckeoweyoehdbtuspwu46

Clearly if you replace the session token as well as userid then the request of <user 1> will essentially become request of <user 2> and that would obviously return the same response as it did for <user 2>. So we want to only replace stuff which an attacker can guess like enumerable user id or email or phone number

Now, we want to make this tool generic and should be able to detect such data leaks across multiple Apps and websites. So, checking for params matching letter to letter with ‘userid’ is not very useful. So, instead we will concentrate on the values of the parameters. An attacker can only enumerate smaller number maybe less than 8 or 9 digits in length. So we might user a regex like \d{1–9} and check all the values in the params of query or request body matching this regex. (And what if sessionToken also is a similar number. Then of course our method won’t work, but we assume that will rarely be the case.)

Similarly, other regexes can be used for email, phone no. or order id.

After replacing request 1 parameters, we need to replay it and see the response and that leads to our next problem.

Problem 3:

Verifying that the response is same as it was for <user 2>.

This is the phase we are in. Exact word to word match might not be ideal since the session token if any present in the response of this new request will be of <user 1>, what if response contains that token.

Other options could be :

  • fuzzy match (but then what would be the threshold match percentage?)
  • or regex match for information leak such as addresses, email, phone in the response body.

We will make the tool open source once it gets ready!