Integrarea autentificării cu doi factori cu CodeIgniter

Cu șirul recente de spargere (hacks) de la Sony și alte companii, este timpul să vă uitați la secțiunea de securitate a site-ului dvs. Web. Autentificarea cu două factori reprezintă un pas în direcția corectă de a vă asigura site-ul de atacatori. În acest tutorial, vom examina implementarea acestui lucru în aplicația noastră CodeIgniter.


Ce este autentificarea cu doi factori?

Autentificarea în doi factori cere utilizatorilor să folosească ceva pe care îl cunosc, cum ar fi un nume de utilizator și o parolă și ceva ce le are, cum ar fi un telefon, pentru a vă conecta.

În ultimul timp, companii precum Google și Facebook au lansat autentificarea cu doi factori pentru utilizatorii lor. Alte servicii, cum ar fi MailChimp, utilizează forme alternative de autentificare cu doi factori pentru a ajuta la atenuarea atacatorilor. Dar totuși, ce anume este autentificarea cu două factori?

Autentificarea cu două factori este o modalitate de a vă dovedi identitatea bazată pe numele de utilizator și parola dvs., precum și pe un dispozitiv fizic pe care îl puteți purta cu dvs..


Aplicația mobilă Duo acceptă notificări push pentru autentificare!

Acest lucru face mult mai greu pentru infractori să vă fure identitatea, deoarece acestea vor avea nevoie de acces la telefon sau jeton hardware - nu doar acreditările dvs. de conectare.

Lucru pentru dvs., Duo Security oferă un serviciu gratuit de două factori ideal pentru oricine caută să-și protejeze site-ul.

Nu numai că Duo este liber, dar este plin de caracteristici. Ele vă permit să vă autentificați într-o varietate de moduri, inclusiv:

  • Autentificare telefonică
  • Jetoane bazate pe SMS
  • Generator de jetoane pentru aplicația mobilă
  • Confirmare pe bază de push
  • Jetoanele hardware disponibile pentru cumpărare

Pasul 1: Configurare

Setup CodeIgniter

Dacă nu ați mai lucrat cu CodeIgniter înainte, vă recomandăm să consultați mai întâi seria TheCodeIgniter From Scratch.

Acest tutorial se va baza pe tutorialul Easy Authentication with CodeIgniter. Acest tutorial va fi mult mai ușor de înțeles dacă finalizați tutorialul anterior înainte de a continua. Vom folosi fișierele din tutorial ca punct de plecare.

Verificați că dvs. config / autoload.php are următorii ajutători încărcați.

$ autoload ['helper'] = array ('url', 'form');

Creează un cont

Mergeți la Duo Security și înscrieți-vă pentru un cont.

Acestea oferă un plan gratuit pentru proiecte open source și pentru site-uri cu mai puțin de 10 utilizatori Duo (utilizatorul A Duo este cineva care va utiliza autentificarea cu două factori pentru a vă conecta).

Creați o integrare

După înregistrare, trebuie să vă conectați la Duo și să creați o integrare. După ce v-ați conectat, faceți clic pe integrările pe panoul lateral pentru a scoate pagina integrată. De acolo, faceți clic pe butonul "Integrare nouă".

Asigurați-vă că integrarea pe care o creați este o integrare a SDK-ului Web. Acest lucru vă va permite să utilizați API-ul PHP cu CodeIgniter.

Numele de integrare este utilizat numai pe site-ul Duo. Aceasta este doar o modalitate de a vă identifica integrarea. Duo are un ghid de început care explică modul de configurare a integrării.

Descărcați aplicația SDK Web

În plus față de configurarea unei integrări, va trebui să descărcați Web SDK.

Există două componente ale SDK-ului de care avem nevoie: un fișier PHP (duo_web.php) și un fișier JavaScript. Rețineți că JavaScript are o dependență jQuery și JavaScript-ul asociat vine cu jQuery.

Vom folosi JavaScript-ul inclus, dar rețineți că dacă nu sunteți, jQuery trebuie încărcat înainte de JavaScript oferit de Duo. Pentru mai multe informații despre SDK-ul Web și despre cum funcționează, consultați documentația de la adresa http://www.duosecurity.com/docs/duoweb


Pasul 2: Modificări pentru securitate

După terminarea modulului Easy Authentication with CodeIgniter tutorial, trebuie să aveți un sistem de autentificare de bază.

