Aktuālā situācija: PHP2Shell. Divas kritiskas PHP ievainojamības (CVSS 9.2) ļauj izpildīt ļaunprātīgu kodu bez pieteikšanās. Ielāpi kopš 21.10.2026.Kas jādara tagad →

Paroļu droša glabāšana PHP: pareiza password_hash lietošana

Kā izstrādātāji PHP glabā paroles ar password_hash un password_verify, izvēlas piemērotu metodi un nomaina vecos MD5 vai SHA-1 jaucējkodus, nepieprasot paroles atiestatīšanu visiem lietotājiem.

Aktuāls uz 5 min lasīšanas laiksDroša izstrāde

Īsi sakot: Paroles PHP glabājiet ar password_hash() un pārbaudiet ar password_verify(). Noklusējums PASSWORD_DEFAULT pašlaik izmanto bcrypt, kopš PHP 8.4 ar izmaksu koeficientu 12; kur PHP ir kompilēts ar Argon2, laba alternatīva ir PASSWORD_ARGON2ID. Vecos MD5 vai SHA-1 jaucējkodus pārejat, tos nekavējoties ietverot password_hash un nākamajā pieteikšanās reizē aizstājot ar tiešu jaucējkodu.

Ko datubāzes noplūde sakara ar jūsu jaucējkodiem

Pēc ielaušanās tīmekļa serverī datubāze ir viens no pirmajiem mērķiem. Kas, kā tas iespējams ar PHP2Shell, var izpildīt kodu serverī, nolasa arī lietojumprogrammas piekļuves datus un tādējādi lietotāju kontu tabulu. Vai paroles tajā kļūs lasāmas pēc stundām vai pēc gadiem, izšķiras nevis uzbrukuma dienā, bet programmēšanas laikā.

Pārsteidzoši daudzas lietojumprogrammas paroles joprojām glabā ar metodēm, kas šim nolūkam nekad nav bijušas paredzētas: MD5, SHA-1, vienkāršu SHA-256 vai pat atgriezeniski šifrētas. Šīs metodes ir ātras, un tieši tā ir problēma. Uzbrucēji ar tām sekundē var izmēģināt ļoti daudz kandidātu.

PHP jau sen piedāvā risinājumu, kas rēķina lēni, katrai parolei automātiski izveido salt un pašā jaucējkodā saglabā metodi un parametrus. Tas tikai konsekventi jālieto.

password_hash PHP: bcrypt vai Argon2id?

password_hash() pazīst vairākas metodes. Izvēle saskaņā ar PHP rokasgrāmatu:

Konstante Metode Piezīme
PASSWORD_DEFAULT pašlaik bcrypt noklusējums, nākamajās versijās var mainīties
PASSWORD_BCRYPT bcrypt izmaksu koeficients kopš PHP 8.4 pēc noklusējuma 12, iepriekš 10; skaitās tikai pirmie 72 baiti
PASSWORD_ARGON2I Argon2i kopš PHP 7.2, tikai ja PHP būvēts ar Argon2 atbalstu
PASSWORD_ARGON2ID Argon2id kopš PHP 7.3, tas pats nosacījums

OWASP kā pirmo izvēli iesaka Argon2id ar vismaz 19 MiB atmiņas, diviem piegājieniem un vienu pavedienu, bet bcrypt galvenokārt esošām sistēmām. Lielākajai daļai PHP lietojumprogrammu starpība praksē ir mazāka nekā starpība starp jebkuru no šīm metodēm un MD5. Svarīgāk, ka jūs vispār lietojat kādu no tām un regulāri pielāgojat parametrus.

Vai Argon2id ir pieejams, parāda īss tests:

<?php
var_dump(defined('PASSWORD_ARGON2ID'));
var_dump(password_algos());

Glabāt un pārbaudīt: pilns paraugs

Šis piemērs rāda reģistrāciju un pieteikšanos ar novecojušu jaucējkodu automātisku atjaunināšanu. Garuma pārbaude pasargā no bcrypt 72 baitu robežas:

<?php
declare(strict_types=1);

const PASSWORT_ALGO = PASSWORD_DEFAULT;

function passwortSpeichern(string $passwort): string
{
    if (strlen($passwort) > 72) {
        throw new InvalidArgumentException('Passwort zu lang für das gewählte Verfahren.');
    }
    return password_hash($passwort, PASSWORT_ALGO);
}

