在你的 PHP 項目中單獨使用 Laravel Eloquent 查詢語句來避免 SQL 注入

owasp (open web application security project) 是一個記錄當前 web 應用所受威脅情況的項目。我一直都在關注他們的網站,從 2010,2013 和 2017 年的報告中我發現了一些相似之處,sql 或其他類型的注入威脅都是高居榜首。

這是個心腹大患。

它會導致你破產,因此這個事情關乎存亡,你單位應該著力處理此類問題避免它的出現。

什么是注入?

所謂注入,就是數據沒有經過過濾,將無法信任的內容直接寫入了系統解釋器,這種行為會導致對站點產生 SQL 注入,更糟糕的是,攻擊者可能會獲得對系統的全部權限。

立即學習PHP免費學習筆記(深入)”;

舉個例子:

看下面的惡意查詢語句,它會將含有惡意行為的 SQL 語句放在 $name 變量里,然后允許用戶通過 POST 的方式傳遞給 PHP 腳本,從而達到最終使用傳入的惡意代碼進行攻擊的目的。

//?將惡意代碼,DROP?TABLE?寫入?$name?變量 $name?=?"Mark';DROP?TABLE?users;?--?";?$query?=?"SELECT?*?FROM?users?WHERE?name='$name'";

經過 PHP 腳本解析,這會最終生成這樣的 SQL 語句:

SELECT?*?FROM?users?WHERE?name='Mark';DROP?TABLE?users;?--?'

正如你猜的那樣,上述語句會將整個 users 數據表從數據庫里刪除掉。

正如尤達說的:

這太危險了,是的,太危險了。

如何防止對 PHP 應用的惡意注入?

首先,其實并沒有真的往數據庫里注入什么東西,這種錯誤只是由于沒有正確地將查詢語句格式化。解決的方法很簡單,只要正確地格式化 SQL 語句,或者是直接把查詢語句和數據分開處理。

怎么做呢?用參數化查詢對數據格式化,并使查詢語句與數據分離。

使用參數化查詢,可以確保程序遠離注入風險。

例子如下:

$statement?=?$db->prepare('SELECT?*?FROM?table?WHERE?id?=???and?name?=???');?$statement->execute([1,?"Mark"]);

除此之外,還有一種安全的做法,就是在項目中使用 ORM ( 對象關系映射)或者是查詢構造器。

我要推薦的是著名的 PHP 框架 laravel 也在用的 Eloquent。接下來,我會教你如何安裝和使用,它可以幫助我們做好數據格式化的工作,從而有效避免注入危害。

安裝 Eloquent

準備工作

請確保你已經安裝了 PHP 和 owasp 。

正式開始

最好在項目開始之初就安裝 ORM。

假設我們想建一個博客應用,包含一個 posts 表和一個 users 表。

初始化配置

首先要做的是為程序創建 composer.json 文件。 你可以在終端上運行 composer init? 并按照終端上的提示進行操作。

在你的 PHP 項目中單獨使用 Laravel Eloquent 查詢語句來避免 SQL 注入

當他要求您來定義依賴關系的時候,寫入 illuminate/database . 最后的輸出應該和上面的圖片中顯示的一樣?,F在你就可以在項中通過運行? composer install? 來安裝相應的依賴了。

或者,如果你已經有了 composer.json 這個文件,你可以直接在終端輸入? composer require illuminate/database 來安裝相應的依賴。

現在我們需要在應用程序的根目錄中創建? start.php 文件并把下面的代碼粘貼到文件中。我會在下面解釋他們的作用。

require?"vendor/autoload.php"; //If?you?want?the?errors?to?be?shown??*是否顯示錯誤 error_reporting(E_ALL); ini_set('display_errors',?'1'); use?IlluminateDatabaseCapsuleManager?as?Capsule; ?$capsule?=?new?Capsule; ?$capsule->addConnection([ ????"driver"?=>?"mysql", ????"host"?=>"127.0.0.1", ????"database"?=>?"test", ????"username"?=>?"root", ????"password"?=>?"root" ?]); //Make?this?Capsule?instance?available?globally.?*要讓?capsule?能在全局使用 ?$capsule->setAsGlobal(); //?Setup?the?Eloquent?ORM. ?$capsule->bootEloquent();

在第一行我們需要引入 vendor/autoload.php 文件。這樣我們才能加載到 vendor 目錄下的所有包。

