Erros de segurança comuns em aplicativos Laravel

Introdução

Na maioria dos casos, as vulnerabilidades de segurança surgem apenas por falta de consciência e não por negligência. Embora descobrimos que a maioria dos desenvolvedores se preocupa com a segurança, às vezes eles não entendem como um determinado padrão de código pode levar a vulnerabilidades, portanto, neste e- book , decidimos compartilhar os problemas de segurança mais comuns que vimos enquanto ajudamos várias startups a proteger seus aplicativos. Laravel. Com cada exemplo de ataque, também mostraremos as melhores práticas para proteger seu aplicativo contra ataques. Esperamos que essas informações sejam úteis para você e sua equipe de desenvolvimento.

Equipe CyberPanda

injeção SQL

O Laravel fornece um Query Builder robusto e Eloquent ORM. E, graças a eles, a maioria das solicitações são protegidas em aplicativos por padrão, portanto, por exemplo, uma solicitação como

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

será automaticamente protegido quando o Laravel traduzir o código em uma instrução preparada e executar.

Mas os desenvolvedores geralmente cometem o erro de acreditar que o Laravel protege contra toda injeção de SQL, embora existam alguns vetores de ataque que o Laravel não pode proteger.

Esses são os motivos mais comuns de injeção de SQL que vimos em aplicativos modernos do Laravel durante nossas auditorias de segurança.

1. Injeção SQL via nome da coluna

, , , 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 , . , :

  • How To Secure Your Web App With HTTP Headers

  • bepsvpt/secure-headers - Security Headers Package for Laravel

  • SecurityHeaders.com - Online tool to check your headers

  • Content Security Policy evaluator from Google

  • Content Security Policy Generator

. , , 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!!}.

* "O vetor de ataque foi corrigido na última versão do Laravel" - de acordo com o artigo original, a data de seu lançamento não está clara, assim como no site deles, por isso não foi possível estabelecer qual versão do Laravel era a mais recente naquele momento. Mesmo assim, o artigo chegou às mãos no dia da tradução, e naquele momento o Laravel 8 já existia por alguns dias.




All Articles