-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
88 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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))) |