Application Security Basics
Alireza (Elijah) Emami

Alireza (Elijah) Emami (Software engineer)

Clock Icon10 min read
Share
Facebook IconLinkedin IconTwitter Icon
Application Security Basics
In today’s digital world, protecting software applications from attacks is more important than ever. This guide will help you understand how to keep your applications safe from threats and vulnerabilities. It covers essential practices and tools to ensure your software remains secure throughout its lifecycle, from development to deployment and maintenance.

Table of content

  1. What’s AppSec and Why do we need it?

  2. S-SDLC

  3. Threat Modeling

  4. Dynamic Application Security Testing (DAST)

  5. Manual Code Review and Static analysis

  6. Secure Coding Basics

  7. OWASP Top 10 Web Application Security Risks

  8. Some Other Important Security Risks

  9. References

What’s AppSec and Why do we need it?

Application security refers to the measures and practices taken to protect software applications from threats, vulnerabilities, and attacks that could compromise their functionality, data integrity, and user privacy. It includes a range of processes, methodologies, and tools designed to safeguard applications throughout their entire lifecycle, from development to deployment and maintenance. As software developers, incorporating security into every stage of the development process is crucial for building robust and trustworthy applications.

S-SDLC

We need to add Security (S) to every stage of our Software Development Life Cycle (SDLC). With any methodologies such as Agile, Waterfall, DevOps, and others, we should implement security checks at every stage.

Threat Modeling

Refer to our threat modeling course!

Dynamic Application Security Testing (DAST)

Dynamic Application Security Testing (DAST) runs automated penetration tests to find vulnerabilities in your web applications and APIs as they are running. DAST automates a hacker’s approach and simulates real-world attacks for critical threats such as cross-site scripting (XSS), SQL injection (SQLi), and cross-site request forgery (CSRF) to uncover vulnerabilities and misconfigurations that other security tools cannot detect. The recommended free option is ZAP, created by OWASP.

Manual Code Review and Static analysis

When performing a secure code review, look at the security controls, input, output, DB calls, etc. Just places where security should be happening. Then make sure that it is, and that the control is being implemented correctly.

You can also use a (Static Application Security Testing) SAST tool for your framework and/or language, which can find all sorts of things you missed in a manual review. (They are a little bit expensive!) Example: semgrep

Secure Coding Basics

1. Input Validation

Validate ALL types of input. If it's not what you are expecting, reject it. Validation includes user input (human or machine), databases, data from an API or serverless app, URL parameters, and body parameters.

Use Approved Lists/Whitelists, Not block lists/blacklists. Perform validation on the server-side, not in javascript or the client-side. Input validation is the absolute most important defence.

The following is the summary of OWASP Cheat Sheet on input validation:

  • Conduct all data validation on a trusted system (e.g., The server). Client-side validation is appropriate as a defensive layer, but the server should make the final decision

  • There should be a centralised input validation routine for the application, if not available, use what is provided by the framework

  • Specify proper character sets, such as UTF-8, for all sources of input

  • Encode data to a common character set before validating (Canonicalize)

  • All validation failures should result in input rejection

  • Determine if the system supports UTF-8 extended character sets and if so, validate after UTF-8 decoding is completed

  • Validate all client provided data before processing, including all parameters, URLs and HTTP header content (e.g. Cookie names and values). Be sure to include automated post backs from JavaScript, Flash or other embedded code

  • Verify that header values in both requests and responses contain only ASCII characters

  • Validate data from redirects (An attacker may submit malicious content directly to the target of the redirect, thus circumventing application logic and any validation performed before the redirect)

  • Validate for expected data types, data range, and data length

  • Validate all input against an allow list if possible

  • If any potentially hazardous characters must be allowed as input, be sure that you implement additional controls like output encoding, secure task specific APIs and accounting for the utilisation of that data throughout the application. Examples of common hazardous characters include: < > " ' % ( ) & + \ \' \ "

2. Output Encoding

Web services need to ensure that the output sent to clients is encoded to be consumed as data and not as scripts. This way if the output contains any sort of attack, it would become powerless. This protects your applications against cross site scripting (XSS), which we will discuss in more detail later in this course.