O mai bună dispreț

Ca un prim pas, vom adăuga o funcție de hashing puternică în baza de date. Openwall are o bibliotecă frumos ce are implementat PHP bcrypt. Ultima versiune a phpass-ului este 0.3 la momentul prezentului articol.

Continuați și descărcați phpass de pe site-ul lor web: http://openwall.com/phpass/. După descărcarea și dezarhivarea folderului, va trebui să îl plasați în directorul dvs. de biblioteci.

Acum va trebui să facem propriul fișier de bibliotecă ca o interfață pentru phpass. Creați un nou fișier de bibliotecă, numit password.php. Biblioteca noastră va avea două funcții:

  • o funcție hash pentru a rehash vechile parole
  • o funcție check_password pentru a compara hashes cu parolele plaintext.
require_once ( 'phpass-0,3 / PasswordHash.php'); clasa Parola var $ hasher; funcția __construct () // 8 este puterea hash. O valoare mai mare poate fi folosită pentru securitate suplimentară. // TRUE face ca parolele să fie portabile. FALSE este mult mai sigur. $ this-> hasher = noul PasswordHash (8, TRUE);  funcția hash ($ pass) retur $ this-> hasher-> HashPassword ($ pass);  funcția check_password ($ pass, $ hash) retur $ this-> hasher-> CheckPassword ($ pass, $ hash); 

require_once () declarația asigură că vom putea să folosim PasswordHash clasa de la phpass.

PasswordHash ia două argumente în constructorul său:

  • un număr care indică o rezistență la hash
  • un boolean cu privire la faptul dacă parolele ar trebui să fie portabile sau nu.

În acest caz, vom face parolele noastre portabile.

Acest lucru înseamnă, în esență, că hash-ul nu este la fel de puternic, dar dacă avem nevoie să schimbăm serverele sau să mutăm baza de date, putem face o copie. Dacă nu folosim o schemă hashing portabilă, riscăm ca toți utilizatorii noștri să creeze parole noi în cazul în care baza de date este mutată.

Notă: Chiar dacă implementăm o funcție de hash mai puternică, trebuie să mai cereți utilizatorilor să aibă o parolă puternică.

Modificarea modelului de administrator

 funcția publică verifică ($ email, $ password) $ q = $ this -> db -> unde ('email_address', $ email) -> limit (1) -> get ('utilizatori'); dacă ($ q-> num_rows> 0) $ rezultat = $ q-> rând (); $ This-> a sarcinii> bibliotecă ( 'parola'); // Asigurați-vă că se potrivesc hash-urile. dacă ($ this-> password-> check_password ($ password, $ result-> password)) return $ rezultat;  return false; 

Anterior, am selectat utilizatorul prin adresa de e-mail și parola hashed. Acum tragem utilizatorul din baza de date pe baza adresei de e-mail. Aceasta înseamnă că trebuie să validăm parola înainte de a putea returna utilizatorul.

După ce am tras utilizatorul din baza de date, vom încărca biblioteca de parole pe care tocmai am creat-o și vom verifica dacă parola introdusă corespunde parolei șterse.

Dacă se potrivesc cele două parole, vom reveni la utilizator, altfel vom reveni fals.

Asigurați-vă că utilizați biblioteca de parole pentru a avea o parolă nouă pentru dvs. Parolele din baza de date vor fi invalide acum!

Modificarea tabelului utilizatorilor

Vom adăuga un câmp de permisiune de bază în baza de date. Această permisiune va determina dacă utilizatorul va intra sau nu în autentificare cu două factori.

Trebuie să adăugăm o coloană în tabelul utilizatorilor pentru permisiuni cu două factori. Puteți face acest lucru prin phpMyAdmin, sau prin rularea următorului SQL.

ALTER TABLE utilizatori ADD two_factor_permission BOOLEAN NOT NULL;

O valoare de 1 în coloana permisiune va face ca utilizatorul să utilizeze autentificarea cu doi factori.

SQL va adăuga o coloană booleană la tabela utilizatorilor. Vom folosi acest lucru pentru a cere utilizatorilor să utilizeze autentificarea cu două factori sau să o ocolească.

