🔒 Hacked
Capitolul 10

Ghid practic pentru securizarea aplicațiilor tale Laravel azi

Ai învățat teoria. Înțelegi semnăturile, entropia, analiza comportamentală și de ce automatizarea contează. Acum e timpul să acționezi.

Acest capitol îți oferă pași acționabili pe care îi poți face astăzi - chiar acum, cu uneltele tale actuale - pentru a îmbunătăți dramatic postura de securitate a aplicației tale Laravel. Nu sunt necesare achiziții. Nu sunt necesare configurări complexe. Doar acțiuni practice care funcționează.

15 min
Audit Rapid
5
Fix-uri Critice
3
Scripturi de Detectare
Azi
Începe Acum

Auditul de Securitate în 15 Minute

Nu ai 8 ore pentru un audit complet? Începe cu aceste 10 verificări care prind cele mai critice probleme în 15 minute.

Verificare 1: Modul Debug (30 secunde)

Verifică Modul Debug
# În rădăcina proiectului tău
grep "APP_DEBUG" .env

# TREBUIE să arate: APP_DEBUG=false

# Dacă APP_DEBUG=true, expui credențiale atacatorilor

Repară imediat dacă e true:

# Editează .env
APP_DEBUG=false
💀

Modul Debug în Producție = Game Over

Modul debug expune APP_KEY, credențialele bazei de date, token-urile API, și permite atacuri XSS prin paginile de eroare. Acesta este adesea primul lucru pe care îl verifică atacatorii.


Verificare 2: Securitatea Fișierului Environment (1 minut)

Verifică Securitatea .env
# Este .env tracked în git?
git ls-files | grep "^.env$"
# Ar trebui să returneze NIMIC

# Este .env în .gitignore?

grep ".env" .gitignore

# Ar trebui să arate .env listat

# Sunt fișiere .env backup expuse?

ls -la .env* 2>/dev/null

# Ar trebui să arate doar .env, nu .env.backup, .env.old, etc.

Remediere:

# Adaugă în .gitignore dacă lipsește
echo ".env" >> .gitignore
echo ".env.backup" >> .gitignore
echo ".env.*.local" >> .gitignore

# Elimină orice fișiere .env tracked din istoricul git
git rm --cached .env 2>/dev/null

Verificare 3: Integritatea APP_KEY (30 secunde)

Verifică APP_KEY
# Verifică formatul APP_KEY
grep "APP_KEY" .env

# Ar trebui să înceapă cu: APP_KEY=base64:

# Ar trebui să aibă 44 de caractere după base64:
// În tinker, verifică lungimea cheii
php artisan tinker
>>> strlen(base64_decode(substr(config('app.key'), 7)))
// Trebuie să returneze: 32
🚨

Dacă APP_KEY Este Compromis

Dacă APP_KEY a fost vreodată expus (în git, log-uri, erori), atacatorii pot:

  • Decripta toate datele criptate
  • Falsifica cookie-uri de sesiune
  • Executa RCE prin deserializare

Generează o cheie nouă imediat: php artisan key:generate Apoi rotește toate datele criptate.


Verificare 4: Vulnerabilități Composer (2 minute)

Rulează Composer Audit
# Verifică pentru vulnerabilități cunoscute
composer audit

# Ar trebui să returneze: No security vulnerability advisories found

# Dacă se găsesc vulnerabilități, actualizează imediat

Dacă se găsesc vulnerabilități:

# Actualizează pachetul specific
composer update vendor/package-name

# Sau actualizează toate (cu grijă, testează după)
composer update

Pachete prioritare de menținut actualizate:


Verificare 5: Fișiere PHP în Directoarele de Upload (2 minute)

Găsește PHP în Uploads
# Verifică storage/app/public
find storage/app/public -name "*.php" -o -name "*.phtml" 2>/dev/null

# Verifică public/uploads (dacă există)

find public/uploads -name "_.php" -o -name "_.phtml" 2>/dev/null

# Verifică alte directoare de upload

find public -name "*.php" -not -path "public/index.php" 2>/dev/null

# Ar trebui să returneze NIMIC (sau doar index.php)
💀

PHP în Directorul de Upload = Backdoor Activ

Dacă găsești ORICE fișiere .php în directoarele de upload, presupune că ești compromis. Nu le șterge încă - investighează mai întâi, apoi urmează secțiunea de răspuns la incidente de la sfârșitul acestui capitol.


Verificare 6: Protecție Mass Assignment (2 minute)

Verifică Modele Neprotejate
# Găsește modele cu $guarded gol
grep -rn "guarded = []" app/Models/

# Ar trebui să returneze NIMIC

# $guarded gol permite atacatorilor să seteze ORICE câmp

Repară cele găsite:

// RĂU - permite setarea oricărui câmp
protected $guarded = [];

