Scrivere codice sicuro: come MYETV fare crypt, auth, trasferire e memorizzare le informazioni

A # Codechange # abbiamo implementato, ogni giorno, miglioramenti MYETV sicurezza; il primo lavoro è stato il servizio di autenticazione spiegato nel# Security # capitolo e poi abbiamo affinato le capacità degli sviluppatori per creare sicurezza esclusiva per il nostro sito web. Gli sviluppatori hanno fatto un aggiornamento ogni volta che abbiamo trovato qualche tipo di vulnerabilità; questo è estremamente utile per rendere l'algoritmo corregge sulla mosca, questo è il momento di concentrarsi su come abbiamo protetto pagine client-side che devono comunicare con il lato server (come chiamate ajax e aggiornamenti post/get). Infatti, abbiamo diviso le due operazioni: GET (dati inviati da querystrings) e POST (dati inviati da un modulo).

Nel primo caso (GET) l'utente deve seguire questi punti per richiedere con successo la pagina:

  1. Autenticare (se richiesta)
  2. Controllo intestazione per essere sicuri che viene chiamato solo tramite Javascript
  3. I/O salvare in un luogo sicuro del timestamp e le informazioni sull'utente, hashed con SHA512; ogni volta che una pagina client-side è richiesto il sistema può contare il datetime e quante volte la pagina è richiesta in un determinato periodo di tempo; si potrebbe essere temporaneamente vietato se si richiede la pagina troppo tempo in un determinato periodo di secondi
  4. Un token di solito inviato da querystring ed è lo SHA1 o SHA512 (dipende da quanto più veloce la richiesta deve essere) hash del sessionID dell'utente
  5. Questo token deve corrispondere all'ID di sessione originale dell'utente, quando l'utente effettua qualsiasi richiesta lato server
  6. Se il token match, allora è consentito fare una semplice richiesta GET

Come richiesta GET intendiamo qualsiasi richiesta che non tocchi database o I/O dei dischi rigidi e venga da querystrings.

Nel secondo caso (POST) l'utente deve seguire questi punti per richiedere con successo la pagina:

  1. Autenticare (se richiesta)
  2. Controllo intestazione per essere sicuri che viene chiamato solo tramite Javascript
  3. I/O salvare in un luogo sicuro del timestamp e le informazioni sull'utente, hashed con SHA512; ogni volta che una pagina client-side è richiesto il sistema può contare il datetime e quante volte la pagina è richiesta in un determinato periodo di tempo; si potrebbe essere temporaneamente vietato se si richiede la pagina troppo tempo in un determinato periodo di secondi
  4. Un primo token di solito inviato da GET (querystring) ed è l'hash SHA1 o SHA512 del sessionID dell'utente
  5. Un secondo token inviato da POST (forma) ed è la cripta aes256 dell'hash con SHA1 o SHA512 (dipende da quanto più veloce la richiesta deve essere) del sessionID dell'utente, più ulteriori informazioni come datatime e altri (crittografato solo con aes256 e pacchetto con tutta la richiesta)
  6. Questi due token devono corrispondere con l'ID sessione originale dell'utente, e le informazioni aggiuntive sono decifrate
  7. Se il token match, allora è consentito fare una semplice richiesta GET
  8. Con la datatime precedentemente crittografata possiamo controllare l'interazione degli utenti ogni secondo e possiamo approvare o non determinate azioni limitandole nel tempo
  9. Quando tutto è disaccoppiato di successo (token e informazioni aggiuntive), basta un paio di secondi per fare una normale richiesta lato server e quindi questo accesso sarà offuscato per il futuro

Come richiesta POST si intende qualsiasi richiesta che venga fornita da un modulo e/o toccare qualsiasi database o I/O dei dischi rigidi.

Controllo delle intestazioni lato server:

