Saturday, September 26, 2015

How to Write Secure Code



http://stackoverflow.com/questions/2794016/what-should-every-programmer-know-about-security/2794089#2794089
http://blog.jobbole.com/16240/
Principles to keep in mind if you want your applications to be secure:
  • Never trust any input!
  • Validate input from all untrusted sources - use whitelists not blacklists
  • Plan for security from the start - it's not something you can bolt on at the end
  • Keep it simple - complexity increases the likelihood of security holes
  • Keep your attack surface to a minimum
Every feature that is added to an application adds a certain amount of risk to the overall application. The aim for secure development is to reduce the overall risk by reducing the attack surface area.
For example, a web application implements online help with a search function. The search function may be vulnerable to SQL injection attacks. If the help feature was limited to authorized users, the attack likelihood is reduced. If the help feature’s search function was gated through centralized data validation routines, the ability to perform SQL injection is dramatically reduced. However, if the help feature was re-written to eliminate the search function (through better user interface, for example), this almost eliminates the attack surface area, even if the help feature was available to the Internet at large.


The attack surface of a software environment is the sum of the different points (the "attack vectors") where an unauthorized user (the "attacker") can try to enter data to or extract data from an environment.
Examples of attack vectors include user input fields, protocols, interfaces, and services.

The basic strategies of attack surface reduction are to reduce the amount of code running, reduce entry points available to untrusted users, and eliminate services requested by relatively few users.
If codeWhichMayFail() fails, the user is an admin by default. This is obviously a security risk. The fix is simple, in this case. It involves a simple reversing of the logic. In the example instance, this is very easy to do.
isAdmin = false;
try {
  codeWhichMayFail();
  isAdmin = isUserInrole( "Administrator" );
}
catch (Exception ex)
{
  log.write(ex.toString());
}
This example is also an example of the Least privilege principle, which states you should never grant more access than required. If codeWhichmayFail() requires admin access, we should be verifying that admin access before we run that code.

  • Use defence in depth
  • Adhere to the principle of least privilege
  • Use threat modelling
  • Compartmentalize - so your system is not all or nothing
  • Hiding secrets is hard - and secrets hidden in code won't stay secret for long
  • Don't write your own crypto
  • Using crypto doesn't mean you're secure (attackers will look for a weaker link)
  • Be aware of buffer overflows and how to protect against them
There are some excellent books and articles online about making your applications secure:
A Guide to Building Secure Web Applications

https://www.owasp.org/index.php/Security_by_Design_Principles

Minimize attack surface area

Every feature that is added to an application adds a certain amount of risk to the overall application. The aim for secure development is to reduce the overall risk by reducing the attack surface area.
For example, a web application implements online help with a search function. The search function may be vulnerable to SQL injection attacks. If the help feature was limited to authorized users, the attack likelihood is reduced. If the help feature’s search function was gated through centralized data validation routines, the ability to perform SQL injection is dramatically reduced. However, if the help feature was re-written to eliminate the search function (through better user interface, for example), this almost eliminates the attack surface area, even if the help feature was available to the Internet at large.

Establish secure defaults

There are many ways to deliver an “out of the box” experience for users. However, by default, the experience should be secure, and it should be up to the user to reduce their security – if they are allowed.
For example, by default, password aging and complexity should be enabled. Users might be allowed to turn these two features off to simplify their use of the application and increase their risk.

Principle of Least privilege

The principle of least privilege recommends that accounts have the least amount of privilege required to perform their business processes. This encompasses user rights, resource permissions such as CPU limits, memory, network, and file system permissions.
For example, if a middleware server only requires access to the network, read access to a database table, and the ability to write to a log, this describes all the permissions that should be granted. Under no circumstances should the middleware be granted administrative privileges.

Principle of Defense in depth

The principle of defense in depth suggests that where one control would be reasonable, more controls that approach risks in different fashions are better. Controls, when used in depth, can make severe vulnerabilities extraordinarily difficult to exploit and thus unlikely to occur.
With secure coding, this may take the form of tier-based validation, centralized auditing controls, and requiring users to be logged on all pages.
For example, a flawed administrative interface is unlikely to be vulnerable to anonymous attack if it correctly gates access to production management networks, checks for administrative user authorization, and logs all access.

Fail securely

Applications regularly fail to process transactions for many reasons. How they fail can determine if an application is secure or not.
For example:
isAdmin = true;
try {
  codeWhichMayFail();
  isAdmin = isUserInRole( “Administrator” );
}
catch (Exception ex) {
  log.write(ex.toString());
}
If either codeWhichMayFail() or isUserInRole fails or throws an exception, the user is an admin by default. This is obviously a security risk.

Don’t trust services

Many organizations utilize the processing capabilities of third party partners, who more than likely have differing security policies and posture than you. It is unlikely that you can influence or control any external third party, whether they are home users or major suppliers or partners.
Therefore, implicit trust of externally run systems is not warranted. All external systems should be treated in a similar fashion.
For example, a loyalty program provider provides data that is used by Internet Banking, providing the number of reward points and a small list of potential redemption items. However, the data should be checked to ensure that it is safe to display to end users, and that the reward points are a positive number, and not improbably large.