// BINE - permite explicit câmpurile
protected $fillable = ['name', 'email', 'password'];

// Sau protejează câmpurile sensibile
protected $guarded = ['id', 'is_admin', 'role'];

Verificare 7: Query-uri SQL Raw (2 minute)

Găsește Query-uri Raw
# Caută query-uri raw potențial vulnerabile
grep -rn "DB::raw|whereRaw|selectRaw|orderByRaw" app/

# Revizuiește fiecare rezultat pentru input utilizator în SQL-ul raw

Pattern vulnerabil:

// PERICULOS - SQL injection posibil
DB::select("SELECT * FROM users WHERE id = $id");
$query->whereRaw("status = '$status'");

Pattern sigur:

// SIGUR - parametrizat
DB::select("SELECT * FROM users WHERE id = ?", [$id]);
$query->whereRaw("status = ?", [$status]);

Verificare 8: Output Blade Neescapat (2 minute)

Găsește Output Neescapat
# Caută output Blade neescapat
grep -rn "{!!" resources/views/

# Fiecare rezultat este XSS potențial - revizuiește cu atenție

Revizuiește fiecare utilizare {!! !!}:

// PERICULOS dacă $userInput vine de la utilizator
{!! $userInput !!}

// SIGUR - escapat implicit
{{ $userInput }}

// Dacă e nevoie de HTML, sanitizează mai întâi
{!! clean($trustedHtml) !!}

Verificare 9: Securitatea Sesiunii (1 minut)

Verifică Configurația Sesiunii
// Verifică config/session.php

return [
'secure' => true, // Trebuie să fie true (doar HTTPS)
'http_only' => true, // Trebuie să fie true (fără acces JS)
'same_site' => 'lax', // Ar trebui să fie 'lax' sau 'strict'
];

Verificare 10: Permisiuni Storage (1 minut)

Verifică Permisiunile
# Verifică permisiunile directorului storage
ls -la storage/

# Directoarele ar trebui să fie 755 (drwxr-xr-x)

# Fișierele ar trebui să fie 644 (-rw-r--r--)

# Repară dacă e nevoie

chmod -R 755 storage/
chmod -R 755 bootstrap/cache/

Scripturi de Detectare Rapidă

Copiază aceste scripturi pentru a detecta rapid amenințări comune.

Script 1: Găsitor de Webshell-uri

find-webshells.sh
#!/bin/bash
# Detectare rapidă de webshell-uri pentru aplicații Laravel

echo "=== Laravel Webshell Scanner ==="
echo ""

# Verifică pentru semnături comune de webshell

echo "[1/5] Verificare pentru pattern-uri eval+base64..."
grep -rln "eval.*base64_decode|base64_decode.*eval" --include="*.php" app/ public/ storage/ 2>/dev/null

echo "[2/5] Verificare pentru system/exec cu input utilizator..."
grep -rln "systems*(s*\$_|execs*(s*\$_|passthrus*(s*\$_|shell_execs*(s*\$_" --include="*.php" app/ public/ storage/ 2>/dev/null

echo "[3/5] Verificare pentru utilizare assert()..."
grep -rln "asserts*(" --include="*.php" app/ 2>/dev/null

echo "[4/5] Verificare pentru create_function()..."
grep -rln "create_functions*(" --include="*.php" app/ 2>/dev/null

echo "[5/5] Verificare pentru preg_replace cu modificatorul /e..."
grep -rln "preg_replace.*/.*e" --include="*.php" app/ 2>/dev/null

echo ""
echo "=== Scanare Completă ==="
echo "Revizuiește cu atenție orice fișiere listate mai sus."

Salvează ca find-webshells.sh și rulează:

chmod +x find-webshells.sh
./find-webshells.sh

Script 2: Fișiere PHP Modificate Recent

recent-php-changes.sh
#!/bin/bash
# Găsește fișiere PHP modificate în ultimele 7 zile
# Util pentru detectarea infecțiilor recente

echo "=== Fișiere PHP Modificate Recent (Ultimele 7 Zile) ==="
echo ""

# Exclude vendor și node_modules

find . -name "_.php" -mtime -7 -not -path "./vendor/_" -not -path "./node_modules/_" -not -path "./.git/_" -exec ls -la {} ;

echo ""
echo "Revizuiește orice modificări neașteptate."

Script 3: Nume de Fișiere Suspecte

suspicious-files.sh
#!/bin/bash
# Găsește fișiere cu nume suspecte

echo "=== Detectare Fișiere Suspecte ==="
echo ""

echo "[1/4] Nume de fișiere PHP cu aspect aleatoriu..."
find . -name "_.php" -regex "._/[a-z0-9]{6,8}.php" -not -path "./vendor/*" 2>/dev/null