Dacă ați făcut acest lucru corect, ar trebui să vedeți o coloană nouă în tabelul dvs. de utilizatori. Apoi, va trebui să actualizați o înregistrare curentă sau să introduceți o nouă înregistrare care setează two_factor_permission la Adevărat (1).

Dacă această coloană este setată la fals (0), utilizatorul va putea ocoli autentificarea cu două factori. Acest lucru este ideal pentru utilizatorii care nu au nevoie de același nivel de securitate ca un administrator.


Pasul 3: Utilizarea setării de permisiuni

Vom avea nevoie de o modalitate de a ocoli autentificarea secundară, precum și de o modalitate de a introduce un pas secundar de autentificare în procesul de autentificare.

Omiterea autentificării secundare

În primul rând, vom avea nevoie de o cale de ocolire a autentificării secundare. Aceasta înseamnă că va trebui să inspectăm utilizatorul în controlerul de administrare.

 dacă ($ res! == FALSE) $ _SESSION ['username'] = $ res-> email_address; dacă ($ res-> two_factor_permission) $ this -> _ second_auth ($ res-> email_address); întoarcere;  altceva $ _SESSION ['logged_in'] = TRUE; redirecționare ( 'bun venit'); 

Aceasta verifică dacă utilizatorul ar trebui să fie conectat cu sistemul nostru cu două factori.

Dacă utilizatorul ar trebui să folosească autentificarea cu doi factori, vrem ca aceștia să meargă la pagina de autentificare secundară fără a le loga.

În loc să redirecționăm utilizatorul, putem apela _second_auth () și încărcați pagina. ""întoarcere"declarația evită încărcarea formularului de autentificare.

Am creat o nouă variabilă de sesiune conectat pe care o vom folosi pentru a verifica dacă utilizatorul a fost conectat. Aceasta înseamnă că trebuie să facem anumite modificări în redirecționările.

Fixarea redirecționărilor

Există două redirecționări care trebuie modificate: prima este în funcția index a controlorului de administrare.

dacă isset ($ _ SESSION ['logged_in']) && $ _SESSION ['logged_in'] === TRUE) redirect ('bun venit'); 

Celălalt este în Bine ati venit controlor. Trebuie să ne asigurăm că utilizatorul nu este conectat înainte de a redirecționa.

dacă isset ($ _ SESSION ['logged_in']) || $ _SESSION ['logged_in']! == TRUE) redirect ('admin'); 

Introducerea autentificării secundare

Acum trebuie să ne ocupăm de autentificarea secundară.

În admin / index funcția, sunăm _second_auth (), așa că să scriem o funcție de bază.

 funcția publică _second_auth ($ username) echo "Bine ați venit $ username, căutați o pagină secundară de autentificare."; 

Pasul 4: Construirea vederii

Sistemele de autentificare tradiționale tratează datele de conectare ca pe un singur pas.

Duo ne dă un pic de JavaScript și HTML pentru a injecta între cei doi pași. Aceasta înseamnă că va trebui să creați o vizualizare cu codul necesar.

Să creăm o nouă viziune, numită second_auth.php în vizualizari pliant. Va trebui să inserăm iframe-ul și JavaScript-ul oferite de Duo pentru a funcționa.

Ar trebui să creați o pagină cu structura HTML de bază. Următoarele pot fi plasate în organism:

  

Într-o configurație tipică, ați păstra toate JavaScript-ul într-un folder de resurse. Aici, am pus un resurse folder în rădăcina site-ului nostru, cu un "js"care conține fișierul JavaScript Web SDK.

Al nostru src va arata ca:

src =“resurse / js / Duo-Web-v1.js“

De asemenea, trebuie să adăugăm acest al doilea bit de JavaScript.

Vom genera aceste date de la operator în scurt timp.

Introducerea unui formular

Dacă ați urmat tutorialul anterior, ar fi trebuit să configurați CodeIgniter pentru a proteja împotriva CSRF.

Deoarece JavaScript va posta date controlorului nostru, CodeIgniter va căuta tokenul CSRF. Dacă nu avem acest jeton, vom primi o eroare.

JavaScript pe care îl folosim va trimite un formular cu codul "duo_form"Tot ce trebuie să facem este să-l creăm.

echo form_open ('admin', array ('id' => "duo_form")); echo form_close ();

Prin utilizarea clasei formularului, CodeIgniter va injecta automat tokenul. Când formularul este postat, CodeIgniter va găsi jetonul și să ne continuăm.


