I fold an orignal origami penguin from a Gum Wrapper.

there is no particular intention of referring to this photo
Postgre SQLi
I solved this SQLi challenge with an unintended solution.
[web] penguins login

I’ve already shared this method on lactf offcial discord, and I’ll share it in this article as well.
Because I was able to come up with an unintended and little known interesting technique for postgresql’s sqli.
The challenge summary consists of regular SQL and Python given by the following file: It’s a standard difficulty problem, as all you need to see to solve the challenge is a simple blacklist mistake.
allowed_chars = set(string.ascii_letters + string.digits + " 'flag{a_word}'")
forbidden_strs = ["like"]
with app.app_context():
conn = get_database_connection()
create_sql = """
DROP TABLE IF EXISTS penguins;
CREATE TABLE IF NOT EXISTS penguins (
name TEXT
)
"""
with conn.cursor() as curr:
curr.execute(create_sql)
curr.execute("SELECT COUNT(*) FROM penguins")
if curr.fetchall()[0][0] == 0:
curr.execute("INSERT INTO penguins (name) VALUES ('peng')")
curr.execute("INSERT INTO penguins (name) VALUES ('emperor')")
curr.execute("INSERT INTO penguins (name) VALUES ('%s')" % (flag))
conn.commit()
@app.post("/submit")
def submit_form():
conn = None
try:
username = request.form["username"]
conn = get_database_connection()
assert all(c in allowed_chars for c in username), "no character for u uwu"
assert all(
forbidden not in username.lower() for forbidden in forbidden_strs
), "no word for u uwu"
with conn.cursor() as curr:
curr.execute("SELECT * FROM penguins WHERE name = '%s'" % username)
result = curr.fetchall()
if len(result):
return "We found a penguin!!!!!", 200
return "No penguins sadg", 201
except Exception as e:
return f"Error: {str(e)}", 400
# need to commit to avoid connection going bad in case of error
finally:
if conn is not None:
conn.commit()
Once you realize that you can use similer to since it’s postgre sql, the rest can be solved by scripting.
However, I became suspicious about the ambiguity of the flag format in the rules, so I wanted to dump the data in non-ASCII representation as well.
In conclusion, a payload such as ' union select name from penguins where name similar to '{x39{x30....' escape '{, worked effectively. This use of {x39 as \x39 involved replacing the escape character with {, allows the brute force discovery of all ASCII characters through hex encoding.
Although it was not needed in this problem, setting escape dynamically could potentially allow various queries to be issued even on a more restricted challenges.
Outro
It’s a small memorandum.
I recently learned a lot of attack techniques specific to postgresql, so I’d like to introduce them someday. See you in the next post.