Here is the summary of the checklist provided by OWASP!

  • Conduct all encoding on a trusted system (e.g., The server)

  • Utilize a standard, tested routine for each type of outbound encoding

  • Contextually output encodes all data returned to the client that originated outside the application's trust boundary. HTML entity encoding is one example, but does not work in all cases

  • Encode all characters unless they are known to be safe for the intended interpreter

  • Contextually sanitize all output of un-trusted data to queries for SQL, XML, and LDAP

  • Sanitize all output of un-trusted data to operating system commands

3. Use Parameterized queries (ORM for DBs)

Parameterized queries disable injected code; parameters are treated only as data. This protects us from SQL Injection and other database injection attacks.

4. Use the Authorization and Authentication features provided by your framework and MFA

Authenticate and authorize users through central systems available from your organization, such as Active Directory, Okta, Single Sign-On (SSO), or others. Never implement or create your own authentication system. Try to implement two-factor authentication whenever possible.

5. Use the identity and session management features available in your framework, network, or cloud provider

Session management

  • Do not allow session tokens to be sent over HTTP (use HTTPS).

  • Do not create your own session token generation code.

  • Prevent session fixation attacks by creating a new token upon user login.

  • Keep session IDs out of URLs.

6. Do not cache sensitive page data

What is sensitive page data? Anything that is personally identifiable information (PII), secrets (passwords, session ID, etc), credit card or other payment info, governmental secrets, intellectual property, etc.

How do you ensure you don't cache sensitive data?

  • Use the Cache-control security header to help with this

  • Ensure your cookies that host sensitive data only ‘persist’ for as long as they need to (use the ‘expires’ and ‘max-age’ settings)

  • Classify and label all your data, so you know what is, and is not, sensitive

7. Secure cookies

Sensitive data should be stored in secure cookies, and all available security features for cookies should be used, including:

  • Secure Flag – HTTPS only

  • HTTPonly flag – cookies not accessible by javascript

  • Max-age and Expires – set a length of time for persistence

  • Domain – name other domains that can use your cookies

  • Path – specify which parts of the app can use the cookie

  • Same-Site – Cookies can only come from within your own site

Cookie Prefixes can be used as an additional layer of security, so that if part of your site is compromised, it could restrict access to those cookies.

Types of Cookie Prefixes

__Secure-
__Host-

8. Take every possible precaution when performing file uploads

  • Always use a pre-made 3rd party component for this, if available.

  • Do not pass user supplied data directly to any dynamic include function

  • Require authentication before allowing a file to be uploaded

  • Limit the type of files that can be uploaded to only those types that are needed for business purposes

  • Validate uploaded files are the expected type by checking file headers. Checking for file type by extension alone is not sufficient

  • Do not save files in the same web context as the application. Files should either go to the content server or in the database.

  • Prevent or restrict the uploading of any file that may be interpreted by the web server.

  • Turn off execution privileges on file upload directories

  • Implement safe uploading in UNIX by mounting the targeted file directory as a logical drive using the associated path or the chrooted environment

  • When referencing existing files, use an allow list of file names and types. Validate the value of the parameter being passed and if it does not match one of the expected values, either reject it or use a hard-coded default file value for the content instead

  • Do not pass user supplied data into a dynamic redirect. If this must be allowed, then the redirect should accept only validated, relative path URLs

  • Do not pass directory or file paths, use index values mapped to pre-defined list of paths

  • Never send the absolute file path to the client

  • Ensure application files and resources are read-only

  • Scan user uploaded files for viruses and malware, For example use AssemblyLine (it’s free!)

9. Error handling

All errors should be caught, handled, logged, and, if appropriate, alerted upon. Do not log any sensitive info including system details, session identifiers or account information.!

What should be logged?

  • Every user login

  • Login fails and any application errors

  • Brute force attempts

  • Security related events (including failed attempts)

  • Type of event, timestamp, URL including subdomain and page, source IP, username and/or identity of user, outcome of the event

OWASP advices on logs:

  • Use error handlers that do not display debugging or stack trace information

  • Implement generic error messages and use custom error pages

  • The application should handle application errors and not rely on the server configuration

  • Properly free allocated memory when error conditions occur

  • Error handling logic associated with security controls should deny access by default

  • All logging controls should be implemented on a trusted system (e.g., The server)

  • Logging controls should support both success and failure of specified security events

  • Ensure logs contain important log event data

  • Ensure log entries that include untrusted data will not execute as code in the intended log viewing interface or software

  • Restrict access to logs to only authorized individuals

  • Utilize a master routine for all logging operations

  • Do not store sensitive information in logs, including unnecessary system details, session identifiers or passwords

  • Ensure that a mechanism exists to conduct log analysis

  • Log all input validation failures

  • Log all authentication attempts, especially failures

  • Log all access control failures

  • Log all apparent tampering events, including unexpected changes to state data

  • Log attempts to connect with invalid or expired session tokens

  • Log all system exceptions

  • Log all administrative functions, including changes to the security configuration settings

  • Log all backend TLS connection failures

  • Log cryptographic module failures

  • Use a cryptographic hash function to validate log entry integrity