然后我們引入 use IlluminateDatabaseCapsuleManager as Capsule 并起別名 ,這樣子我們就能使用 eloquent 了。

接下來,我們創建一個 Capsule 對象并初始化我們的數據庫連接, 如上? bootEloquent() 。

現在,很明顯我們要做的第一件事就是創建名為 test 的數據庫,請確保你在自己本地輸入的是正確的用戶名和密碼.

Migrations / 數據遷移

使用 Eloquent 的一個最大的好處就是可以使用 migrations。

如果你不了解什么是 migrations,可以看下面的解釋:

migration 是一種可以通過 PHP 代碼創建數據表的方式。

在 migrations.php 文件中創建 migration:

require?"start.php"; use?IlluminateDatabaseCapsuleManager?as?Capsule; Capsule::schema()->create('users',?function?($table)?{ ???$table->increments('id'); ???$table->string('name'); ???$table->string('email')->unique(); ???$table->string('password'); ???$table->timestamps(); }); Capsule::schema()->create('posts',?function?($table)?{ ???$table->increments('id'); ???$table->string('title'); ???$table->text('body'); ???$table->integer('created_by')->unsigned(); ???$table->timestamps(); });

上面這段代碼,通過 Capsule 類創建了兩個數據表,一個是 users 表,另一個是 posts 表,并且分別為他們定義了字段名。

運行這個文件,如果你看到白屏,就說明 migrations 運行成功了,現在就可以打開數據庫看看是否生成了這兩個表。

在你的 PHP 項目中單獨使用 Laravel Eloquent 查詢語句來避免 SQL 注入

Models

現在,唯一要做的就是創建對應數據表的 Model 類。

用了 Eloquent,你就可以在 Model 類里操作相應的數據表,執行查詢語句了。

創建一個 Models 文件夾,然后在其中分別創建 User.php 和 Post.php 文件:

namespace?Models; use?IlluminateDatabaseEloquentModel; class?User?extends?Model { ???/** ????*?對應的數據表 ????* ????*?@var?string ????*/ ????protected?$table?=?"users"; ???/** ????*?允許插入的字段 ????* ????*?@var?array ????*/ ????protected?$fillable?=?[ ????????'name',?'email',?'password' ????]; ???/** ????*?需要被隱藏的字段 ????* ????*?@var?array ????*/ ????protected?$hidden?=?[ ????????'password',?'remember_token', ????]; ???/* ????*?給?User?類添加方法 ????* ????*/ ????public?function?posts() ????{ ????????return?$this->hasMany(Post::class,?'created_by'); ????} } And namespace?Models; use?IlluminateDatabaseEloquentModel; class?Post?extends?Model { ???/** ????*?對應的數據表 ????* ????*?@var?string ????*/ ????protected?$table?=?"posts"; ??/** ???*?允許插入的字段 ???* ???*?@var?array ???*/ ???protected?$fillable?=?[ ???????'title',?'body',?'created_by' ???]; ?} 在?composer.json?文件中加入如下代碼,以確保上面創建的類文件能夠被自動加載。 "autoload":?{ ????"classmap":?[ ????????"Models"?//?Folder?where?all?your?models?are ?????] }

然后執行 composer dump-autoload。

通過 Eloquent 操作數據庫

基本大功告成了。 測一下吧,在根目錄創建 index.php 文件,添加如下代碼:

require?"start.php"; use?ModelsUser; use?ModelsPost; User::create( ?[ ??'name'?=>?'Mark?Mike', ??'email'?=>?'temp-email-1@mark.com', ??'password'?=>?'1234' ?] ); Post::create( ?[ ??'title'?=>?'New?Blog?Post', ??'body'?=>?'New?Blog?Content', ??'created_by'?=>?1 ?] ); print_r(User::all()); print_r(Post::all()); print_r(User::find(1)->posts);

如你所見,用 Eloquent 操作數據庫就是這么簡單。除此之外,Eloquent 還提供了很多方法供你使用,而且很安全。

結語:

Eloquent 就像是給你的 SQL 查詢加了一道安全層,它可以過濾掉我們在執行 SQL 查詢時所犯的錯誤。如果你想用它,但是又不想安裝 Laravel 框架,那么我想你已經從這篇文章中學到了該如何去做。這個優雅的 SQL 助手,將幫助你寫出更干凈且更安全的代碼。

更多PHP相關知識,請訪問owasp

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享