Laravel应用程序中的常见安全错误

介绍

在大多数情况下,安全漏洞仅是由于缺乏意识而不是疏忽引起的。尽管我们发现大多数开发人员都在关注安全性,但有时他们不了解特定的代码模式如何导致漏洞,因此在电子书中,我们决定分享在帮助各种新兴公司保护其应用程序时遇到的最常见的安全性问题。 Laravel。在每个攻击示例中,我们还将向您展示保护应用程序免受攻击的最佳实践。我们希望这些信息对您和您的开发团队有用。

数码熊猫团队

SQL注入

Laravel提供了强大的查询生成器和雄辩的ORM。而且,多亏了他们,大多数请求在应用程序中默认情况下都受到保护,因此,例如

Product::where('category_id', $request->get('categoryId'))->get();

Laravel会将代码转换为准备好的语句并执行,因此将受到自动保护。

但是,尽管有一些Laravel无法保护的攻击媒介,但是开发人员通常会误以为Laravel可以防止所有SQL注入。

这些是我们在安全审核期间在现代Laravel应用程序中看到的最常见的SQL注入原因。

1.通过列名进行SQL注入

, , , Laravel , Query Builder Eloquent. , , , , .

Laravel:

PDO does not support binding column names. Therefore, you should never allow user input to dictate the column names referenced by your queries, including "order by" columns, etc. If you must allow the user to select certain columns to query against, always validate the column names against a white-list of allowed columns.

, SQL-:

$categoryId = $request->get('categoryId');
$orderBy    = $request->get('orderBy');

Product::query()
  ->where('category_id', $categoryId)
  ->orderBy($orderBy)
  ->get();

- orderBy

http://example.com/users?orderBy=id->test"' ASC, IF((SELECT count(*)
FROM users ) < 10, SLEEP(20), SLEEP(0)) DESC -- "'

SQL-:

select
  *
from `users`
order by `id`->'$."test"' ASC,
  IF((SELECT count(*) FROM users ) < 10, SLEEP(20), SLEEP(0))
DESC -- "'"' asc limit 26 offset 0

, Laravel*, , , Laravel , Query Builder .

, SQL-, - , , .

, «users» - "secretAnswer", SQL-.

2. SQL-

$id = $request->route('id');
$rules = [
    'username' => 'required|unique:users,name,' . $id,
];
$validator = Validator::make($request->post(), $rules);

Laravel $id , SQL-. " " > "SQL-".

3. SQL-

, , , , DB::raw . , , - . DB::raw - , , DB::getPdo()->quote.

:

public function update(Request $request) {
    $id = $request->route('id');

    $rules = [
        'username' => 'required|unique:users,username,' . $id,
    ];

    $validator = Validator::make($request->post(), $rules);

    if ($validator->fails()) {
        return response()->json($validator->errors(), 422);
    }

    $user = User::findOrFail($id);
    $user->fill($validator->validated());
    $user->save();

    return response()->json(['user' => $user]);
}

required|unique:users,username,'. $id? ! ()

, unique , . , $id , , . , , , .

1.

, - ID = 10|sometimes, required|unique:users,username,10|sometimes , - , .

2. DDOS REGEX

Regex ReDoS DDOS . , , , :

PUT /api/users/1,id,name,444|regex:%23(.*a){100}%23
{
    "username": "aaaaa.....ALOT_OF_REPETED_As_aaaaaaaaaa"
}

3. SQL-

SQL- . :

PUT /api/users/1,id,name,444|unique:users,secret_col_name_here
{
    "username": "secret_value_to_check"
}

, unique ( PDO) SQL- . Laravel .

:

  1. - , , ;

  2. (ID ), , .

XSS ( ) Laravel Blade

XSS 1990- , , - , , . , , XSS- :

Some text
<input onfocus='$.post("/admin/users", {name:"MaliciousUser", email:
"MaliciousUser@example.com", password: "test123", });' autofocus />
test

- . IP- , , /.

, XSS- Laravel.

Laravel Blade, XSS-, , :

// $name = 'John Doe <script>alert("xss");</script>';
<div class="user-card">
 <div> ... </div>
 <div>{{ $name }}</div>
 <div> ... </div>
</div>

Blade {{ }} . , :

<div class="user-card">
 <div> ... </div>
 <div>John Doe
&lt;script&gt;alert(&quot;xss&quot;);&lt;/script&gt;</div>
 <div> ... </div>
</div>

XSS. Laravel ( ) , XSS-, :

1. XSS {!! $userBio !!}

, HTML, {!! !!}:

// $userBio = 'Hi, I am John Doe <script>alert("xss");</script>';
<div class="user-card">
 <div> ... </div>
 <div>{!! $userBio !!}</div>
 <div> ... </div>