The following information must be in the logs

  • What type of event occurred (why this event is security-related/name for event)

  • When the event occurred (timestamp)

  • Where the event occurred (URL)

  • The source of the event (IP address) (If the IP comes from X-Forwarded-For header do not forget to properly validate it, as it could have been tampered with.)

  • The outcome of the event

  • (If possible) the identity of any individuals, users or subjects associated with the event

10. Sensitive or decision-making information should never be stored in URL parameters

Use secure cookies instead!

11. HTTPS ! and TLS

Use these headers: Strict-Transport-Security: max-age=<expire-time>; includeSubDomains

12. Tips

  • Allow users to cut and paste into the password field, to allow for use of password managers.

  • Disable password autocomplete features in browsers.

13. Use secret stores

All connection strings, hashes, passwords and other system secrets must be kept in a secret store and of course no secrets should be stored in the source code!

If there are secrets in the code, rotate them before moving them to a secret manager.

Semgrep Secrets is a tool that can find all of the secrets in the code automatically (there should be other available tools doing this, too.)

Some of the common used secrets are:

  • Database Connection Strings

  • Api Keys

  • API Secrets

  • Data Encryption Keys

  • K8S secrets

  • CI/CD secrets

  • Any type of password, for anything

  • SSL/TLS Keys

  • SSH Keys

  • License keys and etc.

14. Storing Password

If you are storing passwords, then they should be salted (Make the salt at least 28 random characters that were generated with an approved random generator.), then hashed, then stored (one field for the new value, another for the salt, which is not a secret).

15. Api security practices

  • Create a complete inventory of all APIs

  • Use an API gateway to connect

  • Rate Limiting, Throttling and Resource Quotas on ALL APIs

  • Logging, monitoring and alerting, same as for web apps

  • Block all unused HTTP methods/verbs

  • Use a service mesh for communication management

  • Implement standards for your org, enforce them

  • Strict linting of all calls

  • Authenticate THEN authorize

  • Avoid verbose error messages

  • Treat each one as its own island and never assume trust (AuthN& AuthZ)

  • Decommission old or unused versions of APIs.

  • All the same secure coding practices you normally do and mentioned above; input validation using approved lists, parameterized queries, static analysis, dynamic analysis, etc

OWASP Top 10 Web Application Security Risks

  1. Injection

  2. Broken Authentication

  3. Sensitive Data Exposure

  4. XML External Entities (XXE)

  5. Broken Access Control

  6. Security Misconfiguration

  7. Cross Site Scripting (XSS)

  8. Insecure Deserialization

  9. Using Components with Known Vulnerabilities

  10. Insufficient Logging & Monitoring

1. Injection

Definition: Tricking a system into running an attacker’s code, instead of its own.

Mitigation: Input validation, using parameterized queries if accessing a database.

Action: Code review (SAST) and testing (DAST and/or IAST) required. Apply least privilege to all accounts and systems to minimize damage if attack is successful.

2. Broken Authentication

Definition: Errors in implementation of Session Management and/or Authentication (AuthN), allowing inappropriate access or privilege to systems, data and/or user sessions.

Mitigation: Following best practices as listed in Chapter 4, Sections: Session Management, Authentication.

Action: Code review (SAST) and testing (DAST and/or IAST) required.

3. Sensitive Data Exposure

Definition: Sensitive or private data exposed or leaked to users or systems that should not have been. Caused by broken protections, mis-labelling or other mistreatment of data.

Mitigation: Label your data’s sensitivity level, follow best practices as described in Chapter 3, Section: Protecting Sensitive Data.

Action: Code review (SAST) and testing (DAST and/or IAST) required. Your org may require audits as well, verify you are compliant with applicable regulations such as GDPR (European Union) or ISTG (Canada).

4. XML External Entities (XXE)