Separation of duties

A key fraud control is separation of duties. For example, someone who requests a computer cannot also sign for it, nor should they directly receive the computer. This prevents the user from requesting many computers, and claiming they never arrived.
Certain roles have different levels of trust than normal users. In particular, administrators are different to normal users. In general, administrators should not be users of the application.
For example, an administrator should be able to turn the system on or off, set password policy but shouldn’t be able to log on to the storefront as a super privileged user, such as being able to “buy” goods on behalf of other users.

Avoid security by obscurity

Security through obscurity is a weak security control, and nearly always fails when it is the only control. This is not to say that keeping secrets is a bad idea, it simply means that the security of key systems should not be reliant upon keeping details hidden.
For example, the security of an application should not rely upon knowledge of the source code being kept secret. The security should rely upon many other factors, including reasonable password policies, defense in depth, business transaction limits, solid network architecture, and fraud and audit controls.
A practical example is Linux. Linux’s source code is widely available, and yet when properly secured, Linux is a hardy, secure and robust operating system.

Keep security simple

Attack surface area and simplicity go hand in hand. Certain software engineering fads prefer overly complex approaches to what would otherwise be relatively straightforward and simple code.
Developers should avoid the use of double negatives and complex architectures when a simpler approach would be faster and simpler.
For example, although it might be fashionable to have a slew of singleton entity beans running on a separate middleware server, it is more secure and faster to simply use global variables with an appropriate mutex mechanism to protect against race conditions.

Fix security issues correctly

Once a security issue has been identified, it is important to develop a test for it, and to understand the root cause of the issue. When design patterns are used, it is likely that the security issue is widespread amongst all code bases, so developing the right fix without introducing regressions is essential.
For example, a user has found that they can see another user’s balance by adjusting their cookie. The fix seems to be relatively straightforward, but as the cookie handling code is shared among all applications, a change to just one application will trickle through to all other applications. The fix must therefore be tested on all affected applications.

https://www.owasp.org/index.php/Least_privilege
The principle of least privilege recommends that accounts have the least amount of privilege required to perform their business processes. This encompasses user rights, resource permissions such as CPU limits, memory, network, and file system permissions.

Administrative Priviledges Granted to a Middleware Server

For example, if a middleware server only requires access to the network, read access to a database table, and the ability to write to a log, this describes all the permissions that should be granted. Under no circumstances should the middleware be granted administrative privileges.

Connecting to the Database as Root

In this example PHP code, only a SELECT statement from the database is issued. There is no reason to connect to the database as root. Instead, a user should be created with only the necessary access to the database that can be used to perform the SELECT query.


Don't trust user input
https://www.owasp.org/index.php/Don%27t_trust_user_input
A user or client will not always submit data your application will expect. By building robust applications that do not trust user input by default, you ensure the application will be able to handle unexpected data gracefully. Examples of user input include: form data, client information such as user-agent strings, cookies, referer, etc. Anything that is submitted in an HTTP request should be considered user input.
Detecting intrusions requires three elements:
  • the capability to log security-relevant events
  • procedures to ensure the logs are monitored regularly
  • procedures to properly respond to an intrusion once detected
You should log all security relevant information. Perhaps you can detect a problem by reviewing the logs that you couldn't detect at runtime. But you must log enough information. In particular, all use of security mechanisms should be logged, with enough information to help track down the offender. Additionally, the logging functionality in the application should also provide a method of managing the logged information. If the security analyst is unable to parse through the event logs to determine which events are actionable, then logging events provide little to no value.
Detecting intrusions is important because otherwise you give the attacker unlimited time to perfect an attack. If you detect intrusions perfectly, then an attacker will only get one attempt before he is detected and prevented from launching more attacks. Remember, if you receive a request that a legitimate user could not have generated - it is an attack and you should respond appropriately. Logging provides a forensic function for your application/site. If it is brought down or hacked, you can trace the culprit and check what went wrong. If the user uses an anonymizing proxy, having good logs will still help as "what happened" is logged and the exploit can be fixed more easily.
Don't rely on other technologies to detect intrusions. Your code is the only component of the system that has enough information to truly detect attacks. Nothing else will know what parameters are valid, what actions the user is allowed to select, etc. It must built into the application.

A common myth: “I am using a market standard Webserver, Application server and Database. Hence, I don’t need to think about separately securing my application. I rely on security mechanisms provided by those servers!”. While market standard servers are written with security in mind, the actual application’s security is the responsibility of the application team. In fact, sometimes due to lack of proper security in the application, the container (web or app server) is compromised! Thereby other applications deployed on this container are affected.
Not trusting the infrastructure could mean that every application needs to authenticate and authorize every action from surrounded systems.
Another myth: “I need not validate the requests coming from other corporate applications or services into my application, as those requests are from known sources!” In fact, other unsecured application can be the source to damage our application. This can be referred as defense in depth (multi-level security) by implementing application-level security and not trusting the default security mechanisms of the surrounded infrastructure.






Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts