預編譯能否 100%防 sql 注入?

🌟 什么是 SQL 注入?

SQL 注入(SQL Injection)是指攻擊者利用特殊輸入,讓數據庫執行它本來不應該執行的代碼,從而獲取或篡改數據。

就像在考試的時候偷偷改題目,讓老師改成你想要的內容! 😱


🌟 先來看一個正常的 SQL 查詢

假設你的網站有一個登錄功能,代碼是這樣的:

🔹 登錄代碼

$username = $_GET['username']; ?
$password = $_GET['password']; ?

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

? 這個代碼的意思是:
👉 從 users 表里查找 用戶名 = $username密碼 = $password 的用戶。

如果數據庫里有這條數據,用戶就可以登錄!

🌟 用戶輸入正常數據(正確方式)

假設用戶輸入:

username = admin
password = 123456

最終SQL語句:

SELECT * FROM users WHERE username = 'admin' AND password = '123456';

? 如果 admin 這個用戶的密碼是 123456,那么數據庫會返回這個用戶的信息,表示登錄成功!

🚨 但如果攻擊者輸入特殊字符呢?

攻擊者可能會這樣輸入:

username = admin' --
password = (隨便填)

那么最終SQL語句變成:

SELECT * FROM users WHERE username = 'admin' -- ' AND password = 'xxxxx';

這里發生了什么?

  • -- 是SQL中的注釋符號,它會讓后面代碼(AND password='xxxxx')變成無效的注釋

  • 結果就變成:

    SELECT * FROM users WHERE username = 'admin'

    相當于直接查詢 admin 用戶,而不檢查密碼! 😱

  • 這樣攻擊者就可以繞過密碼驗證,直接登錄 admin 賬號!?

  • 🌟 現實世界的比喻

  • 💡 想象你在銀行辦理取款業務,柜員要核對你的身份:

  • 正常情況:
    柜員問你:請告訴我你的用戶名密碼,如果正確,我就給你取錢。

    • 你說:“我是 admin,密碼是 123456

    • 銀行查了一下,發現你的用戶名和密碼匹配,于是讓你取錢。?

  • 被攻擊的情況(SQL注入):
    攻擊者說“我是 admin,但是密碼這部分不重要,你不用檢查。”

    • 銀行糊涂了,以為你就是 admin,直接給你取錢!

    • 🌟 關鍵點總結

    • 1?? SQL 注入的本質:利用特殊字符破壞 SQL 語句結構,讓數據庫執行本不應該執行的代碼。
      2?? 常見注入方式

    • 單引號 '(破壞 SQL 結構)

    • --(注釋掉后續代碼)

    • OR 1=1(讓查詢條件永遠成立)?

    • 3?? 為什么 SQL 注入危險?

    • 可以繞過密碼驗證,直接登錄

    • 可以獲取數據庫里的所有數據(用戶信息、密碼、銀行卡號)

    • 甚至可以刪除數據,破壞整個系統! 😱

    • 🌟 2. 什么是預編譯(Prepared Statement)?

      🔹 預編譯的作用

      預編譯(Prepared Statement)的核心思想是: 👉 把 SQL 語句和用戶輸入的參數分開處理,防止用戶輸入的數據被當成 SQL 代碼執行。

      就像去餐館點菜時,菜譜是固定的,顧客只能填菜名,不能改動菜單的內容,這樣就不會有欺騙行為。


      🔹 普通的 SQL 語句(容易被 SQL 注入攻擊)

      🚨 下面是一個 危險的 SQL 代碼
    • $name = $_GET['name']; ?
      $query = "SELECT * FROM users WHERE name = '$name'";
      $result = $pdo->query($query);

      👆 這里的問題是:

    • $name 直接拼接到 SQL 語句中,如果用戶輸入了惡意代碼,就會被數據庫當成 SQL 代碼執行,導致 SQL 注入!

    • ? 使用預編譯(防止 SQL 注入)

      $stmt = $pdo->prepare('SELECT * FROM users WHERE name = ?');
      $stmt->execute([$name]);

      execute([$name]);

      個代碼是安全的! 為什么?

      ??? prepare('SELECT * FROM users WHERE name = ?') 這一步先定義好 SQL 語句,但不插入具體的值。

      ??? execute([$name]) 這一步才把 $name 作為普通字符串插入,不會被當成 SQL 代碼。

      💡 無論用戶輸入什么,它都會被當成普通文本,不會影響 SQL 語句本身。

    • 🌟 3. 為什么預編譯不能 100% 防 SQL 注入?

      雖然預編譯能防止大部分 SQL 注入,但在某些特殊情況下,仍然可能被繞過。
      下面是三個真實案例,讓你徹底理解!😱

    • 🚨 案例一:寬字節注入

      🌍 發生場景
      某些數據庫(比如 MySQL)在處理GBK 編碼時,可能會錯誤地解析特殊字符,從而導致 SQL 注入。

      💻 代碼示例

    • $pdo->query('SET NAMES gbk');? // 設定 GBK 編碼
      $var = "\xbf\x27 OR 1=1 /*";??? // 特殊構造的字符串
      $query = 'SELECT * FROM test WHERE name = ? LIMIT 1';
      $stmt = $pdo->prepare($query);
      $stmt->execute([$var]);

      ? 為什么會有問題?

      1?? \xbf\x27 在 GBK 編碼下,可能會被誤解析為一個單獨的字符
      2?? 剩下的部分 "OR 1=1 /*" 會被數據庫當成 SQL 代碼執行!
      3?? 這樣就變成:

    • SELECT * FROM test WHERE name = '某些字符' OR 1=1 /*

      OR 1=1 永遠為真,所以查詢會返回所有數據,導致信息泄露! 😱

    • 🚨 案例二:表名注入

      🌍 發生場景
      預編譯只能防止SQL參數注入,但如果動態拼接SQL,還是會有風險!😨

      💻 代碼示例

    • $dbh = new PDO("mysql:host=localhost;dbname=test", "root", "password");
      $name = $_GET['name'];? // 例如輸入:"users; DROP TABLE users;"
      $stmt = $dbh->prepare('SELECT * FROM ' . $name . ' WHERE username = :username');
      $stmt->execute([':username' => $_REQUEST['username']]);

      ? 為什么會有問題?

      1?? $name 直接拼接進 SQL 語句,而不是作為參數傳入 prepare()
      2?? 攻擊者可以輸入惡意表名,比如:

    • users; DROP TABLE users;

      3?? 這樣 SQL 語句變成:

    • SELECT * FROM users; DROP TABLE users; WHERE username = 'admin'

      🔴 結果:users 表被刪除!數據丟失! 😱

    • 案例三:ORDER BY 注入

      🌍 發生場景
      有些 SQL 語句的排序字段不能使用預編譯參數,這會導致 SQL 注入。

      💻 代碼示例

    • $stmt = $dbh->prepare('SELECT * FROM foo ORDER BY :userSuppliedData');
      $stmt->execute([':userSuppliedData' => $_GET['sort']]);

      為什么會有問題?

      1?? ORDER BY 后面的字段名 不能使用預編譯參數
      2?? 攻擊者可以輸入:

    • id DESC; DROP TABLE foo;

      3?? 這樣 SQL 語句變成:

    • SELECT * FROM foo ORDER BY id DESC; DROP TABLE foo;

      4?? 🔴 結果:foo 表被刪除!數據庫數據被破壞! 😱

      🌟 4. 如何完全防止 SQL 注入?

      雖然預編譯是一個很好的安全措施,但它并不能 100% 防止 SQL 注入。
      所以,我們還需要額外的安全措施!👇


      ? 方法 1:嚴格限制輸入格式

      💡 不要讓用戶輸入影響 SQL 結構的內容!
      🔹 例如,限制表名、列名、排序字段只能從“白名單”中選擇!

    • $allowedSortFields = ['id', 'name', 'date']; ?
      if (!in_array($_GET['sort'], $allowedSortFields)) { ?
      ??? die("Invalid input");? // 直接終止,防止 SQL 注入 ?
      }

      ? 方法 2:使用 ORM 框架

      🔹 ORM(Object-Relational Mapping) 框架(比如 Laravel 的 Eloquent、Doctrine)會自動處理 SQL 語句,默認帶有安全檢查

      示例:

    • User::where('name', $name)->first();

      ORM 會自動處理 SQL 注入問題,不需要手動寫 SQL 語句。

      ? 方法 3:最小權限原則

      🔹 不要使用數據庫管理員賬戶(如 root)運行 SQL 語句! 🔹 為應用創建權限受限的數據庫賬戶,這樣即使有 SQL 注入,也不會破壞整個數據庫。

      CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'securepassword';
      GRANT SELECT, INSERT, UPDATE, DELETE ON testdb.* TO 'webapp'@'localhost';

      這樣,即使黑客注入了 DROP TABLE users;,也無法執行,因為 webapp 賬號沒有刪除表的權限!😃


      🌟 總結

      ? 預編譯是 SQL 防注入的核心方法,但并不 100% 安全。
      ? SQL 注入繞過的三種方式:

    • 寬字節注入(特殊字符編碼問題)

    • 表名注入(拼接動態 SQL )

    • ORDER BY 注入(排序字段不能預編譯)
      ? 想要 100% 防 SQL 注入,還需要額外措施!
      ? 最佳安全做法:

    • 嚴格限制用戶輸入

    • 使用 ORM 框架

    • 遵循最小權限原則












    • ?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75707.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75707.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75707.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第十五章 | Layer2、Rollup 與 ZK 技術實戰解析

📚 第十五章 | Layer2、Rollup 與 ZK 技術實戰解析 ——構建下一代高性能區塊鏈應用,從 Solidity 到 zkSync! ? 本章導讀 Layer2 和零知識證明(ZK)正成為區塊鏈發展的核心方向。 隨著主網 Gas 居高不下、TPS 無法滿…

2025-03-26 學習記錄--C/C++-PTA 6-3 求鏈式表的表長

合抱之木,生于毫末;九層之臺,起于累土;千里之行,始于足下。💪🏻 一、題目描述 ?? 6-3 求鏈式表的表長 本題要求實現一個函數,求鏈式表的表長。 函數接口定義: &…

【Linux】Linux_Ubuntu與Windows之間的文件傳輸

一、Linux終端命令的復制粘貼 1.打開linux 終端,輸入以下命令:(注意,需要聯網) 2.命令行下載: sudo apt-get autoremove open-vm-tools 3.命令行安裝: sudo apt-get install open-vm-tools-…

Python Sanic面試題及參考答案

目錄 Sanic 的事件循環機制與 uvloop 的關系 Sanic 的 Request/Response 對象生命周期如何管理?如何訪問請求上下文? 對比 Sanic 與 Flask/Django 的異步處理模型差異 Sanic 的 Blueprint 機制如何實現模塊化路由?如何處理跨藍圖中間件? 如何在 Sanic 中實現 WebSocket…

算法每日一練 (18)

💢歡迎來到張翊塵的技術站 💥技術如江河,匯聚眾志成。代碼似星辰,照亮行征程。開源精神長,傳承永不忘。攜手共前行,未來更輝煌💥 文章目錄 算法每日一練 (18)刪除并獲得點數題目描述解題思路解題…

VsCode啟用右括號自動跳過(自動重寫) - 自錄制gif演示

VsCode啟用右括號自動跳過(自動重寫) - 自錄制gif演示 前言 不知道大家在編程時候的按鍵習慣是怎樣的。輸入完左括號后編輯器一般會自動補全右括號&#xff0c;輸入完左括號的內容后&#xff0c;是按→跳過右括號還是按)跳過右括號呢&#xff1f; for (int i 0; i < a.s…

用Python和Stable Diffusion生成AI動畫:從圖像到視頻的全流程指南

引言 本文將演示如何通過Python代碼實現基于文本提示的AI動畫生成。我們將使用Stable Diffusion生成連貫圖像幀,結合OpenCV合成視頻,最終實現一個可自定義的動畫生成 pipeline。 一、環境準備 1. 依賴安裝 # 安裝核心庫 pip install diffusers transformers torch numpy …

【Git 常用指令速查表】

Git 常用指令速查表 Git 常用指令速查表目錄1. 初始化倉庫2. 提交代碼流程3. 分支管理4. 遠程倉庫操作5. 撤銷操作6. 查看狀態與日志7. 其他實用指令完整操作示例常用場景速查表 Git 常用指令速查表 目錄 初始化倉庫提交代碼流程分支管理遠程倉庫操作撤銷操作查看狀態與日志其…

分布式爬蟲框架Scrapy-Redis實戰指南

引言 在當今數字化的時代背景下&#xff0c;互聯網技術的蓬勃興起極大地改變了旅游酒店業的運營模式與市場格局。作為旅游產業鏈中的關鍵一環&#xff0c;酒店業的興衰與互聯網技術的應用程度緊密相連。分布式爬蟲技術&#xff0c;尤其是基于 Scrapy 框架的 Scrapy-Redis 擴展…

爬蟲:scrapy面試題大全(60個scrapy經典面試題和詳解)

更多內容請見: 爬蟲和逆向教程-專欄介紹和目錄 文章目錄 1. 什么是Scrapy?2. Scrapy 框架的組件及其作用?3. Scrapy的工作流程是什么?(運行機制)4. 如何創建一個Scrapy項目?5. 如何定義一個Spider?6. 如何在Scrapy中提取數據?7. Scrapy中的Item是什么?8. Scrapy中的P…

Leetcode12-整數轉羅馬數字

題目鏈接&#xff1a;12. 整數轉羅馬數字 - 力扣&#xff08;LeetCode&#xff09; 看題目限制輸入1 < num < 3999&#xff0c;就直接用暴力法寫了&#xff0c;還比較簡單 代碼&#xff1a; char* intToRoman(int num) {char *res (char*)malloc(100);int index 0;i…

WebMvcConfigurer 的 addResourceLocations

在 Spring Boot 的 addResourceLocations 方法中&#xff0c;file: 是一個 URL 前綴&#xff0c;用于指示資源的位置是本地文件系統路徑。以下是詳細解釋&#xff1a; 一、file: 的作用 file: 是 Java 中用于表示本地文件系統的 URL 前綴。它告訴 Spring Boot&#xff0c;資源…

Spring Boot響應壓縮配置與優化

一、核心工作機制 1.1 自動協商觸發條件 Spring Boot的響應壓縮功能基于智能協商機制&#xff0c;需同時滿足以下條件方可觸發&#xff1a; 客戶端支持&#xff1a;請求頭包含Accept-Encoding: gzip/deflate數據量閾值&#xff1a;響應體大小超過預設值&#xff08;默認2KB&…

JavaScript 改變 HTML 樣式

JavaScript 改變 HTML 樣式 JavaScript 改變 HTML 樣式的核心是通過操作 DOM 元素的 CSS 屬性或 類名 實現動態視覺效果。以下是具體方法與場景解析: 一、直接修改元素的 style 屬性 通過 DOM 元素的 style 屬性直接設置內聯樣式,優先級最高: // 修改單個樣式 document.…

【vue】vue + vant實現上傳圖片添加水印

目錄 方法1&#xff1a;使用HTML2canvas 說明&#xff1a; 優點 缺點 依賴安裝 方法2&#xff1a;使用canvas結合vant中組件 增加水印方法 在vue組件中使用 要點 方法1&#xff1a;使用HTML2canvas 使用html2canvas來處理水印的生成&#xff0c;需要就給水印元素轉換為…

【深度破解】爬蟲反反爬核心技術實踐:驗證碼識別與指紋偽裝

一、反爬技術體系全景圖 現代Web應用的常見反爬手段&#xff1a; mermaid&#xff1a; graph TDA[反爬體系] --> B[行為特征檢測]A --> C[驗證碼體系]A --> D[指紋追蹤]B --> B1[請求頻率]B --> B2[鼠標軌跡]B --> B3[頁面停留時間]C --> C1[圖形驗證碼…

deepseek(2)——deepseek 關鍵技術

1 Multi-Head Latent Attention (MLA) MLA的核心在于通過低秩聯合壓縮來減少注意力鍵&#xff08;keys&#xff09;和值&#xff08;values&#xff09;在推理過程中的緩存&#xff0c;從而提高推理效率&#xff1a; c t K V W D K V h t c_t^{KV} W^{DKV}h_t ctKV?WDKVht?…

OpenGL繪制文本

一&#xff1a;QPainter繪制 在 OpenGL 渲染的窗口中&#xff08;如 QOpenGLWidget&#xff09;&#xff0c;通過 QPainter 直接繪制文本。Qt 會自動將 2D 內容&#xff08;文本、圖形&#xff09;與 OpenGL 內容合成。在paintGL()里面繪制&#xff0c;如果有其他紋理&#xf…

從零構建大語言模型全棧開發指南:第二部分:模型架構設計與實現-2.1.3前饋網絡(FFN)與激活函數(GELU)優化

?? 點擊關注不迷路 ?? 點擊關注不迷路 ?? 點擊關注不迷路 文章大綱 2.1.3 前饋網絡(FFN)與激活函數(GELU)優化1. 前饋網絡(FFN)的架構設計與數學原理1.1 FFN在Transformer中的核心作用2. GELU激活函數的數學特性與優化2.1 GELU的數學形式與近似計算3. 逐行代碼實現…

React 中的錯誤邊界(Error Boundaries),如何使用它們捕獲組件錯誤

大白話React 中的錯誤邊界&#xff08;Error Boundaries&#xff09;&#xff0c;如何使用它們捕獲組件錯誤 在 React 里&#xff0c;錯誤邊界就像是一個“小衛士”&#xff0c;專門負責在組件出現錯誤時挺身而出&#xff0c;避免整個應用因為一個小錯誤就崩潰掉。接下來我會詳…