</div>

Laravel , $userBio JavaScript , XSS-.

:

  1. html , .

  2. , HTML, , htmlpurifier.org, HTML JS .

2. XSS a.href

, , , , XSS-:

1: javascript:code

// $userWebsite = "javascript:alert('Hacked!');";

<a href="{!! $userWebsite !!}" >My Website</a>

2: base64:

, .

// $userWebsite =
"data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGFja2VkISIpOzwvc2NyaXB0Pg
==";

<a href="{!! $userWebsite !!}" >My Website</a>

(«Hacked!») , « -» ...

:

  1. , . http/https ;

  2. , http/https «#broken-link».

3. XSS

Blade , , HTML. , , , Laravel :

// Registering the directive code
Blade::directive('hello', function ($name) {
    return "<?php echo 'Hello ' . $name; ?>";
});

// user.blade.php file
// $name = 'John Doe <script>alert("xss");</script>';

@hello($name);

:

Laravel e(), , . 3 , Laravel . , XSS- Laravel, XSS-, , , React.js, Vue.js, javascript jQuery, XSS-.

Laravel

Eloquent, ORM, , . , , .

, , :

// app/Models/User.php file
class User extends Authenticatable
{
    use SoftDeletes;

    const ROLE_USER = 'user';
    const ROLE_ADMINISTRATOR = 'administrator';

    protected $fillable = ['name', 'email', 'password', 'role'];

    // ... rest of the code ...
}

// app/Http/Requests/StoreUserRequest.php file
class StoreUserRequest extends Request
{
    public function rules()
    {
        return [
            'name'             => 'string|required',
            'email'            => 'email|required',
            'password'         => 'string|required|min:6',
            'confirm_password' => 'same:password',
        ];
    }
}
// app/Controllers/UserController.php file
class UserController extends Controller
{
    public function store(StoreUserRequest $request)
    {
        $user = new User();
        $user->role = User::ROLE_USER;
        $user->fill($request->all());
        $user->save();

        return response()->json([
            'success' => true,
        ],201);
    }

    // ... rest of the code ...
}

, , - , , .

{
    "name" : "Hacker",
    "email" : "hacker@example.com",
    "role" : "administrator",
    "password" : "some_random_password",
    "confirm_password" : "some_random_password"
}

"role" $fillable. "role" , . , , , API, - , Laravel, . $fillable , , , API, ACL.

, Laravel.

:

1.

, , . , . "name", "email" "password". Laravel $request->validated(), .

, $request->all() $request->validated() :

public function store(StoreUserRequest $request)
{
    $user = new User();
    $user->role = User::ROLE_USER;
    $user->fill($request->validated());
    $user->save();
    
    return response()->json([
        'success' => true,
    ],201);
}

Laravel, $request->validate() $validator->validated(), .

, , , .

2.

$fillable ( , ) $guarded ( , ), $guarded, .

3. . $model->forceFill($data)

$model->forceFill , $forceFill $fillable . forceFill, , .

, , ? , , . , , / . , , , 0,1-0,2% . , - 1 , 10 , 10'000-20'000 . , .

- , .

- Laravel Auth , , IP- , . , :

1.

, . Symantec , 80% 2FA.

2. IP-

, IP, .

3.

IP, 100% , .

4. , /

FaceBook, - , :

5.

, , .

, Laravel, SQL- XSS, , ACL . ACL - , .

Laravel , .

HTTP

- HTTP (HTTP Strict Transport Security, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, , . .), . HTTP . , HTTP Strict Transport Security HTTPS ( , HTTP HTTPS ). X-Frame-Options .

Laravel, . , , ? , , , , , .

Laravel , . , :

. , , 700 Equifax. , Equifax Apache Struts, 2 . Equifax 147,9 .

Laravel , , , , .

Laravel - , - - . , Laravel, API (, Eloquent), , Laravel , .

, , , , :

  1. Race Condition

  2. Server Side Request Forgery

  3. PHP Type Juggling

  4. Unrestricted File Upload

  5. Path Traversal

  6. Sensitive Data Exposure

  7. Server Side Template Injection

  8. Insecure Deserialization

  9. Session Fixation

  10. XML External Entity (XXE) Processing

  11. JWT Security

. , {{$userBio}} {!!$userBio!!}.

*“攻击媒介已在Laravel的最新版本中得到修复”-根据原始文章,它的发布日期以及在他们的网站上均不清楚,因此无法确定当时哪个版本的Laravel是最新的。但是,文章在翻译之日就已经掌握了,那时Laravel 8存在了几天。




All Articles