Introduction to OWASP (Opensource Web Application Security Project)
Objective: Understand the top 10 most common web application attacks, their impact, and how these attacks can be prevented or mitigated!
Resource usage: Learn OWASP top 10 risks!
The story for this article: since my company, where I work, forced every employee to finish the course above, I want to write down something about my ability, or what I understood while watching the resource. I will put my story about some security issues I have faced before to remind me not fucked up again!
Top 10 OWASP and more
It could be already outdated, but I'm here to learn its essence and concepts; name or definition could be changed, but the essence never!
Injection
I think it is best known as "SQL Injection". Example, if we don't validate input username = "admin' OR '1'='1' --". Then our code will be fucked if:
SQL Injection
def login(username, password):
query = f"SELECT * FROM users WHERE user='{username}' AND pass='{password}'"
# username = "admin' --"
# → Query: SELECT * FROM users WHERE user='admin' --' AND pass='...'
# Consequence: Bypass authentication and more....
It is already prevented by most modern frameworks today, but it's better to know its essence instead of using a framework without understanding why it is secure!
Broken Authentication and Session Management
Prevent "Impersonate":
- Use a strong password, multi-factor authentication.
- Require current password/credentials when "sensitive" information is requested or changed, like in my Techcombank - Banking App, I want to view my CCV for the current card, it always requires me to enter my secret PIN.
- Log out or expire session after xxx amount of time.
And something else I didn't really understand
Cross-site Scripting (XSS)
Why XSS? because CSS will get mis-understand related with Cascading Style Sheets xD
What is it? Still same like injection but executed by browser
How to mitigate? Just alway untrust the fucking input data!
Broken Access Control
I could tell a story related to this, so it is about a lazy issue. Back in 2017, I was working with the role of System Admin and yeah manual tester as well, LOL. When my department (4 people) is creating a new tool for internal usage. When the tool was about to finish and ready to release, the leader asked me to test and report if any issues were found.
So in the user view, the menu of the manager is hidden, but you can still access the manager page by entering the direct URL xD. I asked why that was. He just told skip it, haha.
So let me provide a simple issue by pseudocode
// Frontend - Only hide button
{user.role === 'admin' && <Link to="/admin">Admin Panel</Link>}
// Backend doesn't check role
app.get('/admin', (req, res) => {
return res.json(adminData);
});
Security Misconfiguration
Yes, this is simple to understand, misconfiguration will fucked you up!
The most common issue is enabling fucking debug flag! Developers deploy themself; no one verifies or validates changes for deployment! This simple misconfiguration can lead to many, many more problems later!
The example I really remember about: Path traversal via misconfigured NGINX alias
Example - bad:
DEBUG=True
ALLOWED_HOSTS=['*']
Example - good:
DEBUG=False
ALLOWED_HOSTS=['yourdomain.com']
SECRET_KEY=os.environ.get('SECRET_KEY') # From env, not hardcode
Sensitive Data Exposure
The resource showed back in 2017, it was using MD5/SHA1 hash solution, which is well-known as insecure
# Bad
password_hash = md5(password)
# Great for example xD
password_hash = bcrypt.hash(password, 12)
HTTP vs HTTPS: HTTPS could prevent Man-in-the-Middle (MitM)
Storing Sensitive Data in Plain Text: It is about dev behavior, i guess? Because it is a very bad practice, if we store sensitive information without hashing or tokenizing.
Exposing Data in Logs/Errors: Haha, I see myself in this sometimes, for debugging purposes, but forgot to remove or set the log level.
Unnecessary Data Collection: Collect more information than required? This can be related to speed or performance. It would be better if we select only 2 required fields rather than select all fields. I have been told by my developer friend in the very early days, when I started typing echo hello world!
Additional mask for logs:
logger.info(f"Processing card: ****{card[-4:]}") # Show only last 4 fucking number!
Insufficient Attack Protection
It was updated to: Security Logging and Monitoring Failures - A09:2021
When I'm learning this section, the first thing I thought was Rate Limit, we should not trust users even if it was deployed to the internal environment, who knows in the future they will not fucked us up? Just set the fucking Rate Limit to prevent issues in the future!
Other key protections are: Account Lockout, Automated Response, and Web Application Firewall (WAF).
Conclusion: Defense in depth!
Cross-site request forgery (CSRF)
I think I was familiar with this before long time ago, but I never understood it, haha. So an example with PHP - Laravel.
So, CSRF protection prevents an attacker from using the authenticated session of a victim to send an illegal request.
CSRF Token generated with the user session. When sending a request to the server, it will go together. Server validates by checking the token to see if it matches with session.
- Match: process request
- Not match: reject (with 419 status response)
And only need to use CSRF for state-changing requests: POST/PUT/DELETE/PATCH. Other state like GET/HEAD/OPTIONS is not needed!
Using Components with Known Vulnerabilities
We can understand that they are a third-party component.
- Virtual Patch: Workaround by block, limit access, or whatever, but do not fix the real issue! Short-term solutions, bro!
- Real Patch: So we can have a small example with a Python package, which is a third-party component because we would install/import and use it. Ex
requestsversion1.0.0hasCVE-XXX, fix it by upgrading it to version1.0.1.. Ex: CVE-2023-32681
# Vulnerable
requests==2.6.0 # CVE-2023-32681: Certificate validation bypass
# Fixed example
requests==2.31.0 # Patched version
That is a simple example, Known vulnerabilities can be appear in:
- Third-party libraries (requests, lodash, spring, etc.)
- Frameworks (Laravel, Django, React)
- OS packages (OpenSSL, bash)
- Containers/images (Docker base images)
- Dependencies of dependencies (transitive dependencies)
Underprotected APIs
This is basic, nothing much to tell, I guess...
Simple example on a project I recently used. The Pydantic package used data validation library for Python.
I remember I used it to validate both requests to the API and responses from the API.
Sample pseudo code for input:
from pydantic import BaseModel, EmailStr, Field
# Define schema cho request
class CreateUserRequest(BaseModel):
username: str = Field(min_length=3, max_length=20)
email: EmailStr # Auto validate email format
age: int = Field(ge=18, le=100) # >= 18 and <= 100
password: str = Field(min_length=8)
# API endpoint
def create_user(request_data):
# ✅ Pydantic validate automatically
user = CreateUserRequest(**request_data)
# ❌ If invalid:
# {"username": "ab"} → ValidationError: min_length 3
# {"email": "bad-email"} → ValidationError: invalid email
# {"age": 15} → ValidationError: must be >= 18
# ✅ If valid, continue processing
save_to_db(user)
return {"message": "User created"}
# Usage:
create_user({
"username": "john",
"email": "john@example.com",
"age": 25,
"password": "SecurePass123"
})
For response validation, you can use Google to search, but putting it here is not necessary, haha
And put the fucking Rate Limit
XML external entities (XXE)
No idea about this much, I guess I haven't used this feature before
But good to know how to prevent in a scenario where you are processing XML data.
Insecure deserialization
Hmm, from what I'm understanding, it is not only validate serialized object, also need to validate deserilialized object progress?
Insufficient logging and monitoring
Lack of logging and monitoring, which is unable to discover an attack when it happens or has happened!
Basically, make a system with fully logged (but only with useful logs) and monitored (with useful metrics), sounds easy, but in fact it is hard AF!!!
Simple example AF to help you/me to understand: log when a user enters wrong credentials and notify if there are like 10 failed logins from a single account / single IP (Which can be known as brute-force!)
Updated OWASP from 2021 -> 2025 xD
Software and data integrity failures
What was that? Supply chain attack
What the hell is Supply chain attack? When the third-party software, tools, or dependencies your product relies on become compromised, outdated, or malicious without you noticing!
How to prevent or reduce the risk of being attacked? I think there are some basic things, like scanning for CVE/Vulnerable, using an image tag with a hash, not a tag, because they could be changed
Sample command to scan an image and get SBOM, this is for compliance requirements to prove what you did on that day. Otherwise integrated to CI/CD, no need for it really in my opinion xD
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd):/output \
aquasec/trivy:latest image \
--format cyclonedx \
--output /output/sbom.json \
nginx:latest
Server-side Request Forgery
So basically, just don't trust anyone, anything, even if they are in the same internal network.
Zero trust (Never trust, always verify) for everything:
- Input validation and strict as most you can
- Network segmentation: allow specific and known traffic flows, always use a service account with the least privileges
- Service authentication/authorization: Yes, trust fucking no one, even in the internal network!
- Monitor and Alert!
Extra section
Defense in depth
It could be boring while reading, but in fact, they did really great to provide complete information, covering almost everything you need to do!
STRIDE
Hmm, this appears in the exam Kubernetes and Cloud Native Security Associate (KCSA). I would prefer not to talk about it here!
# Search google for: STRIDE framework
The STRIDE framework is a threat modeling methodology developed by Microsoft to help identify potential security threats in software by categorizing them into six types: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, and Elevation of Privilege, each corresponding to a core security property like Authenticity or Confidentiality, guiding developers to find and fix vulnerabilities early in the Software Development Life Cycle (SDLC).
What I'm missing?
I think some sections below are missing, but I'm too lazy to continue xDD
- Security Headers
- Secrets Management
Conclusion
The course I used to write this article is great, I believe. Great explanation for something I used to see but never understood its essence!
And most of it can be reduced by implementing a correct CI/CD pipeline. I would like to give a link to my DevSecOps pipeline here xD:
- Practical DevSecOps: Securing the Pipeline from Code to Deployment - Part 1
- Practical DevSecOps: Hardening and Monitoring: Benchmarking and Runtime Security in DevSecOps - Part 2
- Practical DevSecOps: Automating Security, Integrating DevSecOps into CI/CD with Jenkins and Golang application - Part 3
Not really perfect, a little outdated at this time (1 year ago xD). But still has essences in some aspect to prevent/reduce the chance of being attacked!!!