Pasul 5: Pregătirea datelor

Înapoi în admin controlor, trebuie să generăm niște date în cadrul nostru _second_auth () funcţie.

Gazda este adresa URL API la care ați fost furnizat când v-ați înscris la Duo. Această adresă URL ar trebui să arate ceva asemănător api-xxxxxxxx.duosecurity.com (unde 'xxxxxxxx' este un șir unic legat de contul dvs. Duo).

$ date ['gazdă'] = "api-xxxxxxxx.duosecurity.com";

Nu uitați să înlocuiți gazda cu adresa URL specifică. URL-ul de mai sus nu va funcționa.

Acțiunea post este adresa URL care va gestiona răspunsul odată ce utilizatorul a încercat să se autentifice cu Duo.

Vom crea o altă funcție în controlerul de administrare pentru a gestiona post-spate. Pentru moment, vom numi funcția process_second_auth ().

 date $ ['post_action'] = base_URL (). "Admin / process_second_auth";

Încărcarea fișierului SDK PHP Web

Asigurați-vă că redenumiți "duo_web.php" în "duo.php" pentru a evita erorile CodeIgniter.

Dacă nu ați descărcat ultima copie a duo_web.php, o puteți obține de pe pagina GitHub a site-ului Web SDK al Duo.

Deoarece SDK-ul Web vine ca o clasă PHP, îl putem redenumi "duo.php"și plasați-o în folderul" aplicații / biblioteci ".

După ce ați plasat fișierul în biblioteci dosar, îl putem încărca în controlerul nostru.

 funcția publică _second_auth ($ username) $ this-> load-> library ('duo'); $ date ['gazdă'] = "api-xxxxxxxx.duosecurity.com"; date $ ['post_action'] = base_URL (). "Admin / process_second_auth"; echo "Bine ați venit $ username, căutați o pagină secundară de autentificare."; 

Generarea solicitării semnate

Pentru a înțelege cum să generați sig_request, trebuie să înțelegeți ce generăm.

$ Akey variabila trebuie să aibă cel puțin 40 de caractere, altfel biblioteca Duo va afișa o eroare!

Duo Web SDK creează două semne semnate, una cu cheia secretă pe care o dau, alta cu o cheie de aplicație pe care o compuneți.

sig_request este o combinație a celor două jetoane.

Prin crearea cheii de aplicație proprie veți avea un al doilea nivel de securitate. Un atacator va avea nevoie atāt de cheia secretă de la Duo, cāt și de cheia dvs. de aplicație personală pentru a compromite un simbol.

Acum vom genera 'sig_request'. Duo vă va oferi o cheie de integrare și o cheie secretă când creați o integrare.

Asigurați-vă că înlocuiți textul de mai jos cu cheia de integrare și cheia secretă care vi sa dat. Trebuie să faci cheia ta secretă. Trebuie să aibă o lungime de cel puțin 40 de caractere și ar trebui să fie cât mai aleator posibil.

funcția publică _second_auth ($ username) $ this-> load-> library ('duo'); // Cheie de integrare Duo $ ikey = "ÎNLOCUIRE CU TASUL DE INTEGRARE DUO"; // Duo Secret Key $ skey = "Inlocuiti cu dvs. cheia secreta DUO"; // Cheie de aplicație personală $ akey = "CREATE A KEY APPLICATION"; $ date ['gazdă'] = "api-xxxxxxxx.duosecurity.com"; date $ ['post_action'] = base_URL (). "Admin / process_second_auth"; $ date ['sig_request'] = $ acest-> duo-> signRequest ($ ikey, $ skey, $ akey, $ username); echo "Bine ați venit $ username, căutați o pagină secundară de autentificare."; 

Duo signRequest () va genera jetoanele și le va returna ca un șir pentru a trece la sig_request.

Acum trebuie să încărăm datele în vizualizarea pe care am creat-o mai devreme.

funcția publică _second_auth ($ username) $ this-> load-> library ('duo'); // Cheie de integrare Duo $ ikey = "ÎNLOCUIRE CU TASUL DE INTEGRARE DUO"; // Duo Secret Key $ skey = "Inlocuiti cheia ta secreta DUO"; // Cheie de aplicație personală $ akey = "CREATE A KEY APPLICATION"; $ date ['gazdă'] = "api-xxxxxxxx.duosecurity.com"; date $ ['post_action'] = base_URL (). "Admin / process_second_auth"; $ date ['sig_request'] = $ acest-> duo-> signRequest ($ ikey, $ skey, $ akey, $ username); $ this-> load-> view ('second_auth', $ date); 