function passwortPruefen(string $eingabe, string $gespeicherterHash, callable $hashAktualisieren): bool
{
    if (!password_verify($eingabe, $gespeicherterHash)) {
        return false;
    }
    if (password_needs_rehash($gespeicherterHash, PASSWORT_ALGO)) {
        $hashAktualisieren(password_hash($eingabe, PASSWORT_ALGO));
    }
    return true;
}

strlen() skaita baitus, nevis rakstzīmes. Šeit tas ir vēlams, jo bcrypt robeža attiecas uz baitiem. Kolonnai datubāzē saskaņā ar rokasgrāmatu jāietilpina vairāk par 60 rakstzīmēm, 255 ir laba izvēle. Nekad nenorādiet savu salt: šī opcija ir novecojusi un kopš PHP 8.0 tiek ignorēta.

Pārejot uz PHP 8.4, bcrypt noklusējuma izmaksu koeficients pieaug no 10 uz 12. Esošie jaucējkodi ar password_needs_rehash() nākamajā pieteikšanās reizē tiek automātiski paaugstināti. Stipri noslogotās sistēmās pirms pārejas vērts veikt īsu pieteikšanās slodzes testu.

Padoms

Izmēriet izmaksu koeficientu savā produkcijas serverī. Vienai pārbaudei jāprasa jūtams skaitļošanas laiks, bet jāpaliek ievērojami zem sekundes, lai pieteikšanās slodzes laikā nekļūtu par sašaurinājumu.

Veco MD5 un SHA-1 jaucējkodu nomaiņa

Īstais izaicinājums parasti ir esošie dati. Pašas paroles jūs nezināt, tātad nevarat tās vienkārši jauniekodēt. Gaidīt, kamēr katrs lietotājs atkal piesakās, atstāj neaktīvos kontus neaizsargātus. OWASP tāpēc apraksta divpakāpju pieeju:

  1. Nekavējoties ietvert: katru esošo MD5 vai SHA-1 vērtību ar skriptu ietvert password_hash() un saglabāt ar atzīmi, piemēram, kolonnā hash_typ.
  2. Pieteikšanās laikā pārbaudīt: atzīmētiem kontiem ievadi vispirms pārrēķināt ar veco metodi un tad ar password_verify() pārbaudīt pret ietverto vērtību.
  3. Tieši aizstāt: pēc sekmīgas pieteikšanās no atklātā teksta izveidot parastu jaucējkodu un atzīmi noņemt.
  4. Sakopt atlikumu: kontiem, kuriem pēc noteikta termiņa vēl ir ietverti jaucējkodi, iestatīt paroles atiestatīšanu.
<?php
// 1. posms (vienreiz ar skriptu): $neu = password_hash($alterMd5Wert, PASSWORD_DEFAULT);
// 2. un 3. posms pieteikšanās laikā:
if ($konto['hash_typ'] === 'md5-umhuellt') {
    $ok = password_verify(md5($eingabe), $konto['passwort_hash']);
    if ($ok) {
        $speichere(password_hash($eingabe, PASSWORD_DEFAULT), 'direkt');
    }
}

Ietverti jaucējkodi ir labāki nekā kaili MD5 vērtības, bet vājāki nekā tieši jaucējkodi. Tas ir pārejas risinājums, nevis mērķis. Pēc incidenta, kurā varētu būt skarta datubāze, šī pāreja neaizstāj aicinājumu lietotājiem nomainīt paroles. Kādas pēdas liecina par šādu incidentu, apraksta Vai esmu jau kompromitēts?.

Pepper, šifrēšana un citi maldu ceļi

Dažas idejas izklausās pēc lielākas drošības, bet dod maz vai kaitē:

  • Paša veidotas jaukšanas konstrukcijas, piemēram, vairākkārtējs SHA-256 ar pašu izveidotu salt, ir ātrākas nekā bcrypt un tāpēc vājākas.
  • Šifrētas paroles ir atgriezeniskas. Ja atslēga atrodas tajā pašā serverī, šifrēšana pēc ielaušanās gandrīz neaizsargā.
  • Pepper, tas ir, slepena papildu vērtība visām parolēm, var būt papildu slānis, ja to glabā atsevišķi no datubāzes. Tomēr tas neaizstāj labu jaukšanas metodi un apgrūtina vēlākas maiņas.
  • Pirmsjaukšana pirms bcrypt, lai apietu 72 baitu robežu, saskaņā ar OWASP rada savus riskus. Skaidra garuma robeža vai Argon2id ir vienkāršāk.

