A Little Cyber Security Primer Before We Start - Authentication and Authorization
A Little Cyber Security Primer Before We Start - Authentication and Authorization
A Little Cyber Security Primer Before We Start - Authentication and Authorization
Injection flaws result from a classic failure to filter untrusted input. It can
happen when you pass unfiltered data to the SQL server (SQL injection), to
the browser (XSS – we’ll talk about this later), to the LDAP server (LDAP
injection), or anywhere else. The problem here is that the attacker can inject
commands to these entities, resulting in loss of data and hijacking clients’
browsers.
Anything that your application receives from untrusted sources must be
filtered, preferably according to a whitelist. You should almost never use a
blacklist, as getting that right is very hard and usually easy to bypass.
Antivirus software products typically provide stellar examples of failing
blacklists. Pattern matching does not work.
Prevention: The good news is that protecting against injection is “simply” a
matter of filtering your input properly and thinking about whether an input
can be trusted. But the bad news is that all input needs to be properly filtered,
unless it can unquestionably be trusted (but the saying “never say never” does
come to mind here).
In a system with 1,000 inputs, for example, successfully filtering 999 of them
is not sufficient, as this still leaves one field that can serve as the Achilles heal
to bring down your system. And you might think that putting an SQL query
result into another query is a good idea, as the database is trusted, but if the
perimeter is not, the input comes indirectly from guys with malintent. This is
called Second Order SQL Injection in case you’re interested.
Since filtering is pretty hard to do right (like crypto), what I usually advise is to
rely on your framework’s filtering functions: they are proven to work and are
thoroughly scrutinized. If you do not use frameworks, you really need to think
hard about whether not using them really makes sense in your server security
context. 99% of the time it does not.
Assuming that anyone still wants to roll their own authentication code in 2014
(what are you thinking??), I advise against it. It is extremely hard to get right,
and there are a myriad of possible pitfalls, just to mention a few:
1. The URL might contain the session id and leak it in the referer header to
someone else.
This is a classic case of trusting user input and paying the price in a resulting
security vulnerability. A direct object reference means that an internal object
such as a file or database key is exposed to the user. The problem with this is
that the attacker can provide this reference and, if authorization is either not
enforced (or is broken), the attacker can access or do things that they should
be precluded from.
For example, the code has a download.php module that reads and lets the user
download files, using a CGI parameter to specify the file name
(e.g., download.php?file=something.txt ). Either by mistake or due to laziness,
the developer omitted authorization from the code. The attacker can now use
this to download any system files that the user running PHP has access to, like
the application code itself or other data left lying around on the server, like
backups. Uh-oh.
Another common vulnerability example is a password reset function that
relies on user input to determine whose password we’re resetting. After
clicking the valid URL, an attacker can just modify the username field in the
URL to say something like “admin”.
Incidentally, both of these examples are things I myself have seen appearing
often “in the wild”.
Prevention: Perform user authorization properly and consistently, and
whitelist the choices. More often than not though, the whole problem can be
avoided by storing data internally and not relying on it being passed from the
client via CGI parameters. Session variables in most frameworks are well
suited for this purpose.
Prevention:
In transit: Use HTTPS with a proper certificate and PFS (Perfect Forward
Secrecy). Do not accept anything over non-HTTPS connections. Have the secure
flag on cookies.
In storage: This is harder. First and foremost, you need to lower your exposure.
If you don’t need sensitive data, shred it. Data you don’t have can’t be stolen. Do
not store credit card information ever, as you probably don’t want to have to deal
with being PCI compliant. Sign up with a payment processor such
as Stripe or Braintree. Second, if you have sensitive data that you actually do
need, store it encrypted and make sure all passwords are hashed. For hashing,
use of bcrypt is recommended. If you don’t use bcrypt, educate yourself
on salting and rainbow tables.
And at the risk of stating the obvious, do not store the encryption keys next to
the protected data. That’s like storing your bike with a lock that has the key in
it. Protect your backups with encryption and keep your keys very private. And
of course, don’t lose the keys!
http://example.com/app/transferFunds?
amount=1500&destinationAccount=4673243
243
After this URL is opened, a success page is
presented to Todd, and the transfer is done.
Alice also knows, that Todd frequently visits
a site under her control at
blog.aliceisawesome.com, where she places
the following snippet:
<img src=http://example.com/app/transferFunds?
Prevention:
Exercise caution. Beyond obviously using caution when using such components,
do not be a copy-paste coder. Carefully inspect the piece of code you are about to
put into your software, as it might be broken beyond repair (or in some cases,
intentionally malicious—web security attacks are sometimes unwittingly invited
in this way).
Stay up-to-date. Make sure you are using the latest versions of everything that
you trust, and have a plan to update them regularly. At least subscribe to a
newsletter of new security vulnerabilities regarding the product.
This is once again an input filtering issue. Suppose that the target site has
a redirect.php module that takes a URL as a GET parameter. Manipulating
the parameter can create a URL on targetsite.com that redirects the browser
to malwareinstall.com . When the user sees the link, they will
see targetsite.com/blahblahblah which the user thinks is trusted and is safe
to click. Little do they know that this will actually transfer them onto a
malware drop (or any other malicious) page. Alternatively, the attacker might
redirect the browser to targetsite.com/deleteprofile?confirm=1 .
It is worth mentioning, that stuffing unsanitized user-defined input into an
HTTP header might lead to header injection which is pretty bad.
Prevention: Options include:
Don’t do redirects at all (they are seldom necessary).
Epilogue
I hope that I have managed to tickle your brain a little bit with this post and to
introduce a healthy dose of paranoia and website security vulnerability
awareness.
The core takeaway here is that age-old software practices exist for a reason
and what applied back in the day for buffer overflows, still apply for pickled
strings in Python today. Security protocols help you write (more) correct
programs, which all programmers should aspire to.
Please use this knowledge responsibly, and don’t test pages without
permission!
For more information and more specific server side attacks, have a look
at: https://www.owasp.org/index.php/Category:Attack.
Feedback on this post and its mitigation advice is welcome and appreciated.
Future related posts are planned, particularly on the issue of distributed
denial-of-service (DDoS) and old-school (not web) IT security vulnerabilities.
If you have a specific request on what kind of web protection to write about,
please feel free to contact me directly at [email protected].
Here’s to website security! Cheers.