A multitude of organizations don’t prioritize security until they’ve experienced a breach. A successful IT security strategy is inherently proactive and protective. This discussion emphasizes on circumventing ten prevalent and critical web-based IT security shortcomings.
Many businesses only start to prioritize web security risk is best practices after they’ve experienced a security breach. As an IT security specialist, I’ve repeatedly observed how the complexities of web development security can be elusive to numerous programmers, leading to overlooked website vulnerabilities.
A successful strategy for dealing with web security threats must inherently be proactive and defensive. Our goal is to cultivate a security-conscious mindset and instill a substantial level of caution in the reader.
This guide specifically aims to raise awareness of and address ten prevalent and significant web security pitfalls, which span from common web application vulnerabilities to browser vulnerabilities.
Authentication and Authorization: A Cyber Security Introduction
The difference between authorization and authentication often confuses programmers and IT professionals. The use of the abbreviation ‘auth’ for both terms further blurs their distinction.
Here’s a clear definition of the two:
Authentication: The process of confirming that a user is (or at least appears to be) who they claim to be. Authorization: The act of giving a user access to a specific resource or permission to carry out a certain action. In other words, authentication is about identifying an entity, while authorization is about defining what a given entity can do. With this understanding, let’s delve into ten common internet vulnerability issues.
What is Injection Flaws?
Injection flaws are typically the result of failing to filter untrusted input. These flaws can occur when unfiltered data is passed to the SQL server (SQL injection), to the browser (via Cross Site Scripting), to the LDAP server (LDAP injection), or elsewhere. The issue arises when the attacker can inject commands to take over clients’ browsers, leading to data loss.
Any data your application receives from an untrusted source must be filtered, ideally based on a whitelist. Using a blacklist for this purpose is not advisable, as it is challenging to set up correctly and is considered easy for a hacker to circumvent. Antivirus software products often exemplify the shortcomings of blacklists. Pattern matching is ineffective.
Prevention: Guarding against injection is “simply” about filtering our input and determining which senders are trustworthy. Filtering is a significant task because we need to process all input unless it can be unquestionably trusted.
If we filter 999 inputs in a system with 1,000 inputs, we still have one field that can potentially compromise our system.
Using Second Order SQL Injection to inject one SQL query result into another is also deemed risky. It might seem like a good idea because the database is trusted. However, if the perimeter is not secure, our input could indirectly come from a malicious source.
Since filtering is quite challenging to perfect, it is recommended to rely on our framework’s filtering functions. They are proven to work and have been thoroughly examined. If you’re not already using a framework, consider the server security advantages of adopting one.
Sure, here’s a rephrased version of the paragraphs:
Authentication Failures
Issues arising from authentication failures don’t always originate from the same source. It’s generally advised against creating your own authentication code, as it’s challenging to perfect. There are numerous potential hazards, including:
- The session ID might be included in the URL and leaked through the referer header.
- Passwords may not be encrypted during storage or transmission.
- Session IDs could be predictable, simplifying unauthorized access.
- Session fixation could be a possibility.
- Incorrectly implemented timeouts or the use of HTTP (without SSL security) could lead to session hijacking.
Prevention: The most direct method to circumvent web security vulnerabilities associated with broken authentication is to utilize a framework. If you decide to create your own code, be extremely cautious and familiarize yourself with web security considerations and potential problems that could emerge.
Cross-Site Scripting (XSS)
An attacker might send JavaScript tags as input to your web application. If this input is returned to the user without sanitization, the user’s browser would execute it. This is a common failure in input sanitization, essentially a subset of injection flaws. XSS can be as basic as creating a link and convincing a user to click on it, or it can be far more malicious. For instance, upon page load, the script would run and be used to send your cookies to the attacker.
Prevention: In simple terms, avoid returning HTML tags to the client. This would also safeguard you from HTML injection, which occurs when an attacker injects plain HTML content (like images or loud but invisible flash players). To implement this solution, transform all HTML entities to return something else. For instance, convert <script>
to return <script>
. Alternatively, you can use regular expressions to remove HTML tags using regular expressions on <
and >
. However, this is risky because some browsers may not interpret severely broken HTML. It’s safer to convert all characters to their escaped counterparts.
Unsecured Direct Object References
This is a typical instance of trusting user input and subsequently inheriting a security vulnerability. A direct object reference implies that an internal object (like a file or a database key) is exposed to the user, making us susceptible to attack. The attacker can provide this reference, and if authorization is not enforced or is broken, the attacker gains access.
For example, the code might have a download.php module that reads and allows the user to download files, using a CGI parameter to specify the file name (e.g., download.php?file=something.txt). If the developer neglected to include authorization in the code, the attacker can now use it to download system files accessible to the user running PHP (like the application code or random server data like backups).
Another instance of unsecured direct object reference vulnerability is a password reset function that relies on user input to determine their identity. After clicking the valid URL, an attacker could alter the username field in the URL to something like “admin.”
Coincidentally, I have frequently encountered both of these examples “in the wild.”
Prevention: Conduct user authorization correctly and consistently, and whitelist the choices. More often than not, the vulnerability can be completely avoided by storing data internally and not depending on data being passed from the client via CGI parameters. Session variables in most frameworks are well suited for this purpose.
Misconfiguration of Security
Misconfigurations in web servers and applications are frequently observed in my experience. Here are some instances of security issues related to misconfiguration:
- Enabling debug mode in a production environment
- Allowing directory listing on the server, which can disclose important information
- Utilizing outdated software, such as WordPress plugins or old versions of PhpMyAdmin
- Operating unnecessary services
- Failing to modify default keys and passwords, which is surprisingly common
- Disclosing error handling information, like stack traces, to potential intruders
Mitigation: Implement a robust and, if possible, automated build and deploy process that can run tests upon deployment. A simple solution to security misconfiguration is to use post-commit hooks to prevent deployment of code with default passwords or development features.
Exposure of Sensitive Data
This security vulnerability pertains to the protection of resources and cryptography. Sensitive data must always be encrypted, both in transit and at rest, without exceptions. Information such as credit card details and user passwords should never be transmitted or stored without encryption, and passwords should always be hashed. It’s crucial to use a strong crypto/hashing algorithm. If unsure, AES (256 bits and above) and RSA (2048 bits and above) are recommended by web security standards.
It’s important to note that session IDs and sensitive data should not be transmitted in URLs. Cookies containing sensitive data should be marked with the “secure” flag.
Mitigation:
- In transit: Use HTTPS with a valid certificate and Perfect Forward Secrecy (PFS). Reject all non-HTTPS connections and set the “secure” flag on cookies.
- In storage: Minimize your vulnerability by eliminating unnecessary sensitive data. The data you don’t possess can’t be stolen. Avoid storing credit card information to bypass the need for PCI compliance. Consider using a payment processor like Stripe or Braintree. Store and encrypt sensitive data, and ensure all passwords are hashed using bcrypt. If you’re not using bcrypt, familiarize yourself with salting and rainbow tables.
And it goes without saying, don’t store encryption keys near the data they protect. That’s akin to locking your bike but leaving the key in the lock. Encrypt and protect your backups, keep your keys private, and don’t lose them!
Lack of Function Level Access Control
This failure occurs when a server-side function is called without proper authorization. Developers often assume that if the server generates the UI, the client won’t be able to access functionality not provided by the server. However, an attacker can forge a request to the “hidden” functionality. The fact that the desired functionality isn’t easily accessible won’t deter an attacker. For instance, there might be an /admin panel, and the button is only present in the UI for actual admins. But without proper authorization, an attacker can discover and misuse this functionality.
Mitigation: Always perform authorization on the server side.
Cross-Site Request Forgery (CSRF)
In a CSRF attack, also known as a confused deputy attack, an attacker tricks the browser into misusing its authority to perform an action on the attacker’s behalf.
In a CSRF scenario, a site controlled by the attacker manipulates your browser, cookies, and session to send a request to a target site (like your bank). If you’re logged into your bank in one browser tab and your bank is susceptible to this kind of attack, another tab can be manipulated to misuse your browser’s credentials on behalf of the attacker, leading to the confused deputy issue. The deputy here is the browser that misuses its authority (session cookies) to execute the attacker’s commands.
Here’s an illustrative example: Attacker Alice aims to deplete target Todd’s funds by transferring some of his money to her account.
To transfer money, Todd visits the following URL: https://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243 at his bank, which is, unfortunately, susceptible to CSRF attacks. After Todd completes his transaction, a success page appears, and the transfer is finalized.
Alice knows that Todd often visits a site she controls at https://blog.aliceisawesome.com, so Alice embeds the following snippet on her site: <img src=https://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243 width=0 height=0 />
When Todd next visits Alice’s website, his browser mistakenly interprets the snippet as an image link. The browser automatically sends an HTTP GET request to fetch the image. However, instead of retrieving an image to display in the browser, the request instructs Todd’s bank to transfer $1,500 to Alice.
Interestingly, this example not only showcases the CSRF vulnerability but also the serious vulnerability of altering the server state with an idempotent (safe) HTTP GET request. HTTP GET requests should be idempotent, i.e., they should not alter the accessed resource. Idempotent methods should never be used to change the server state.
Prevention: A secret token should be stored in a hidden form field, which a third-party site cannot access. This necessitates the verification of the hidden field. Some sites may require a password before allowing you to change sensitive settings (like a password reminder email). This could be a measure to prevent the misuse of your abandoned sessions on public computers.
Using Components With Known Vulnerabilities
The heading is self-explanatory. This issue is more related to maintenance/deployment. Before integrating new code, it’s essential to conduct some research and possibly some auditing. Using code from an unknown person on GitHub, for instance, might be convenient, but it carries a significant risk of severe web security vulnerability.
There have been numerous cases where sites were compromised (i.e., an outsider gained administrative access to a system) because third-party software (like WordPress plugins) was left unpatched for years in production. If you think your hidden phpmyadmin installation will go unnoticed, you might want to familiarize yourself with DirBuster.
The takeaway here is that software development doesn’t stop when the application is deployed. Documentation, tests, and maintenance plans are necessary to keep the application updated, especially if it includes third-party or open-source components.
Prevention:
Avoid being a copy-paste coder. Thoroughly examine the code you’re about to incorporate into your software, as it might be faulty or, in some instances, deliberately harmful. Web security attacks are sometimes inadvertently invited in this manner.
Keep up with the latest versions of everything you trust and have a regular update plan. To stay informed about new security vulnerabilities, subscribe to your products’ newsletters.
Redirects and Forwards Without Validation
This issue is related to another form of input filtering. Consider a scenario where a website has a redirect.php module that accepts a URL as a GET parameter. By altering this parameter, it’s possible to create a URL on the website that redirects the user’s browser to a malicious site. The link would appear as website.com/randomtext, which seems harmless enough for a user to trust and click. However, clicking this link could lead the user to a page that drops malware or carries out other harmful actions. In another scenario, the attacker could redirect the user’s browser to website.com/deleteprofile?confirm=1.
It’s important to note that inserting unfiltered user-defined input into an HTTP header could result in header injection, which is quite serious.
Prevention strategies include:
Avoid redirects; they are rarely necessary. If a redirect is unavoidable, maintain a static list of valid redirect locations. Implement a whitelist for the user-defined parameter. Be aware that this can be complex.
Conclusion
The aim here is to stimulate your thinking and raise your awareness of potential security vulnerabilities on websites.
The key message is that traditional software practices are still relevant today. The same principles that applied to buffer overflows in the past are still applicable to pickled strings in Python today. Adhering to security protocols helps us develop better and safer software, which should always be our goal.