Skip to content

Commit

Permalink
add pin level
Browse files Browse the repository at this point in the history
  • Loading branch information
zardus committed Sep 1, 2024
1 parent 70ecd59 commit 23925b5
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 6 deletions.
1 change: 0 additions & 1 deletion web-security/auth-bypass-cookie/server
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,5 @@ def challenge_get():
</body></html>
"""

os.setuid(os.geteuid())
app.secret_key = os.urandom(8)
app.run("challenge.localhost", int(os.environ.get("HTTP_PORT", 80)))
1 change: 0 additions & 1 deletion web-security/level-3/server
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,5 @@ def challenge_get():
return page


os.setuid(os.geteuid())
app.secret_key = os.urandom(8)
app.run("challenge.localhost", int(os.environ.get("HTTP_PORT", 80)))
10 changes: 6 additions & 4 deletions web-security/module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ challenges:
name: Authentication Bypass 1
- id: auth-bypass-cookie
name: Authentication Bypass 2
- id: level-4
- id: sqli-pin
name: SQLi 1
- id: level-4
name: SQLi 2
description: Exploit a structured query language injection vulnerability to login
- id: level-5
name: SQLi 2
name: SQLi 3
description: Exploit a structured query language injection vulnerability to leak data
- id: level-6
name: SQLi 3
name: SQLi 4
description: Exploit a structured query language injection vulnerability with an unknown database structure
- id: level-7
name: SQLi 4
name: SQLi 5
description: Exploit a structured query language injection vulnerability to blindly leak data
- id: level-8
name: XSS 1
Expand Down
13 changes: 13 additions & 0 deletions web-security/sqli-pin/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Of course, these sorts of security gaps abound!
For example, in this level, the specification of the logged in user is actually secure.
Instead of get parameters or raw cookies, this level uses an encrypted session cookie that you will not be able to mess with.
Thus, your task is to get the application to actually authenticate you as admin!

Luckily, as the name of the level suggests, this application is vulnerable to a _SQL injection_.
A SQL injection, conceptually, is to SQL what a Command Injection is to the shell.
In Command Injections, the application assembled a command string, and a gap between the developer's intent and the command shell's actual functionality enabled attackers to carry out actions unintended by the attacker.
A SQL injection is the same: the developer built the application to make SQL queries for certain goals, but because of the way these queries are assembled by the application logic, the resulting actions of the SQL query, when executed by the database, can be disastrous from a security perspective.

When you find the SQL query into which you can inject your input (hint: it is the only SQL query to substantially differ between this level and the previous level), look at what the query looks like right now, and what unintended conditions you might inject.
The quintessential SQL injection adds a condition so that an application can succeed without knowing the password.
How can you accomplish this?
69 changes: 69 additions & 0 deletions web-security/sqli-pin/server
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/opt/pwn.college/python

import tempfile
import sqlite3
import random
import flask
import os

app = flask.Flask(__name__)

class TemporaryDB:
def __init__(self):
self.db_file = tempfile.NamedTemporaryFile("x", suffix=".db")

def execute(self, sql, parameters=()):
connection = sqlite3.connect(self.db_file.name)
connection.row_factory = sqlite3.Row
cursor = connection.cursor()
result = cursor.execute(sql, parameters)
connection.commit()
return result

db = TemporaryDB()
# https://www.sqlite.org/lang_createtable.html
db.execute("""CREATE TABLE IF NOT EXISTS users AS SELECT "admin" AS username, ? as pin""", [random.randint(1, 2**64)])
# https://www.sqlite.org/lang_insert.html
db.execute("""INSERT INTO users SELECT "guest" as username, 1337 as pin""")

@app.route("/", methods=["POST"])
def challenge_post():
username = flask.request.form.get("username")
pin = flask.request.form.get("pin")
if not username:
flask.abort(400, "Missing `username` form parameter")
if not pin:
flask.abort(400, "Missing `pin` form parameter")

try:
user = db.execute(f'SELECT rowid, * FROM users WHERE username = "{username}" AND pin = {pin}').fetchone()
except sqlite3.Error as e:
flask.abort(500, f"SQL error: {e}")

if not user:
flask.abort(403, "Invalid username or pin")

flask.session["user"] = username
return flask.redirect(flask.request.path)

@app.route("/", methods=["GET"])
def challenge_get():
page = "<html><body>"
if not flask.session.get("user", None):
page += "Welcome to the login service! Please log in as admin to get the flag."
else:
username = flask.session.get("user")
page = f"<html><body>Hello, {username}!"
if username == "admin":
page += "<br>Here is your flag: " + open("/flag").read()

return page + """
<hr>
<form method=post>
User:<input type=text name=username>PIN:<input type=text name=pin><input type=submit value=Submit>
</form>
</body></html>
"""

app.secret_key = os.urandom(8)
app.run("challenge.localhost", int(os.environ.get("HTTP_PORT", 80)))

0 comments on commit 23925b5

Please sign in to comment.