SQL隱碼攻擊

cdrcsy發表於2024-07-02
  1. SQL隱碼攻擊介紹
    結構化查詢語言(SQL)主要用於與資料庫互動的文字語言,SQL Injection就是利用某些資料庫的外部介面將使用者資料插入到實際的資料庫操作語言中,從而達到入侵資料庫乃至作業系統的目的,主要由於程式對使用者輸入的資料沒有進行嚴格的過濾,導致非法資料庫查詢語句執行。
    SQL隱碼攻擊具有很大的危險,可以利用它讀取、修改或者刪除資料庫內的資料,獲取資料庫中的使用者名稱和密碼等敏感資訊,甚至可以獲得資料庫員的許可權,SQL Injection也很難防範,無法透過安裝系統補丁或進行簡單的安全配置進行自我保護,一般防火牆也無法攔截SQL Injection攻擊。

    http://127.0.0.1/user.php?username=angel' or '1=1
    這樣的SQL可以登入系統。因為新增了一個恆等。
    http://127.0.0.1/user.php?username=angel' /*
    http://127.0.0.1/user.php?username=angel' #

    在SQL中,"/*","#" 可以將後面的語句註釋掉。

  2. PrepareStatement+Bind-variable
    對Java、JSP開發的應用,可以使用PrepareStatement+Bind-variable來防止SQL隱碼攻擊,
    php5開始,擴充套件mysqli中支援PrepareStatement,在使用這類語言作為資料庫開發時,強烈建議使用PrepareStatement+Bind-variable來實現,儘量不要使用拼接的SQL。

  3. 使用應用程式提供的轉換函式
    mysql c api:使用mysql_real_escape_string() API呼叫。
    mysql++ :使用escape和quote修飾符。
    php : 使用mysqli,支援PrepareStatement.
    perl DBI :使用placeholders或者quote方法。
    ruby DBI:使用placeholders或者quote方法。

    pymysql為例, 它在執行sql前,會對sql中的特殊字元進行轉義,如

字元轉義:
def escape_string(value, mapping=None):
"""escape_string escapes value but not surround it with quotes.

    Value should be bytes or unicode.
    """
    if isinstance(value, unicode):
        return _escape_unicode(value)
    assert isinstance(value, (bytes, bytearray))
    value = value.replace('\\', '\\\\')
    value = value.replace('\0', '\\0')
    value = value.replace('\n', '\\n')
    value = value.replace('\r', '\\r')
    value = value.replace('\032', '\\Z')
    value = value.replace("'", "\\'")
    value = value.replace('"', '\\"')
    return value

執行sql的正確方法,不要在sql中拼接引數,字元轉義只會針對引數args

execute(query, args=None)

django/sqlalchemy
orm框架都是使用pymysql/MySQL-python等庫,並且都使用execute(query,args)呼叫,將sql與引數分開傳入。

sql注入檢測工具
sqlmap

  1. 自定義函式進行校驗
    如果現有轉換函式仍然不能滿足要求,需要自己編寫函式進行輸入效驗,輸入驗證是一個很複雜的問題,輸入驗證的途徑可以分為以下幾種:
    整理資料使之變得有效。
    拒絕已知的非法輸入 。
    只接受已知的合法輸入。
    採用正規表示式來對使用者提供的輸入資料進行嚴格的檢測和驗證。

function safeRequest ($ParaName,$ParaType)
{
/---傳入引數----/
/* ParaName:引數名稱-字元型/
/
ParaType:引數型別-數字型(1表示引數是數字或字元,0表示引數為其他)/
if ($ParaType == 1)
{
$re = “/[^\w+$]/”;
}
else
{
$re = “/(|\’ | (%27)|;|(%3b)|=|(%3d)|(|(%28)|)|(%29)|(/
)|(%2f%2a)|(\ */)|(%2a%2f)|+|(%2b)|<|(%3c)|>|(%3e)|(--)|[|%5b|]|%5b)/”;
}
if (preg_match($re,$PareName)>0)
{
echo (“引數不符合要求,請重新輸入!”);
return 0;
}
else
{
return 1;
}
}

相關文章