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

2021-03-02 php中文網最新課程

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

這是個心腹大患。

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

什麼是注入?

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

舉個例子:

看下面的惡意查詢語句,它會將含有惡意行為的 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 和 Composer。

正式開始

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

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

初始化配置

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

當他要求您來定義依賴關係的時候,寫入 illuminate/database . 最後的輸出應該和上面的圖片中顯示的一樣。現在你就可以在項中通過運行  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 Illuminate\Database\Capsule\Manager 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 Illuminate\Database\Capsule\Manager as Capsule 並起別名 ,這樣子我們就能使用 eloquent 了。

接下來,我們創建一個 Capsule 對象並初始化我們的資料庫連接, 如上  bootEloquent() 。

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

Migrations / 數據遷移

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

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

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

在 migrations.php 文件中創建 migration:

require "start.php";
use Illuminate\Database\Capsule\Manager 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 運行成功了,現在就可以打開資料庫看看是否生成了這兩個表。

Models

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

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

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

namespace Models;
use Illuminate\Database\Eloquent\Model;
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 Illuminate\Database\Eloquent\Model;
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 Models\User;
use Models\Post;
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 助手,將幫助你寫出更乾淨且更安全的代碼。

-END-

▼請點擊下方:「閱讀原文」,在線查看全部文章內容!

