The key fix is to stop joining user input directly into the SQL string.
# Vulnerable
query = (
"SELECT * FROM users "
"WHERE username = '" + username + "' "
"AND password = '" + password + "'"
)
# Safer
query = (
"SELECT * FROM users "
"WHERE username = %s "
"AND password = %s"
)
cursor.execute(query, (username, password))
That keeps the database from treating attacker input like part of the command.