From the course: Advanced Practices in Application Security
Secure coding practices
From the course: Advanced Practices in Application Security
Secure coding practices
Welcome to this video on secure coding practices for modern developers. In 2025, despite decades of awareness about SQL injection, it still ranks in the OWASP top 10. In fact, the majority of applications still have injection vulnerabilities. But SQL injection is completely preventable with proper coding practices that take just minutes to implement and can be used to prevent millions in losses. In this video, we'll explore the secure coding practices that create more resilient applications. We'll focus on memory safety, input validation, and defensive programming strategies that help mitigate attacks before they start. By the end of this video, you'll be able to apply secure coding techniques that prevent the most common attack vectors, implement input validation, and output encoding strategies in your applications. Let's start with something that CISA calls unforgivable defects. These are memory safety vulnerabilities, like buffer overflows, and they are fundamental design flaws that enable entire classes of attacks. Memory safety forms the foundation of all secure coding practices. How can we solve this? When we build Secure Cart using Rust, Go, Python, or Java, entire categories of vulnerabilities simply don't exist. The language prevents buffer overflows, use after free errors, and memory corruption attacks at the compiler level. For existing C, C++ code bases, compiler protections like address sanitizer catch memory errors before they become vulnerabilities. Input validation, your first line of defense. Now let's examine Secure Cart's product search feature. Every day, customers search for products using queries in search bar. But attackers can try to inject malicious code through these same input fields. Here's what vulnerable code looks like using Python. First, the insecure option uses direct string concatenation. The user's input is inserted directly into the SQL statement. This is dangerous because it allows attackers to inject malicious SQL code potentially compromising your database. Now, let's see what the secure option using parametized queries looks like. In this version, the query uses placeholders and passes the user input as a separate parameter. This prevents SQL injection by ensuring that input is treated as data, not executable code. Always use parametized queries to keep your database safe. However, input validation goes beyond SQL injection. In Secure Cart, we validate things like data types where we ensure product IDs are integers, not scripts, length limits, such as preventing buffer overflow attempts, character sets, such as blocking suspicious special characters, business logic, such as ensuring discount codes follow expected formats. Input validation protects data going in, output encoding protects data going out. Output encoding, protecting your users. Consider when a customer leaves a product review containing this text. Without proper output encoding, this script would execute in every visitor's browser, potentially stealing session cookies or redirecting users to malicious sites. Here's how Secure Cart handles this. In the first section, the code retrieves a user review using getUserReview and inserts it directly into an HTML string. This approach is risky because if the user review contains HTML or JavaScript code, it'll be rendered by the browser, potentially leading to cross-site scripting attacks. In the second one labeled secure, This also retrieves a user review, but then applies HTML escape to the text before inserting it into the HTML string. The HTML escape function converts special characters into their corresponding HTML entities, ensuring that any embedded HTML or JavaScript is displayed as plain text rather than executed. This prevents cross-site scripting attacks and makes the output safe for the user. These tactical approaches support a broader defensive strategy, defensive programming, building resilient systems, Defensive programming means writing code that assumes a tax will happen and prepares accordingly. In SecureCard's payment processing system, we implement several defensive strategies. Fail-safe defaults. If our fraud detection system encounters an error, it defaults to blocking the transaction rather than approving it. Better to inconvenience one legitimate customer than enable fraudulent purchases. Principle of least privilege. Our database connections use accounts with minimal necessary permissions. The product search feature can only read product data. It cannot modify user accounts or access payment information. Error handling without information disclosure. When Secure Cart encounters an error, we log detailed technical information for our developers, but show generic error messages to users, ensuring attackers cannot learn about our system architecture from the error messages. Summary. Let's do a quick recap of what we learned from this video. We examined essential secure coding techniques from memory safety to input validation to defensive programming strategies. Through secure card examples, we've seen how these practices transform vulnerable code into resilient applications that can withstand real-world attacks. In our next video, we'll explore how secure configuration and defaults complement these coding practices.
Practice while you learn with exercise files
Download the files the instructor uses to teach the course. Follow along and learn by watching, listening and practicing.