Dacă încercați să vă conectați acum, ar trebui să vedeți această pagină:

Acesta este formularul de înscriere. Vă puteți înscrie telefonul mobil aici, dar nu avem nimic de procesat autentificarea secundară, pentru a nu vă conecta.

Dacă nu vedeți nimic, vizualizați sursa paginii pentru mesajele de eroare. Orice erori cu datele vor fi afișate în > etichetă.

Dacă scrie "Accesul refuzat", asigurați-vă că ați introdus cheia de integrare și secretul de pe site-ul web al Duo Security.


Pasul 6: Procesarea autentificării secundare

Am creat acțiunea noastră pentru postare admin / process_second_auth, așa că trebuie să creați o process_second_auth () funcţie.

funcția publică process_second_auth () if (isset ($ _ SESSION ['logged_in']) && $ _SESSION ['logged_in'] === TRUE) redirect ('welcome'); 

Deoarece această funcție va avea propriul URL, trebuie să redirecționăm utilizatorii conectați.

Trebuie să încărăm din nou biblioteca Duo pentru a valida datele.

$ This-> a sarcinii> bibliotecă ( 'duo'); // Acele chei folosite în _second_auth () $ ikey = "ÎNLOCUIRE CU DUO INTEGRATION DOWN"; $ skey = "ÎNLOCUIRE CU DUO SECRET CHEIE"; $ akey = "ÎNLOCUIRE CU TASUL DE APLICARE";

Vom avea nevoie de același lucru $ ikey, skey și $ Akey de la _second_auth () pentru a valida datele postate.

Mesajele JavaScript înapoi a sig_response de la serverele Duo.

$ sig_response = $ this-> input-> post ('sig_response'); $ username = $ this-> duo-> verificaResponse ($ ikey, $ skey, $ akey, $ sig_response);

Odată ce am tras sig_response din datele postate, vom rula prin verifyResponse () funcţie. Aceasta va reveni la NULL dacă tokenurile nu se potrivesc sau un nume de utilizator dacă acestea sunt valide.

dacă ($ username) $ _SESSION ['logged_in'] = TRUE; redirecționare ( 'bun venit');  altceva redirect ("admin"); 

În cele din urmă, vom verifica dacă un nume de utilizator a fost returnat și încheiați conectarea prin setarea valorii acestuia $ _SESSION [ 'logged_in'] la adevărat.

Toate împreună funcția ar trebui să arate astfel:

funcția publică process_second_auth () if (isset ($ _ SESSION ['logged_in']) && $ _SESSION ['logged_in'] === TRUE) redirect ('welcome');  $ this-> load-> library ("duo"); // Aceleași chei folosite în _second_auth () $ ikey = "ÎNLOCUIRE CU KLU-ul de integrare DUO"; $ skey = "ÎNLOCAȚI CU DREPTUL SECRET DUO"; $ akey = "ÎNLOCUIRE CU TASUL DE APLICARE"; $ sig_response = $ this-> input-> post ('sig_response'); $ username = $ this-> duo-> verificaResponse ($ ikey, $ skey, $ akey, $ sig_response); dacă ($ username) $ _SESSION ['logged_in'] = TRUE; redirecționare ( 'bun venit');  altceva redirect ("admin"); 

Acum ar trebui să vă puteți autentifica cu autentificare cu doi factori, mergeți mai departe și încercați!


Concluzie

Sperăm că ați creat propriul sistem de autentificare cu două factori pentru CodeIgniter!

Ce altceva ai putea să faci? Există multe de făcut în ceea ce privește securitatea, dar cea mai mare îmbunătățire ar fi urmărirea acțiunilor utilizatorilor.

Un sistem de securitate bun nu este numai sigur: vă va ajuta să identificați de unde provine o vulnerabilitate. Ar trebui să țineți evidența încercărilor de conectare și a altor acțiuni pentru a ușura identificarea atacatorilor.

Vă mulțumim pentru lectură! Dacă aveți probleme, lăsați o postare în comentarii.

Cod