echo "[2/4] Fișiere PHP ascunse..."
find . -name "._.php" -not -path "./vendor/_" 2>/dev/null

echo "[3/4] Fișiere PHP în locații neașteptate..."
find ./public -name "_.php" -not -name "index.php" 2>/dev/null
find ./storage/app -name "_.php" 2>/dev/null

echo "[4/4] Fișiere cu extensii duble..."
find . -name "_.php._" -o -name "_.jpg.php" -o -name "_.png.php" 2>/dev/null

echo ""
echo "=== Scanare Completă ==="

Întărirea Configurației Critice

Aplică aceste configurații la toate aplicațiile Laravel de producție.

1. Întărire Environment

.env (Producție)
APP_ENV=production
APP_DEBUG=false
APP_URL=https://domeniultau.com

# Securitate puternică a sesiunii

SESSION_DRIVER=database
SESSION_SECURE_COOKIE=true
SESSION_LIFETIME=120

# Dezactivează funcționalități inutile

DEBUGBAR_ENABLED=false
TELESCOPE_ENABLED=false

2. Middleware Security Headers

app/Http/Middleware/SecurityHeaders.php
<?php

namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;

class SecurityHeaders
{
public function handle(Request $request, Closure $next)
  {
      $response = $next($request);

      $response->headers->set('X-Content-Type-Options', 'nosniff');
      $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
      $response->headers->set('X-XSS-Protection', '1; mode=block');
      $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');

      if ($request->secure()) {
          $response->headers->set(
              'Strict-Transport-Security',
              'max-age=31536000; includeSubDomains'
          );
      }

      return $response;
  }

}

Înregistrează în bootstrap/app.php (Laravel 11) sau app/Http/Kernel.php:

->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\App\Http\Middleware\SecurityHeaders::class);
})

3. Protecție Upload (.htaccess)

storage/app/public/.htaccess
# Previne execuția PHP în directorul de upload
<FilesMatch ".php$">
  Order Deny,Allow
  Deny from all
</FilesMatch>

# Blochează fișiere comune de atac

<FilesMatch "(^.ht|.bak$|.sql$|.zip$)">
  Order Deny,Allow
  Deny from all
</FilesMatch>

Creează acest fișier în fiecare director unde utilizatorii pot încărca fișiere.

4. Rate Limiting

routes/web.php
<?php

use IlluminateSupportFacadesRateLimiter;
use IlluminateCacheRateLimitingLimit;

// În AppServiceProvider sau RouteServiceProvider
RateLimiter::for('login', function (Request $request) {
  return Limit::perMinute(5)->by($request->ip());
});

RateLimiter::for('api', function (Request $request) {
  return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});

// Aplică la rute
Route::post('/login', [LoginController::class, 'login'])
->middleware('throttle:login');

Răspuns Imediat: Dacă Găsești Ceva

Ai rulat scripturile și ai găsit fișiere suspecte. Ce faci acum?

Pasul 1: Nu Intra în Panică, Nu Șterge

🚨

NU Șterge Imediat

Primul tău instinct va fi să ștergi malware-ul. Rezistă. Ștergerea distruge dovezi de care ai nevoie pentru a: - Înțelege cum au intrat - Găsi alte backdoor-uri - Preveni reinfecția

Pasul 2: Documentează Tot

# Creează director de incident
mkdir -p ~/incident-$(date +%Y%m%d)
cd ~/incident-$(date +%Y%m%d)

# Copiază fișierele suspecte (nu muta)
cp /path/to/suspicious/file.php ./

# Înregistrează metadatele fișierului
ls -la /path/to/suspicious/file.php > file-metadata.txt
stat /path/to/suspicious/file.php >> file-metadata.txt

# Obține hash-urile fișierului
md5sum /path/to/suspicious/file.php > file-hashes.txt
sha256sum /path/to/suspicious/file.php >> file-hashes.txt

# Verifică log-urile de acces recente
tail -1000 /var/log/apache2/access.log > access-log-sample.txt
# sau pentru nginx
tail -1000 /var/log/nginx/access.log > access-log-sample.txt

Pasul 3: Izolează (Dacă E Amenințare Activă)

Dacă găsești un webshell activ în utilizare:

# Opțiunea 1: Redenumește pentru a preveni execuția (păstrează pentru analiză)
mv suspicious.php suspicious.php.quarantine

# Opțiunea 2: Elimină permisiunile de execuție
chmod 000 suspicious.php

# Opțiunea 3: Blochează la nivelul serverului web (nginx)
# Adaugă în blocul server:
location ~ /path/to/suspicious\.php {
    deny all;
}

Pasul 4: Găsește Punctul de Intrare

Verifică aceste puncte de intrare comune:

Investigare Punct de Intrare
# 1. Verifică fișierele modificate recent în jurul momentului infecției
find . -name "*.php" -newer suspicious.php -mtime -1

