Web Security & VulnHawk Mastery

Injection: SQL, Commands and Templates

35 分钟

Injection happens when user input is treated as code: SQL, shell commands, templates or LDAP queries.

SQL injection

Vulnerable:

query = f"SELECT * FROM users WHERE email = '{email}'"
db.session.execute(text(query))

Input ' OR '1'='1 returns every user; worse payloads read or modify any data.

Fixed with parameters:

db.session.execute(text("SELECT * FROM users WHERE email = :email"), {"email": email})
# or simply use the ORM:
User.query.filter_by(email=email).first()

Parameters send data separately from SQL, so input can never change the query's structure. For dynamic ORDER BY columns (which cannot be parameters), map user choices to a fixed allowlist.

Command injection

Vulnerable:

os.system(f"convert {filename} thumb.png")          # filename = "x.png; rm -rf /"

Fixed:

subprocess.run(["convert", safe_path, "thumb.png"], check=True, timeout=30)

Pass a list of arguments (no shell), validate inputs and prefer libraries (Pillow) over shell commands.

Template injection

Rendering user input as a template lets attackers run code:

render_template_string("Hello " + request.args["name"])     # dangerous
render_template("hello.html", name=request.args["name"])     # safe: name is data

Finding injection

  • Review code for string-built queries, shell=True, os.system, eval, render_template_string.
  • Use static analysis (Bandit for Python, Semgrep rules).
  • Automated scanners send crafted payloads to parameters and look for errors or behaviour changes; treat their findings as leads to verify, not final answers.

Defence checklist

  • [ ] ORM or parameterised queries everywhere
  • [ ] No shell commands built from input; argument lists only
  • [ ] No eval/exec on user data
  • [ ] Database user with least privilege (cannot drop tables)
  • [ ] Errors do not reveal SQL or stack traces to users

Exercise

Search a project (yours or an intentionally vulnerable practice app such as OWASP Juice Shop or DVWA running locally) for injection patterns with Bandit or Semgrep, fix each finding with parameterisation or argument lists, and add a test that the old payload no longer works.

Check yourself

  • Why do parameterised queries prevent SQL injection?
  • How do you safely allow user-chosen sort columns?
  • Why is render_template_string with user input dangerous?

你的进度只保存在此浏览器中。

提交审核(10 积分)