Laravel 損壞對(duì)象級(jí)授權(quán)

讓我們看看 Laravel 中的 BOLA。我們將使用一個(gè)實(shí)現(xiàn)上述 API 的應(yīng)用程序。 

一個(gè)簡(jiǎn)單的 Laravel Rest API

Laravel 使構(gòu)建 CRUD API 變得非常簡(jiǎn)單。 

由于我們使用 MySQL 作為存儲(chǔ)漫畫的后端,因此模型代碼非常簡(jiǎn)單。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Comic extends Model
{
use HasFactory;
}

Laravel 也使基本身份驗(yàn)證變得簡(jiǎn)單。通過將對(duì)控制器的調(diào)用與對(duì)Sanctum的調(diào)用包裝在一起,可以輕松確保沒有人在沒有有效會(huì)話的情況下訪問 API。

因此,我們的漫畫 API 路由條目使用 Sanctum 中間件。同時(shí),登錄注冊(cè) 路由,以便您可以使用它們來(lái)創(chuàng)建會(huì)話。

<?php

use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->get('/comics', 'App\Http\Controllers\ComicController@index');
Route::middleware('auth:sanctum')->get('/comics/{comic}', 'App\Http\Controllers\ComicController@show');
Route::middleware('auth:sanctum')->post('comics', 'App\Http\Controllers\ComicController@store');
Route::middleware('auth:sanctum')->put('comics/{comic}', 'App\Http\Controllers\ComicController@update');
Route::middleware('auth:sanctum')->delete('comics/{comic}', 'App\Http\Controllers\ComicController@delete');

Route::post('login', [App\Http\Controllers\AuthController::class, 'login']);
Route::post('register', [App\Http\Controllers\AuthController::class, 'register']);

漫畫控制器使用該模型來(lái)檢索、更新、創(chuàng)建和刪除 MySQL 中的項(xiàng)目。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Comic;
use Illuminate\Support\Facades\Log;

class ComicController extends Controller
{

public function index()
{
return Comic::all();
}

public function show(Request $request, $id)
{
return Comic::find($id);
}

public function store(Request $request)
{
$comic = Comic::create($request->all());
return response()->json($comic, 201);
}

public function update(Request $request, $id)
{
$comic = Comic::findOrFail($id);
$comic->update($request->all());
return response()->json($comic, 200);
}

public function delete(Request $request, $id)
{
$Comic = Comic::findOrFail($id);
$Comic->delete();

return response()->json(null, 204);
}
}

最后,我們需要一個(gè)控制器來(lái)創(chuàng)建新用戶并讓他們登錄。

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;

class AuthController extends Controller
{

public function login(Request $request)
{
if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){
$auth = Auth::user();
$success['token'] = $auth->createToken('LaravelSanctumAuth')->plainTextToken;
$success['name'] = $auth->name;

return $this->handleResponse($success, 'User logged-in!');
}
else{
return $this->handleError('Unauthorised.', ['error'=>'Unauthorised']);
}
}

public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'confirm_password' => 'required|same:password',
]);

$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$success['token'] = $user->createToken('LaravelSanctumAuth')->plainTextToken;
$success['name'] = $user->name;
return $this->handleResponse($success, 'User successfully registered!');
}
}

測(cè)試服務(wù)

那么,讓我們嘗試一下這項(xiàng)新服務(wù)。 

一位新用戶想通過網(wǎng)絡(luò)購(gòu)買一些漫畫。他們嘗試通過 API 列出漫畫。 

GUI 不應(yīng)該讓您到達(dá)這一點(diǎn),但由于 API 阻止了未經(jīng)授權(quán)的請(qǐng)求,因此不會(huì)造成任何損害。

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

這個(gè)簡(jiǎn)單的服務(wù)返回了內(nèi)部服務(wù)器錯(cuò)誤,因?yàn)槲覀冞€沒有將所有正確的狀態(tài)連接在一起。在生產(chǎn)中,你會(huì)得到 401 而不是 500。 

因此,我們的新客戶走上了正確的道路并創(chuàng)建了新的登錄。

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

現(xiàn)在他們有了登錄名和令牌,所以他們就可以看漫畫了!

我們?cè)O(shè)置的簡(jiǎn)單授權(quán)期望令牌作為Bearer Token返回。

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

成功!

在購(gòu)物應(yīng)用中列出所有商品不是問題,尤其是當(dāng) API 知道如何實(shí)現(xiàn)分頁(yè)以避免 UI 崩潰時(shí)。但在管理用戶數(shù)據(jù)的應(yīng)用中,這會(huì)是個(gè)問題。 

不管怎么說(shuō),那本綠巨人漫畫看起來(lái)很貴,而且標(biāo)題也不對(duì)!讓我們來(lái)解決這個(gè)問題。 

