[Laravel 8.x] 資安弱點掃描與調整

公司結案需提出第三方資安檢測報告,這邊針對我有遇到的部分紀錄調整方式。

一、SQL Injection

說明:

對伺服器發送不正常參數,可以得到正常資料回應。

處理:

針對有問題的程式加上 Validation,確保參數正確性。


二、Open Redirection

說明:

網站有 redirect 功能,卻沒有限制可以 redirect 的 url,可能會被用作網路釣魚,讓使用者迷惑他們正在造訪哪個網站。

處理:

加上針對 url 的判斷,確認是可允許的連線。

// 網址:https://your-web-site.com.tw/redirect?url=https://laravel.com/

// 錯誤範例
public function redirect(Request $request)
{
    $url = $request->query('url');

    if ($url) {
        return redirect($url);
    } else {
        return redirect()->back();
    }
}

// 正確範例
public function redirect(Request $request)
{
    $url = $request->query('url');

    if ($url && '確認網址是可允許的連線') {
        return redirect($url);
    } else {
        return redirect()->back();
    }
}

三、Clickjacking: X-Frame-Options header

說明:

服務器沒有返回值為 DENY 或 SAMEORIGIN 的 X-Frame-Options 標頭。

處理:

Laravel 預設有一個 FrameGuard Middleware 可以達到這個效果,我們只需要把他加進 app/Http/Kernel.php 的 $middleware 陣列中即可。

protected $middleware = [
    ...

    \Illuminate\Http\Middleware\FrameGuard::class,
    
    ...
];

四、Cookies: SameSite

說明:

Cookies 未確實設定「SameSite」屬性。

處理:

Laravel 設定在 config/session.php。

/*
|--------------------------------------------------------------------------
| Same-Site Cookies
|--------------------------------------------------------------------------
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| will set this value to "lax" since this is a secure default value.
|
| Supported: "lax", "strict", "none", null
|
*/

'same_site' => 'lax',

五、Cookies: HttpOnly

說明:

Cookies 未確實設定「HttpOnly」屬性。

處理:

Laravel 設定在 config/session.php。

/*
|--------------------------------------------------------------------------
| HTTP Access Only
|--------------------------------------------------------------------------
|
| Setting this value to true will prevent JavaScript from accessing the
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. You are free to modify this option if needed.
|
*/

'http_only' => true,
絕大部分的 cookie 都會被正確設定,除了 XSRF-TOKEN,網路上是說這個 cookie 不用設定 HttpOnly 也沒關係,但資安公司就是會掃出來。
如果希望這個 cookie 也有 HttpOnly 可以在 App\Http\Middleware\VerifyCsrfToken 新增以下程式碼,這段程式碼是從父類別複製過來改寫,差異在第 28 行的 http_only 參數,改成讀 config 設定。
<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
use Symfony\Component\HttpFoundation\Cookie;

class VerifyCsrfToken extends Middleware
{
    /**
     * Add the CSRF token to the response cookies.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Symfony\Component\HttpFoundation\Response  $response
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function addCookieToResponse($request, $response)
    {
        $config = config('session');

        if ($response instanceof Responsable) {
            $response = $response->toResponse($request);
        }

        $response->headers->setCookie(
            new Cookie(
                'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
                $config['path'], $config['domain'], $config['secure'], $config['http_only'], false, $config['same_site'] ?? null
            )
        );

        return $response;
    }
}
但須注意如果 JavaScript 有使用 axios 會有 419 問題,因為 axios 就是撈這個 cookie 作為 header,所以我們可以在 js 中加上。
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = document.head.querySelector('meta[name="csrf-token"]').content;

六、Cookies: Secure

說明:

Cookies 未確實設定「Secure」屬性。

處理:

Laravel 設定在 config/session.php。

/*
|--------------------------------------------------------------------------
| HTTPS Only Cookies
|--------------------------------------------------------------------------
|
| By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you when it can't be done securely.
|
*/

'secure' => env('SESSION_SECURE_COOKIE'),

七、Insecure Frame (External)

說明:

iframe 標籤缺少 sandbox 屬性。

處理:

增加 sandbox 屬性進行安全上的限制。

<iframe 
    src="https://www.google.com/maps/embed?..." 
    width="800" 
    height="600" 
    style="border:0;" 
    allowfullscreen="" 
    loading="lazy" 
    sandbox="allow-scripts allow-same-origin"
></iframe>
複測時說 sandbox 屬性裡面不能有 allow-scripts,最後索性把 iframe 拔掉。

留言