# 2. Caută cod legat de upload care ar putea fi vulnerabil

grep -rn "move_uploaded_file|file_put_contents" app/

# 3. Verifică log-urile serverului web pentru fișierul suspect

grep "suspicious.php" /var/log/*/access.log

# 4. Caută alte fișiere create la momente similare

ls -la --time-style=full-iso $(dirname suspicious.php)

# 5. Verifică pentru pattern-uri de vulnerabilități cunoscute

grep -rn "unserialize._\$_" app/
grep -rn "include._\$_|require.*\$_" app/

Pasul 5: Verifică pentru Persistență

Atacatorii lasă adesea mai multe backdoor-uri:

Verificare Persistență
# Verifică crontab-urile
crontab -l
cat /etc/crontab
ls -la /etc/cron.*/

# Verifică fișierele Laravel modificate

# Compară cu o instalare Laravel proaspătă sau git

git diff --name-only HEAD

# Verifică fișierele .htaccess pentru redirectări

find . -name ".htaccess" -exec cat {} ;

# Verifică pentru eval în fișierele de configurare

grep -rn "eval|base64_decode" config/

# Verifică service providers pentru cod injectat

grep -rn "eval|system|exec|shell_exec" app/Providers/

Pasul 6: Curăță și Întărește

Doar după ce ai documentat și înțeles breșa:

  1. Elimină tot malware-ul identificat (l-ai documentat mai întâi, nu?)
  2. Rotește toate credențialele:
    • APP_KEY (php artisan key:generate)
    • Parole bază de date
    • Chei API
    • Sesiuni utilizator (php artisan session:clear sau truncate tabelul sessions)
  3. Actualizează toate dependențele: composer update
  4. Aplică toată întărirea de securitate din acest capitol
  5. Monitorizează atent pentru 2-4 săptămâni pentru reinfecție

Rutina Săptămânală de Securitate

Odată ce ai făcut întărirea inițială, menține securitatea cu această rutină săptămânală:

ZiTaskTimp
LuniRulează composer audit2 min
MiercuriRulează scriptul de detectare webshell5 min
VineriVerifică modificările recente de fișiere5 min
SăptămânalRevizuiește log-urile de eroare pentru anomalii10 min

Timp total: ~22 minute pe săptămână

Nu va prinde totul, dar e infinit mai bine decât nimic - și e sustenabil.


Lacuna Care Rămâne

Acum ai pași practici pentru a îmbunătăți securitatea imediat. Dar să fim onești despre limitări:

Ce POȚI Face ManualCe NU POȚI Face Manual
Verificări spot săptămânaleMonitorizare orară
Detectare semnături cunoscuteDetectare polimorfism AI
Audit configurație de bazăAnaliză comportamentală
Răspuns reactivPrevenție proactivă
Focus pe un singur siteCoordonare multi-site
ℹ️

Securitatea Manuală Are Limite

Pașii din acest capitol îmbunătățesc dramatic postura ta de securitate. Dar nu rezolvă problema fundamentală din Capitolul 8: nu poți fi peste tot odată, și amenințările nu așteaptă programul tău.

Scripturile și verificările din acest capitol sunt necesare dar nu suficiente. Sunt echivalentul de securitate al încuierii ușii din față - esențial, dar nu un sistem de securitate complet.

Pentru protecție completă, ai nevoie de:

Aici intervine scanarea automatizată.


Sumar

Acțiuni imediate (fă astăzi):

  1. Verifică APP_DEBUG=false
  2. Rulează composer audit și actualizează pachetele vulnerabile
  3. Verifică pentru fișiere PHP în directoarele de upload
  4. Revizuiește securitatea .env
  5. Adaugă protecție .htaccess în directorul de upload

Scripturi de detectare rapidă:

Dacă găsești malware:

  1. Documentează mai întâi, șterge mai târziu
  2. Găsește punctul de intrare
  3. Verifică pentru persistență
  4. Curăță, rotește credențiale, întărește
  5. Monitorizează pentru reinfecție

Rutina săptămânală:

Ai făcut primii pași. Ți-ai întărit aplicația. Ai configurat monitorizare de bază. E mai mult decât fac vreodată majoritatea dezvoltatorilor Laravel.

Dar știi că amenințările evoluează mai repede decât pot ține pasul verificările manuale. Știi că malware-ul generat de AI se schimbă la fiecare 15 secunde. Știi că auditurile săptămânale lasă ferestre de expunere de 6 zile.

Capitolul următor introduce o soluție care adresează aceste lacune.


Următorul: Capitolul 11 - Întâlnește-ți Noul Partener de Securitate

Ai făcut ce poți manual. Acum cunoaște unealta care face restul - 24/7, automat, în timp ce tu te concentrezi pe construirea funcționalităților.