以下是記錄的更新內(nèi)容:

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

這是PUT 請(qǐng)求。我們將嘗試使用客戶的持有者令牌來(lái)更新漫畫。

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

請(qǐng)求成功。服務(wù)器返回 200 并將新值回顯給我們。 

我們?cè)贆z查一下。

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

哎呀。我們使用客戶的憑證更改了庫(kù)存。這破壞了對(duì)象級(jí)授權(quán)。 

修復(fù) Laravel BOLA

那么我們?cè)撊绾谓鉀Q這個(gè)問題呢? 

我們需要驗(yàn)證用戶是否有權(quán)提出請(qǐng)求,而不僅僅是他們是否具有有效的會(huì)話。 

Laravel 使這變得簡(jiǎn)單。當(dāng) Sanctum 驗(yàn)證持有者令牌時(shí),它會(huì)將用戶信息添加到 與請(qǐng)求關(guān)聯(lián)的 auth對(duì)象中。因此,我們可以在處理請(qǐng)求之前檢查用戶名。它存儲(chǔ)在auth(‘sanctum’)->user() 中。 

讓我們?cè)试S銷售人員更新漫畫,這樣他們就可以在銷售漫畫時(shí)調(diào)整數(shù)量,并且我們?cè)试S老板更新漫畫,因?yàn)樗麄兪抢习濉H绻脩舨皇沁@些人之一,我們將返回 401。 

public function update(Request $request, $id)
{
if (auth('sanctum')->user()->name == "theboss" || auth('sanctum')->user()->name == 'sales') {
$comic = Comic::findOrFail($id);
$comic->update($request->all());
return response()->json($comic, 200);
} else {
return response()->json(null, 401);
}
}

讓我們用新用戶的承載令牌來(lái)測(cè)試這一點(diǎn)。

Laravel 損壞的對(duì)象級(jí)授權(quán)指南:示例和預(yù)防措施

我們得到了 401(未授權(quán))狀態(tài)。成功了! 

對(duì)用戶名等值進(jìn)行硬編碼從來(lái)都不是一個(gè)好主意。理想情況下,我們會(huì)將其添加到數(shù)據(jù)庫(kù)架構(gòu)中,但現(xiàn)在我們可以將其添加到配置文件中。 

因此,讓我們?cè)赾onfig/app.php中的應(yīng)用程序配置中添加兩個(gè)數(shù)組 : 

'administrators' => ['theboss'],
'sales' => ['sales'],

現(xiàn)在我們可以擁有多個(gè)管理員或銷售帳戶。 

接下來(lái),更新檢查以使用配置值: 

public function update(Request $request, $id)
{
if ( in_array(auth('sanctum')->user()->name, Config::get('app.administrators')) ||
in_array(auth('sanctum')->user()->name, Config::get('app.sales'))) {
$comic = Comic::findOrFail($id);
$comic->update($request->all());
return response()->json($comic, 200);
} else {
return response()->json(null, 401);
}
}

在更新項(xiàng)目之前,該函數(shù)會(huì)根據(jù)兩個(gè)數(shù)組檢查用戶名。只有當(dāng)請(qǐng)求者是管理員銷售人員的成員時(shí),它才會(huì)允許請(qǐng)求通過。 

我們現(xiàn)在也可以限制只有管理員才能刪除項(xiàng)目:

public function delete(Request $request, $id)
{
if (in_array(auth('sanctum')->user()->name, Config::get('app.administrators'))) {
$Comic = Comic::findOrFail($id);
$Comic->delete();
return response()->json(null, 204);
} else {
return response()->json(null, 401);
}
}

因此,此應(yīng)用程序現(xiàn)在具有簡(jiǎn)單的對(duì)象級(jí)授權(quán)。更好的解決方案可能是在 MySQL 中設(shè)置訪問級(jí)別,甚至可能將其作為 Sanctum 信息的一部分返回。但是,主要的安全漏洞已修復(fù),并且有權(quán)限的用戶沒有被硬編碼。 

總結(jié)

我們首先研究了對(duì)象級(jí)授權(quán)問題,以及用戶如何利用它來(lái)竊取或更改他們本不應(yīng)該能夠竊取或更改的信息。然后,我們轉(zhuǎn)向了 Laravel 在一個(gè)簡(jiǎn)單的 REST API 中破壞的對(duì)象授權(quán)。我們了解了漏洞的面貌并應(yīng)用了一個(gè)簡(jiǎn)單的修復(fù)程序。 

文章來(lái)源:Laravel Broken Object Level Authorization Guide

上一篇:

探討路徑遍歷攻擊的概念與預(yù)防方法

下一篇:

應(yīng)用程序安全審計(jì):深入指導(dǎo)
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)