相關焦點

  • php mysql SQL注入語句構造
    由於PHP和MYSQL本身得原因,PHP+MYSQL的注射要比asp困難,尤其是注射時語句的構造方面更是個難點,本文主要是借對Okphp BBS v1.3一些文件得簡單分析,來談談php+mysql注射語句構造方式,希望本文對你有點幫助。
  • 3分鐘短文|Laravel複雜SQL超多WHERE子句,本地作用域你沒用過
    引言使用框架就是為了方便把注意力集中在邏輯上,而不用關心與資料庫操作的方方面面。Laravel提供的 eloquent orm 使用面向對象的方式封裝了PDO資料庫操作,使用起來非常方便,對於複雜的SQL操作也遊刃有餘。今天說一說,複雜的超多的WHERE子句,怎麼寫起來較為優雅。
  • Windows下Laravel 7.0連接sql server - php中文網
    laravel 7.0 默認連接 mysql, 同時項目需要連接 sql servel (另一個系統應用)$users = DB::connection (『php_sqlsrv』)->select (…);
  • SQL注入攻擊詳解
    ,但是無論怎麼分常用的查詢數據類型總是以數字與字符來區分的,所以就會產生注入點為何種類型。4.2.1 數字型判斷當輸入的參 x 為整型時,通常 abc.php 中 Sql 語句類型大致如下:select * from <表名> where id = x 這種類型可以使用經典的 and 1=1 和 and 1=2 來判斷:Url 地址中輸入 http://xxx/abc.php?id= x and 1=1 頁面依舊運行正常,繼續進行下一步。
  • 3分鐘短文|Laravel如何改造複雜的多表聯合查詢,這很高效!
    假設要查詢一篇文章,且需要連帶查詢出該文章的分類信息,發布者信息,最直觀的是使用 join 關聯查詢。而且一點也不laravel。所以我們嘗試著使用laravel eloquent orm 方式實現。首先是創建表對應的模型 User.php,<?
  • Myql SLEEP函數和SQL注入
    緣起如果你審查過的慢查詢日誌或者網站access日誌中,你可能都會看到如下的語句:可能就是你網站啟用後大概1小時候內就收到的日誌,或者你Web伺服器(nginx如果你是在Mysql慢查詢日誌中或者access日誌中看到,並且該跳請求返回的狀態碼為200,而不是404,那麼恭喜你可能中標了,被人Sql攻擊了。本文蟲蟲就和大家以sleep()函數為介入來討論。SLEEP()函數SLEEP(n),暫停資料庫n秒。
  • 特殊場景的sql注入思路
    上一篇介紹了sql注入的基礎知識以及手動注入方法,但是在實際的環境中往往不會像靶場中那樣簡單。今天我就來為大家介紹一種特殊場景的sql注入思路。用戶名與密碼分開驗證的情況第一個場景我們以We Chall平臺的Training: MySQL II 一題為例。
  • SQL注入的幾種類型和原理
    操作第二個參數能直接的觸發錯誤為什麼使用concat函數?使其中的語句字符串化,如果有讀者直接將第二個參數使用查詢版本的函數就會發現,報錯的結果不包含「@」符號前的字符,原理大概也猜得到,「@」符號在xpath格式中有其他含義。為什麼使用concat函數中第一個參數構造了一個波浪號?其實這個原因和上面一樣,構造非法的參數,這樣才能在錯誤中看到後面完整的數據。
  • desc巧用及反引號 ` SQL注入——【61dctf】 inject writeup
    = sql_query($sql);關於反引號反引號 ` 在mysql中是為了區分mysql中的保留字符與普通字符而引入的符號例如,如果test表中存在一個」from」欄位,當我們查找內容時,就需要使用反引號,以防使用保留字符而報錯select `from` from test關於desc查看表結構
  • 從WordPress SQLi談PHP格式化字符串問題
    圖片的post_id被帶入查詢,$wpdb->prepare 中使用了 sprintf,會做自動的類型轉化,可以輸入  22 payload  ,會被轉化為meta_key = '_thumbnail_id' AND meta_value = 'payload'之後這條語句會進入查詢,結果為真代碼才能繼續,所以要修改_thumbnail_id對應的meta_value的值為payload,保證有查詢結果。
  • SQL注入、XSS以及CSRF分別是什麼?
    什麼是SQL注入、XSS和CSRF?本篇文章就來帶大家了解一下SQL注入、XSS和CSRF,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。SQL注入SQL注入是屬於注入式攻擊,這種攻擊是因為在項目中沒有將代碼與數據(比如用戶敏感數據)隔離,在讀取數據的時候,錯誤的將數據作為代碼的一部分執行而導致的。典型的例子就是當對SQL語句進行字符串拼接的時候,直接使用未轉義的用戶輸入內容作為變量。
  • Laravel 自定義 SQL 查詢參數綁定
    引言 laravel使用模型進行資料庫操作時,並不是所有的欄位或者關聯關係 都能滿足查詢需求,有時候會有一些MySQL的函數計算等功能放在資料庫 層面執行。
  • 淺談開啟magic_quote_gpc後的sql注入攻擊與防範
    通過啟用php.ini配置文件中的相關選項,就可以將大部分想利用SQL注入漏洞的駭客拒絕於門外  通過啟用php.ini配置文件中的相關選項,就可以將大部分想利用SQL注入漏洞的駭客拒絕於門外。SQL語句:$sql="select * from users where username=$name and password='$pwd'";注意:變量$name沒加引號此時,在地址欄中輸入username=admin%23,則合成後的sql語句為:select * from users where username='admin\' #' and password='
  • PHP代碼安全有必要了解下
    ,插入其他用於修改後端資料庫的語句,並可能執行系統命令,從而對系統造成危害例如刪除 id 為 1 的帖子,sql 如下:$post_id = $_POST['post_id'];$sql = "DELETE FROM posts WHERE user_id = 1 AND id = $post_id";\DB::statement
  • 徹底幹掉噁心的 SQL 注入漏洞, 一網打盡!
    rs = stmt.executeQuery(sql);安全的寫法是使用參數化查詢(參數化查詢),即SQL語句中使用參數綁定(?這裡需要注意的是,使用了PreparedStatement 並不意味著不會產生注入,如果在使用PreparedStatement之前,存在拆分sql語句,那麼仍然會導致注入,如// 拼接 sqlString sql = "SELECT *
  • SQL 注入攻防入門詳解
    這幾天把sql注入的相關知識整理了下,希望大家多多提意見。(對於sql注入的攻防,我只用過簡單拼接字符串的注入及參數化查詢,可以說沒什麼好經驗,為避免後知後覺的犯下大錯,專門查看大量前輩們的心得,這方面的資料頗多,將其精簡出自己覺得重要的,就成了該文)下面的程序方案是採用 ASP.NET + MSSQL,其他技術在設置上會有少許不同。
  • 使用explain和show profile來分析SQL語句實現優化SQL語句
    SQL語句優化是建立在慢查詢分析的基礎上,通過慢查詢定位有問題的SQL語句,關於慢查詢的介紹及其分析工具,可以參考[mysql慢查詢及慢查詢日誌分析工具]一、通過explain查詢1 用法:explain sql2 作用:用於分析sql語句
  • Java web安全黑客攻防之sql注入
    1.什麼是sql注入sql注入通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙伺服器執行惡意的SQL命令通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙伺服器執行惡意的SQL
  • 3分鐘短文:Laravel ORM 模型用法綱要
    引言 前兩期為了說明laravel框架提供的資料庫操作能力,直接使用DB門面操作, 而沒有引入更為強大的eloquent orm功能。從本期開始,我們就分次把 eloquent的一些簡要知識點,為大家提煉演示一下。主要以代碼為主,配以簡要說明。
  • PHP代碼安全
    插入其他用於修改後端資料庫的語句,並可能執行系統命令,從而對系統造成危害例如刪除 id 為 1 的帖子,sql 如下:$post_id = $_POST['post_id'];$sql = "DELETE FROM posts WHERE user_id = 1 AND id = $post_id";\DB::statement($sql