Definition: Some XML processor allow the loading of entities that are defined outside the document (i.e. External Entities)". An attacker taking advantage of this is able to instruct the vulnerable XML processor, via its own crafted malicious XLM file, to send requests (ex: HTTP/FTP/…) to internal or external systems in order to perform actions or read data. Essentially, this is misconfiguration of XML processors, but it is so pervasive and damaging, that it has been granted its own category.

Mitigation: Don’t use XML (use JSON or something else more modern). If this is not an option, disable these features on all XML processors (XML external entity and DTD processing).

Action: Audit all XML parsers for this issue. Add a dedicated security unit test suite to constantly ensure that any XML parser instantiated is correctly configured. Manual testing looking specifically for this issue. More details will be provided later in this chapter.

5. Broken Access Control

Definition: Errors in implementation of Access Control and/or Authorization (AuthZ), allowing inappropriate access or privilege to systems, and/or data.

Mitigation: Following best practices of IAM.

Action: Code review (SAST) and testing (DAST and/or IAST) required.

6. Security Misconfiguration

Definition: Any system that is improperly configured such that it leads to security vulnerabilities.

Mitigation: Follow the hardening guide for every product in your network. Implement a defense-in-depth strategy to minimize damage if something is missed. If possible, hire someone well-experienced with each system for implementation and/or auditing.

Action: Config audits and change management (self-documenting, preferably), and testing (DAST and/or IAST) required.

7. Cross Site Scripting (XSS)

Definition: Tricking an application to run an attacker’s JavaScript, in a user’s browser.

Mitigation: Input validation, output encoding, Content Security Policy (CSP) + x-xss-protection security headers. As covered in Chapters 2, 3 and 4.

Action: Code review (SAST) and testing (DAST and/or IAST) required.

8. Insecure Deserialization

Definition: An attacker replaces a serialized object with their own, malicious, serialized object. The object is deserialized as the attack is executed.

Mitigation: Whenever possible, avoid using serialization. If unavoidable, do not accept objects from unknown sources, or only use primitive (unchangeable/basic) data classes from an approved/accepted list.

Action: This list is long and will be discussed at length later in this chapter. Code review (SAST) and testing (DAST and/or IAST) required, at a minimum.

9. Using Components with Known Vulnerabilities

Definition: Including a library, dependency or component that contains a known security vulnerability in your application, potentially creating the same vulnerability in your application.

Mitigation: Third-Party Components, use a Software Composition Analysis (SCA) tool to versify if your components are known to be vulnerable.

Action: Use SCA (like osv-scanner) against your code repos and in your build pipelines/processes.

10. Insufficient Logging & Monitoring

Definition: Attacks and other security events or incidents not being detected/prevented/documented due to improper, mis-configured or absent logging and/or monitoring systems.

Mitigation: Section: Error Handling, Logging and Monitoring.

Action: Auditing and testing of these systems required to ensure that events are being detected properly and timely.

Some Other Important Security Risks

These following security risks are not part of the OWASP Top 10 (2017) list, but they are very important.

Buffer overflows

  • Buffer overflows can only happen in languages that are not memory safe, like C

  • Memory-safe languages include java, .net, ruby, or rust, basically anything modern, so simply use a memory-safe language to avoid this

  • Buffer overflows are terrifying, because they can result (in worst case) with RCE (remote code execution)

  • Buffer overflows are related to integer overflows and strcpy vulnerabilities

Cross Site Request Forgery (CSRF)

This vulnerability depends on the victim being logged into a vulnerable site, then clicking on a malicious link (either on a malicious site or in a phishing email). Passing an anti-CSRF token is the most user-friendly defense, but you can also use a captcha or have them re-enter their password if the token wasn’t an option for some reason.

Tips:

  • Only perform transactions on PUT or POST, never GET

  • Use cookie ‘SameSite’ setting to block this as well!

  • Anti-CSRF defenses built directly into .Net & Ruby on Rails

For languages that don’t have an Anti-CSRF feature built in:

  • For Java: OWASP CSRF Guard or Spring Security

  • For PHP and Apache: CSRFProtector Project

  • For AngularJS: Cross-Site Request Forgery (XSRF) Protection

  • Java Spring has functionality you can configure yourself

  • Django has middleware you can configure yourself

References

tanya janca, Secure Coding (Semgrep Academy),https://academy.semgrep.dev/courses/secure-coding

OWASP Foundation. "OWASP Top 10 - 2021", 2021.https://owasp.org/www-project-top-ten/