Arī jaunu paroļu noteikumiem vērts pievērst uzmanību tehnikas līmenim: garums aizsargā vairāk nekā sarežģīti norādījumi par speciālajām rakstzīmēm, un ļoti izplatītas vai jau datu noplūdēs parādījušās paroles jānoraida. Piespiedu maiņas fiksētos intervālos bez iemesla pēc pieredzes rada drīzāk paredzamus modeļus nekā stiprākas paroles.

Pieteikšanās sistēmām paroles nekad nav vienīgais elements: divu faktoru metodes administratoriem un bremze pret masveida pieteikšanās mēģinājumiem papildina glabāšanu. Abus aplūko ceļvedis Admin pieteikšanās aizsardzība pret Brute Force. Atiestatīšanas saitēm un vienreizējiem kodiem ir citi noteikumi, skatiet Droši gadījuma skaitļi un tokeni PHP. Pārskatu par citām funkcijām dod PHP iebūvētās drošības funkcijas.

Kā PHP SOS palīdz konkrēti?

  • Mēs pārbaudām, kā jūsu lietojumprogramma un spraudņi glabā paroles, un atrodam novecojušas metodes arī blakusfunkcijās.
  • Mēs plānojam esošo datu pāreju ar ietveršanu, pieteikšanās migrāciju un termiņu atlikušajiem kontiem.
  • Mēs saskaņojam izmaksu koeficientu vai Argon2 parametrus ar jūsu serveriem.
  • Pēc incidenta mēs palīdzam lemt par paroļu atiestatīšanu un tās tehnisko īstenošanu.

Savas PHP programmatūras pārbaudi piedāvājam kā drošības auditu un penetrācijas testu.

Biežāk uzdotie jautājumi

Kādu algoritmu izmanto password_hash ar PASSWORD_DEFAULT?

Pašlaik bcrypt. PHP rokasgrāmata norāda, ka noklusējums var mainīties, kad parādās stiprākas metodes. Tāpēc datubāzes kolonnai jāietilpina vairāk par 60 rakstzīmēm; rokasgrāmata kā labu izvēli min 255.

Vai paroles jāšifrē, nevis jāhešo?

Nē. Šifrētas paroles ar atslēgu var atkal nolasīt, un šī atslēga parasti atrodas tajā pašā serverī. Paroles jaucējkods ir vienvirziena iela: lietojumprogramma var tikai pārbaudīt, vai ievadītais der.

Cik augstam jābūt bcrypt izmaksu koeficientam?

Kopš PHP 8.4 noklusējums ir 12, iepriekš 10. OWASP kā apakšējo robežu min 10 un iesaka iet tik augstu, cik jūsu serveri panes. Izmēriet savā aparatūrā, cik ilgi ilgst viena pārbaude.

Ko nozīmē 72 baitu robeža bcrypt gadījumā?

bcrypt ņem vērā tikai pirmos 72 paroles baitus, viss pārējais tiek nogriezts. Ar burtiem ar diakritiskajām zīmēm viena rakstzīme bieži aizņem divus baitus. Tāpēc garumu ierobežojiet nepārprotami vai izmantojiet Argon2id, ja jūsu PHP ar to ir kompilēts.

Vai lietotājiem pēc ielaušanās jāmaina paroles?

Ja nevar izslēgt, ka datubāze ir aizplūdusi, tas jāierosina. Labi jaucējkodi paroļu uzlaušanu būtiski palēnina, taču vājas paroles paliek ievainojamas. Vai papildus pastāv ziņošanas pienākums, noskaidrojiet ar savu datu aizsardzības speciālistu.

Avoti

Tūlītējs kontakts

Katra stunda ir svarīga. Rakstiet mums tūlīt.

Īsi aprakstiet sistēmu, PHP versiju un novēroto. Mēs sazināsimies, noskaidrosim situāciju un strādāsim attālināti, līdz incidents ir slēgts un dokumentēts.

Tūlītēja palīdzība