TwojePC.pl © 2001 - 2025
|
 |
A R C H I W A L N A W I A D O M O Ś Ć |
 |
|
|
Zmniejszenie podatności logowania na atak z użyciem Rainbow Tables - czy to jest sensowne? , bwana 29/04/10 00:11 Cześć,
Zastanawiam się, czy następujące rozwiązanie będzie dobrym zabezpieczeniem przed atakiem na hasło z wykorzystaniem Rainbow Tables.
Jeśli mamy Rainbow Tables dla jakiejś puli potencjalnych haseł, to możemy wyszukać hasło, podając jego hasha. No ale jeśliby przed haszowaniem do hasła dodawać jakiś ciąg (najlepiej zmienny w ramach danego serwisu) to takie RbT nic by nie pomogło ewentualnemu włamasowi. A żeby ciąg nie był stały, mógłby być to np. login użytkownika, bo taki ciąg może być nawet jawny. I tak trzeba by na nowo generować Rainbow Tables pod konkretny login (czyli nakład pracy stałby się równy jak przy brute force).
Wtedy przy logowaniu po stronie zdalnego klienta (na jego maszynie) login doklejany byłby do hasła, następnie całość haszowana i wysyłana do serwera. Taki sam hash byłby po stronie serwera (razem z loginem). Po stronie serwera należałoby sprawdzić, czy dla danego loginu otrzymany hash "zdalny" jest identyczny z hashem utrzymywanym przez serwer i w zależności od tego zalogować bądź odmówić dostępu.
Intuicyjnie czuję, że to może być dobre rozwiązanie, ale na zagadnieniach dot. bezpieczeństwa sieci się po prostu nie znam - ma to ręce i nogi?"you don't need your smile when I cut
your throat" - Dobrze kombinujesz , Conroy 29/04/10 00:16
Tutaj więcej:
http://pl.wikipedia.org/.../S%C3%B3l_(kryptografia)http://flickr.com/photos/myhacien
da - :-D , bwana 29/04/10 01:10
czyli znów wymyśliłem coś, co istnieje. W ogólniaku na informatyce wymyśliłem relacyjną bazę danych - jakiż byłem rozczarowany, kiedy dowiedziałem się, że inni zrobili to wcześniej (choć z tych samych powodów);-D
i faktycznie, teraz mi się przypomina, salt lub sól tudzież algorytm z solą.
Może kiedyś się przyda, teraz to była teoretyczna dywagacja. Ale dzięki:-)"you don't need your smile when I cut
your throat"
- Dobrze to czujesz i tak zasadniczo się to robi :) , Mcmumin 29/04/10 00:23
Ja to rozwiązuję w frameworku:
pliczek config.inc.php :
<?php
@ini_set('display_errors', 'off');
@ini_set('upload_max_filesize', '100M');
@ini_set('default_charset', 'utf-8');
@ini_set('memory_limit', '32M');
if (function_exists('date_default_timezone_set'))
date_default_timezone_set('Europe/Warsaw');
/* Autoload */
function __autoload($className)
{
if (!class_exists($className, false))
require_once(dirname(__FILE__).'/../classes/'.$className.'.php');
}
include(dirname(__FILE__).'/settings.inc.php');
blablabla
i settings.inc.php:
<?php
define('__PS_BASE_URI__', '/');
define('_DB_NAME_', '####');
define('_DB_SERVER_', 'localhost');
define('_DB_USER_', '####');
define('_DB_PREFIX_', '##_');
define('_DB_PASSWD_', '####');
define('_DB_TYPE_', 'MySQL');
define('_MD5_KEY_', 'JAKIŚ_FAJNY_DŁUGI_CIĄG_ZNACZKÓW_DODAWANY_I_HASHOWANY_RAZEM_Z_HASŁEM');- Wszystko tylko nie MD5... , Tig3r 29/04/10 01:23
...ten skrót już dawno został skompromitowany. Chociaż przy długiej soli nadal się trzyma.
http://en.wikipedia.org/wiki/MD5#Security- hmm , Liu CAs 29/04/10 02:39
w takim razie, jak nie MD5 to jaki inny sensowny zamiennik ?-= parówkowym skrytożercom,
mowimy NIE =- - coś z , myszon 29/04/10 09:15
SHA - whirlpool , kubazzz 29/04/10 13:42
ja używam w zasadzie tylko tego.SM-S908
- mhm, tylko w przypadku Twojego frameworku ujawnienie wartości , bwana 29/04/10 01:39
stałej _MD5_KEY_ oznacza, że przygotowując RbT dedykowane Twojemu serwisowi (wiadomo, to i tak ogromny nakład obliczeniowy) można zaatakować wszystkie hasła, jakie są w tym serwisie używane. Gdyby zaś zamiast stałej wartości podawać jako sól (tadam! dzięki Conroy:-D) coś indywidualnego dla danego loginu (np. sam login) to dla złamania każdego hasła w serwisie trzeba by przygotowywać oddzielne RbT (co jest chyba bez sensu), dobrze to kumam?
Zastanawiam się, jak w Twoim ujęciu wygląda "obrót" wartością stałej _MD5_KEY_. Zakładam, że ta wartość musi trafić do klienta i być widoczna jawnie (w cookies, w kodzie strony, ostatecznie w pamięci peceta na którym działa klient) w formularzu logowania tak, aby ten formularz mógł skleić i zahaszować przed wysłaniem do serwera. A jakby tak pokombinować, żeby jawna wartość _MD5_KEY_ nie trafiała do klienta, a mimo to do serwera trafiała odpowiednio sklejona i zahaszowana wartość?
Jakby założyć, że serwis jest dobrze zabezpieczony, to hasła użytkowników mogłyby być przechowywane jawnie w bazie. I teraz np. Klient i Serwer podczas logowania synchronizowałyby czas. Data i czas z jakąś tam dokładnością byłyby używane jako sól. Serwis wiedziałby o której godzinie wysłał do klienta formularz logowania i przyjmując od klienta hasło zahaszowane jego (klienta) wraz datą i godziną, swoje lokalne hasło też by haszował po doklejeniu daty i godziny i porównywał hashe.
Jeśliby rozwiązać problem synchronizacji czasu między klientem i serwerem (raczej proste, nie?) to jedynym utrudnieniem byłoby to, że od wysłania formularza do klienta do odesłania formularza musiałoby upłynąć stosunkowo niewiele czasu (powiedzmy 20 sekund, zresztą życie by to zweryfikowało), żeby logowanie się udało (to tak jak przy wklepywaniu tokena, można się spóźnić i wysłać wszystko pięknie, tylko wartość tokena już jest nieaktualna). Doszłoby jednak ryzyko, że ktoś przygotowywałby RbT z uwzględnieniem przyszłych dat i godzin jako soli dodawanej do haszu, ale to już byłoby raczej karkołomne wyzwanie. Bonusem z takiego rozwiązania byłaby sól, którą nie trzeba by było zarządzać i do tego zmienna w czasie. Niedogodnością konieczność wysłania jawnego hasła podczas "zakładania konta" (lub w innej formie dostarczenia go do serwisu) i składowanie jawnych haseł. Hmmm... Ale ciekawe to jest:-D"you don't need your smile when I cut
your throat" - i wlasnie dotarles , Ranx 29/04/10 10:54
do tokenow:)
mniej wiecej:)o roztramtajdany charkopryszczańcu... - doszedłem, mówisz... , bwana 29/04/10 11:50
w ogóle nie poczułem, cholera;-D"you don't need your smile when I cut
your throat"
- :) po pierwsze - stała _MD5_KEY_ nie trafia do klienta , Mcmumin 29/04/10 11:12
po drugie to nie koniec niespodzianek :)
var $_iv = NULL;
function __construct($key, $iv)
{
$_iv = $iv;
$this->setKey($key);
}
function _encipher(&$Xl, &$Xr)
{
for ($i = 0; $i < 16; $i++) {
$temp = $Xl ^ $this->_P[$i];
$Xl = ((($this->_S[0][($temp>>24) & 255] +
$this->_S[1][($temp>>16) & 255]) ^
$this->_S[2][($temp>>8) & 255]) +
$this->_S[3][$temp & 255]) ^ $Xr;
$Xr = $temp;
}
$Xr = $Xl ^ $this->_P[16];
$Xl = $temp ^ $this->_P[17];
}
function _decipher(&$Xl, &$Xr)
{
for ($i = 17; $i > 1; $i--)
{
$temp = $Xl ^ $this->_P[$i];
$Xl = ((($this->_S[0][($temp>>24) & 255] +
$this->_S[1][($temp>>16) & 255]) ^
$this->_S[2][($temp>>8) & 255]) +
$this->_S[3][$temp & 255]) ^ $Xr;
$Xr = $temp;
}
$Xr = $Xl ^ $this->_P[1];
$Xl = $temp ^ $this->_P[0];
}
function encrypt($plainText)
{
$cipherText = '';
$len = strlen($plainText);
$plainText .= str_repeat(chr(0), (8 - ($len % 8)) % 8);
for ($i = 0; $i < $len; $i += 8) {
list(, $Xl, $Xr) = unpack('N2',substr($plainText, $i, 8));
$this->_encipher($Xl, $Xr);
$cipherText .= pack('N2', $Xl, $Xr);
}
return $cipherText;
}
function decrypt($cipherText)
{
$plainText = '';
$len = strlen($cipherText);
$cipherText .= str_repeat(chr(0), (8 - ($len % 8)) % 8);
for ($i = 0; $i < $len; $i += 8) {
list(, $Xl, $Xr) = unpack('N2', substr($cipherText, $i, 8));
$this->_decipher($Xl, $Xr);
$plainText .= pack('N2', $Xl, $Xr);
}
return $plainText;
}
function setKey($key)
{
$len = strlen($key);
$k = 0;
$data = 0;
$datal = 0;
$datar = 0;
for ($i = 0; $i < 18; $i++)
{
$data = 0;
for ($j = 4; $j > 0; $j--)
{
$data = $data << 8 | ord($key{$k});
$k = ($k + 1) % $len;
}
$this->_P[$i] ^= $data;
}
for ($i = 0; $i <= 16; $i += 2) {
$this->_encipher($datal, $datar);
$this->_P[$i] = $datal;
$this->_P[$i+1] = $datar;
}
for ($i = 0; $i < 256; $i += 2) {
$this->_encipher($datal, $datar);
$this->_S[0][$i] = $datal;
$this->_S[0][$i+1] = $datar;
}
for ($i = 0; $i < 256; $i += 2) {
$this->_encipher($datal, $datar);
$this->_S[1][$i] = $datal;
$this->_S[1][$i+1] = $datar;
}
for ($i = 0; $i < 256; $i += 2) {
$this->_encipher($datal, $datar);
$this->_S[2][$i] = $datal;
$this->_S[2][$i+1] = $datar;
}
for ($i = 0; $i < 256; $i += 2) {
$this->_encipher($datal, $datar);
$this->_S[3][$i] = $datal;
$this->_S[3][$i+1] = $datar;
}
}
}
class Blowfish extends Crypt_Blowfish
{
function encrypt($plaintext)
{
$ciphertext = '';
$paddedtext = $this->maxi_pad($plaintext);
$strlen = strlen($paddedtext);
for($x = 0; $x < $strlen; $x += 8)
{
$piece = substr($paddedtext, $x, 8);
$cipher_piece = parent::encrypt($piece);
$encoded = base64_encode($cipher_piece);
$ciphertext = $ciphertext.$encoded;
}
return $ciphertext;
}
function decrypt($ciphertext)
{
$plaintext = '';
$chunks = split('=', $ciphertext);
$ending_value = sizeof($chunks) ;
for($counter = 0; $counter < ($ending_value - 1); $counter++)
{
$chunk = $chunks[$counter].'=';
$decoded = base64_decode($chunk);
$piece = parent::decrypt($decoded);
$plaintext = $plaintext.$piece;
}
return $plaintext;
}
function maxi_pad($plaintext)
{
$str_len = sizeof($plaintext);
$pad_len = $str_len % 8;
for($x = 0; $x < $pad_len; $x++)
$plaintext = $plaintext.' ';
return $plaintext;
}
}
?>
Oczywiście TABLICE z własnym Blowfishem zostawię dla siebie :)- Czy wrzucanie tu kodu ma sens? , Tig3r 29/04/10 11:20
Wiesz chociaż, że bwana na pewno pisze w PHP?- pisze pisze , bwana 29/04/10 11:49
a właściwie kiedyś pisał: http://bwana.website.pl/kursphp/
ale teraz bez skupienia i tak rozumie trzy po trzy para piętnaście:-)"you don't need your smile when I cut
your throat"
- Może coś źle rozumiem, ale... , Tig3r 29/04/10 11:16
1. Hasła z formularza logowania są przesyłane do serwera w postaci odkodowanej - powiedzmy przez SSL (https) dla bezpieczeństwa.
2. Sól występuje tylko po stronie serwera - służy do zapisania hasła w bazie w sposób uniemożliwiający jego złamanie z pomocą Rainbow Tables.
3. Sól wcale nie musi być stała. Możesz przecież skorzystać z innych danych dostępnych dla danego użytkownika, na przykład (chociaż to już przesada) :
SHA1( login_z_formularza + stały_ciąg_znaków + data_rejestracji_podanego_loginu + kolejny_stały_ciąg_znaków + ip_zapisany_przy_rejestracji + kolejny_stały_ciąg_znaków + hasło_właściwe )
gdzie:
login_z_formularza, hasło_właściwe - wprowadzone przez użytkownika w formularzu logowania
data_rejestracji_podanego_loginu, ip_zapisany_przy_rejestracji - wartości wyciągnięte z bazy na podstawie loginu podanego w formularzu logowania
stałe_ciągi_znaków - zapisane w konfiguracji frameworka
Nie za bardzo rozumiem użycie jako soli wartości zmieniającej się z logowania na logowanie... np jeśli w bazie zaszyfrujesz hasło używając czasu rejestracji (powiedzmy 2010-04-29 11:13:00) to gdy zmieni się godzina nie będziesz już w stanie sprawdzić czy hasło jest poprawne.
W chwili sprawdzania poprawności hasła musisz być w stanie odzyskać (wygenerować, odczytać z bazy, z pliku) całą sól użytą do jego zakodowania (dokładnie: utworzenia skrótu)
|
|
|
|
 |
All rights reserved ® Copyright and Design 2001-2025, TwojePC.PL |
 |
|
|
|