//accesso limitato ajax solo...
definire('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH]) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH]) == 'xmlhttprequest');
se(!IS_AJAX) {
die('accesso limitato');
#
$pos = strpos($_SERVER['HTTP_REFERER'],getenv('HTTP_HOST'));
Se(==false)
die('accesso limitato');
#

questo è un codice lato server (PHP) vi darà un'idea su come le intestazioni sono controllate; questa è una sicurezza aggiuntiva, ma le intestazioni potrebbero essere spoofed facilmente in modo da dobbiamo implementare un altro livello di sicurezza come di seguito.

Controllo disco rigido I/O

// numero di richieste di pagina consentite per l'utente
definire("CONTROL_MAX_REQUESTSclientside", 1);
// intervallo di tempo per iniziare a contare le richieste della pagina (secondi)
definire("CONTROL_REQ_TIMEOUTclientside", 1);
// secondi per punire l'utente che ha superato le richieste
definire("CONTROL_BAN_TIMEclientside", 10);
// IP dell'utente
se (vuoto($_SERVER["REMOTE_ADDR"])):
definire("USER_IPclientside", sanitizeUSERIPclientside(hash('sha512','clientside'.session_id())));
Altro:
definire("USER_IPclientside", sanitizeUSERIPclientside(hash('sha512', 'clientside'.$_SERVER["REMOTE_ADDR"]));
endif;

// directory writable per mantenere i dati dello script sostituire "[directory]" con una cartella sicura nel disco rigido
definire("SCRIPT_TMP_DIRclientside", "[directory]");
definire("CONTROL_DBclientside", "[directory2]");
definire("CONTROL_LOCK_DIRclientside", "[directory3]");
definire("CONTROL_LOCK_FILEclientside", "[directory4]".sanitizeUSERIPclientside(hash('sha512', USER_IPclientside));
@mkdir(CONTROL_LOCK_DIRclientside);
@mkdir (SCRIPT_TMP_DIRclientside);

//mostra l'errore se esiste qualche errore
se (file_exists(CONTROL_LOCK_FILEclientside) (')
se (tempo()-filemtime(CONTROL_LOCK_FILEclientside) > CONTROL_BAN_TIMEclientside) {
// questo utente ha completato la sua punizione
unlink (CONTROL_LOCK_FILEclientside);
} altro {
// troppe richieste
echo "Troppe richieste";
touch (CONTROL_LOCK_FILEclientside);
morire;
#
#

funzione antiflood_countaccessCLIENTSIDE() (')
// richieste di conteggio e ultima ora di accesso
$control = Array();
se (file_exists(CONTROL_DBclientside)) (')
$fh = fopen (CONTROL_DBclientside, "r");
$control = array_merge($control, (array)unserialize(fread($fh, filesize(CONTROL_DBclientside))));
fclose($fh);
#
se (isset($control[USER_IPclientside])) (')
se (tempo()-$control[USER_IPclientside]["t"] < CONTROL_REQ_TIMEOUTclientside) {
$control[USER_IPclientside]["c"]++;
} altro {
$control[USER_IPclientside]["c"] = 1;
#
} altro {
$control[USER_IPclientside]["c"] = 1;
#
$control[USER_IPclientside]["t"] = tempo();
se ($control[USER_IPclientside]["c"] >= CONTROL_MAX_REQUESTSclientside) {
// questo utente ha fatto troppe richieste entro un breve periodo di tempo
$fh = fopen (CONTROL_LOCK_FILEclientside, "w");
fwrite($fh, USER_IPclientside);
fclose($fh);
#
// scrittura tabella di controllo aggiornata
$fh = fopen (CONTROL_DBclientside, "w");
fwrite($fh, serialize($control));
fclose($fh);
#
//sanitizzare l'utente IP o sessionID per il nome del file da scrivere sul disco
funzione sanitizzare NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1 NT1
//sanitize userip o session ID
$userIP = str_replace(array('[\', \']'), '', $theuserIP);
$userIP = preg_replace('/\[.*\]/U', '', $userIP);
$userIP = preg_replace('/&(amp)?#?[a-z0-9]+;/i', '-', $userIP);
$userIP = htmlentities($userIP, ENT_COMPAT, 'utf-8');
$userIP = preg_replace('/&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);/i', '\1', $userIP );
$userIP = preg_replace(array('/[^a-z0-9]/i', '/[-]+/') , '-', $userIP);
ritorno strtolower(trim($userIP, '-'));
#

questo è un codice algoritmo lato server (PHP) e scriverà in un luogo sicuro dei dischi rigidi il numero di volte che la richiesta viene inviata, il timestamp e alcune informazioni uniche di questa richiesta hashed con SHA512 (come il nome del file); quando il numero di volte superato o il timestamp è diverso da quello specificato, la richiesta fallirà a tutti e viene visualizzato un errore. Questo algoritmo è un po' complicato e funziona da solo, con il numero dato di secondi e le cartelle giuste sul disco rigido, senza nessun altro intervento umano.

autenticazione Tokens

$token1 = urlencode(sha1(session_id());
// con AES256 CRYPT
$token2 = AES256CRYPT(sha1(session_id()),"[initialvectorkey]");
//WITHOUT aes 256 CRYPT
//$token2 = sha1(session_id());

definiamo il valore dei token nell'esempio precedente.

>
Traduzione: >" >
Traduzione: fp echo time(); ?> / >

< >

questo sopra è un esempio di una richiesta POST; in combinazione quando la richiesta POST viene licenziata, una richiesta GET viene licenziata anche (con javascript ajax) con una querystring come quella:

// Avviare la richiesta a /form.php (non percorso reale, solo per esempio)
richiesta = $.ajax({
url: "form.php?token1= fp echo $token1 >",
tipo: "post",
dati: serializzato Dati
});

in questo modo i due gettoni vengono inviati dal client agli script lato server pronti per essere abbinati.

Abbina i token

$token1GETVAR = urldecode($_GET['token1']);
// con AES256 CRYPT
$token2POSTVAR = AES256DECRYPT($_POST['token2'], "[initialvectorkey]");
// senza AES256 CRYPT
//$token2POSTVAR = $_POST['token2'];
$token1PHPVAR = sha1(session_id());
$token2PHPVAR = sha1(session_id());
se($token2POSTVAR!= $token2PHPVAR || $token1GETVAR!= token1PHPVAR):
die('