Common Attacks · Lesson 4 of 6
OWASP Top 10 for Beginners: SQL Injection, XSS and Broken Access Control
The OWASP Top 10 lists the most critical web application risks. Learn the ones you will meet as a developer — broken access control, injection, XSS, misconfiguration and more — with vulnerable code next to the fixed version.
The OWASP Top 10 is a list, maintained by the Open Worldwide Application Security Project, of the most critical security risks to web applications. It is the closest thing the industry has to a shared checklist, and "explain one OWASP risk and how to prevent it" is a very common interview question for developers and security roles alike.
The list is updated every few years. These are the risks that have appeared consistently, and the ones you are most likely to meet in real code.
1. Broken access control
Consistently one of the top risks: users can do or see things they should not. The classic form is an IDOR (Insecure Direct Object Reference):
https://college.example/results?student_id=21045 ← your result
https://college.example/results?student_id=21046 ← change one digit… someone else's result?
The flaw: the server checks that you are logged in, but not that student 21046 is you.
# Vulnerable: trusts the ID sent by the browser
@app.get("/results")
def results():
return db.get_result(request.args["student_id"])
# Fixed: the server decides whose data you may see
@app.get("/results")
@login_required
def results():
student_id = current_user.student_id # from the session, not from the request
return db.get_result(student_id)
Rule: check authorisation on the server for every request and every object — "is this user allowed to do this to this record?" Hiding a button in the UI is not access control.
2. Injection (SQL injection)
Injection happens when user input is mixed into a command — SQL, a shell command, an LDAP query — and the input changes the command's meaning.
# Vulnerable: input is glued into the SQL string
email = request.form["email"]
query = f"SELECT * FROM users WHERE email = '{email}'"
cursor.execute(query)
# If someone types: ' OR '1'='1
# the query becomes: SELECT * FROM users WHERE email = '' OR '1'='1' → returns every user
# Fixed: a parameterised query — the database treats input strictly as data
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
Parameterised queries (prepared statements) or a well-used ORM prevent SQL injection reliably. Escaping strings by hand and "blocking bad words" do not.
3. Cross-site scripting (XSS)
XSS happens when an application puts untrusted input into a web page without encoding it, so an attacker's script runs in other users' browsers — stealing sessions, changing the page or acting as the user.
# Vulnerable: a comment is inserted into HTML as-is
html = f"<p>{comment}</p>"
# A "comment" containing a <script> tag would now run for everyone who views the page
# Fixed: encode output for the HTML context
from markupsafe import escape
html = f"<p>{escape(comment)}</p>" # <script> becomes harmless text
- Use your template engine's automatic escaping (Jinja2, Django templates, React's JSX) and do not switch it off.
- Be careful with "raw HTML" features:
innerHTML,dangerouslySetInnerHTML,|safe. Sanitise with a proven library if you must allow HTML. - Add a Content Security Policy header as an extra layer that blocks unexpected scripts.
- Set session cookies as
HttpOnlyso scripts cannot read them.
4. Security misconfiguration
Default passwords, debug mode left on in production, detailed error pages showing stack traces, open cloud storage buckets, unnecessary services and admin panels exposed to the internet. These are not clever attacks — they are open doors. Fix with secure defaults, a hardening checklist and automated configuration checks.
5. Cryptographic failures
Sensitive data sent without HTTPS, passwords stored with fast hashes, home-made encryption, hard-coded keys. Use TLS everywhere, standard libraries, slow password hashing (previous lesson) and a secret manager for keys.
6. Vulnerable and outdated components
Modern apps are mostly other people's code: frameworks, npm and pip packages. A known vulnerability in one library is exploitable in every app that uses it. Keep dependencies updated, use tools like npm audit, pip-audit or GitHub Dependabot, and remove packages you no longer use.
7. Identification and authentication failures
Weak password rules, no rate limiting, session IDs in URLs, sessions that never expire, missing MFA on admin accounts. Covered in the passwords lesson.
Also on the list
- Insecure design — security was never considered in the design (for example, a password reset based on easily guessed security questions).
- Software and data integrity failures — trusting updates, plugins or CI/CD pipelines without verifying them.
- Logging and monitoring failures — attacks go unnoticed because nothing is logged or nobody looks.
- Server-side request forgery (SSRF) — tricking the server into fetching internal URLs, such as cloud metadata endpoints.
Legal and ethical line: test these vulnerabilities only in your own code or in deliberately vulnerable practice apps such as OWASP Juice Shop or DVWA running on your own machine. Trying them on real websites without written permission is illegal under the IT Act, 2000 — however curious you are.
Try it yourself: Run OWASP Juice Shop locally with Docker (docker run -p 3000:3000 bkimminich/juice-shop) and solve two beginner challenges. Then review one of your own projects: are all SQL queries parameterised, and does every endpoint check that the user owns the record?
Common interview questions
Try answering each one aloud before you open it.
1What is SQL injection and how do you prevent it?
An attack where untrusted input is concatenated into a SQL query and changes its logic, allowing data theft or modification. Prevent it with parameterised queries or prepared statements (or a safe ORM), least-privilege database accounts and input validation as an extra layer.
2What is XSS and how do you prevent it?
Cross-site scripting injects malicious scripts into pages viewed by other users. Prevent it with context-aware output encoding (template auto-escaping), sanitising any allowed HTML, avoiding unsafe DOM APIs, a Content Security Policy and HttpOnly cookies.
3What is an IDOR?
Insecure Direct Object Reference — a broken access control flaw where the application uses an identifier from the request (like an ID in the URL) to access an object without checking that the user is authorised to access that specific object.
Practise this
Build something with it
FAQs
Is the OWASP Top 10 a complete security checklist?
No. It is an awareness document of the most critical risks. For detailed requirements, OWASP also publishes the Application Security Verification Standard (ASVS) and practical Cheat Sheets.
Do frameworks protect me automatically?
Modern frameworks prevent many issues by default — parameterised ORMs, auto-escaping templates, CSRF tokens — but access control and business logic are always your responsibility.
References & further reading
Finished this lesson?
Mark it complete. Create a free account to save it on every device.