Description
There is a website with a login page. Can you log in? The application is vulnerable to SQL injection.
Setup
Open the challenge login page in your browser.
Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1
Inject SQL into the username fieldObservationI noticed the challenge description explicitly flags the login page as vulnerable to SQL injection, which suggested the server is concatenating user input directly into a query and that an always-true OR condition in the username field would bypass the authentication check.The login query is likely constructed by string concatenation: SELECT * FROM users WHERE username='INPUT' AND password='...'. Entering admin' OR '1'='1 as the username closes the username string early and appends a condition that is always true, bypassing the authentication check entirely.What didn't work first
Tried: Entering a single quote (') alone in the username field to test for errors.
A raw quote does expose a SQL error if the app is vulnerable, but it does not log you in. Beginners stop here thinking it did not work. The actual goal is to complete a valid SQL expression that evaluates to true, so you need to follow the quote with OR '1'='1 or a comment to close the original query logic.
Tried: Injecting admin' OR 1=1 - into the password field instead of the username field.
In the standard login query the password check comes after the AND, so commenting it out from the password field position may not bypass the username check. The injection is more reliable in the username field because it short-circuits the entire WHERE clause before the password AND is even reached.
Learn more
SQL injection (SQLi) is one of the oldest and most dangerous web vulnerabilities - consistently ranked in the OWASP Top 10. It occurs when user-supplied input is concatenated directly into a SQL query string without sanitization. The database then executes the attacker's input as part of the query, allowing arbitrary data retrieval, authentication bypass, data modification, or even operating system command execution.
The classic login bypass payload
admin' OR '1'='1works by manipulating the query structure. A vulnerable query looks like:SELECT * FROM users WHERE username='USERINPUT' AND password='PASSINPUT'After injection it becomes:
SELECT * FROM users WHERE username='admin' OR '1'='1' AND password='...'. BecauseOR '1'='1'is always true and OR has lower precedence than AND, the WHERE clause evaluates to true for the admin row, returning it regardless of the password.Other common payloads to know:
' OR 1=1 --- comment out the rest of the query (MySQL/MSSQL)' OR 1=1 #- comment out with hash (MySQL)' OR 'x'='x- always-true string comparisonadmin'--- comment out password check entirely
Step 2
Submit the injection and collect the flagObservationI noticed the injected username payload had already broken the WHERE clause logic into an always-true condition, which suggested submitting the form with any non-empty password would complete the login and reveal the flag on the resulting authenticated page.Set username to admin' OR '1'='1 and enter any value for the password. Submit the form. The always-true WHERE clause causes the query to return a row, granting you access. The flag is displayed on the authenticated page.What didn't work first
Tried: Leaving the password field blank and only filling in the injected username.
Some backends reject empty passwords before ever reaching the SQL query, returning a client-side validation error. Entering any non-empty string as the password lets the form submit normally so the server actually executes the injected query.
Tried: Expecting the flag to appear in an error message or URL after the form submission.
The flag is placed on the page that the application renders after a successful login, not in an error or redirect parameter. If the injection worked you will land on an authenticated dashboard or success page - that is where you look for the flag text.
Learn more
Once the injected query returns a matching row, the application's authentication logic is fooled into believing the login succeeded. The server creates a session and redirects to the authenticated area, where the flag is displayed. This is authentication bypass - the attacker never needed to know a valid password.
Prevention: The definitive fix for SQL injection is parameterized queries (also called prepared statements). Instead of building a query string with user input, you pass a query template with placeholders and supply values separately. The database driver handles escaping, ensuring user input is always treated as data, never as SQL syntax. Example in Python with sqlite3:
cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))ORMs (Object-Relational Mappers) like SQLAlchemy and Django ORM use parameterized queries by default. Input validation, web application firewalls (WAFs), and the principle of least privilege (database users with only SELECT permission) provide defense-in-depth but should not replace parameterized queries as the primary control.
Interactive tools
- SQL Injection Payload GeneratorGenerate SQL injection payloads for auth bypass, UNION extraction, blind SQLi, NoSQL operator injection, and sqlmap commands. Supports MySQL, PostgreSQL, SQLite, and MSSQL.
Flag
Reveal flag
picoCTF{s0m3_SQL_...}
SQL injection occurs when user input is concatenated directly into a SQL query - always use parameterized queries or prepared statements to prevent it.