DWORD dwTickBegin = GetTickCount(); while (GetTickCount() < dwTickBegin + 5000) Sleep(100);
#define __STDSTRING #include <string> #include <stdio.h> #include <windows.h> using namespace std; int main(int argc, char* argv[]) { DWORD tick_begin, tick_end; tick_begin = GetTickCount(); #ifdef __STDSTRING string dest; string src("test1"); for (int x = 0; x < 100000; x++) dest = src + "test2"; #else char* dest = (char*)malloc(1024); memset(dest, 0, 1024); char* src = "test1"; for (int x = 0; x < 100000; x++) { memset(dest, 0, 1024); strcat(dest, (char*)&src); strcat(dest, "test2"); } free(dest); #endif tick_end = GetTickCount(); printf("100000 additions in %u msec (%u, %u) -- %.5f per add\n", tick_end - tick_begin, tick_begin, tick_end, (tick_end - tick_begin) / 100000.0); return (0); }
' WinAPI structures Private Type ACL AclRevision As Byte Sbz1 As Byte AclSize As Integer AceCount As Integer Sbz2 As Integer End Type Private Type SECURITY_DESCRIPTOR Revision As Byte Sbz1 As Byte Control As Long Owner As Long Group As Long Sacl As ACL Dacl As ACL End Type Private Type SECURITY_ATTRIBUTES nLength As Long lpSecurityDescriptor As Long bInheritHandle As Long End Type ' WinAPI constants Private Const MUTEX_ALL_ACCESS = 2031617 Private Const SECURITY_DESCRIPTOR_REVISION = (1) ' Mutex related WinAPI imports Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As SECURITY_ATTRIBUTES, ByVal bInitialOwner As Long, ByVal lpName As String) As Long Private Declare Function OpenMutex Lib "kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long Private Declare Function InitializeSecurityDescriptor Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, ByVal dwRevision As Long) As Long Private Declare Function SetSecurityDescriptorDacl Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, ByVal bDaclPresent As Long, pDacl As Long, ByVal bDaclDefaulted As Long) As Long ... Dim MutexHandle As Long ... ' Opening mutex with NULL DACL MutexHandle = OpenMutex(MUTEX_ALL_ACCESS, 0, "VBMUTEX05") If MutexHandle = 0 Then Select Case Err.LastDllError Case 2& ' Preparation of NULL SECURITY_DESCRIPTOR Dim MutexAtts As SECURITY_ATTRIBUTES MutexAtts.bInheritHandle = False MutexAtts.nLength = Len(MutexAtts) Dim SecDesc As SECURITY_DESCRIPTOR Dim SecInitRes As Boolean SecInitRes = InitializeSecurityDescriptor(SecDesc, _ SECURITY_DESCRIPTOR_REVISION) If Not SecInitRes Then ' ERROR initializing SD Exit Sub End If Dim SetSDRes As Boolean SetSDRes = SetSecurityDescriptorDacl(SecDesc, _ True, ByVal 0&, False) If Not SetSDRes Then ' ERROR creating DACL-SD Exit Sub End If MutexAtts.lpSecurityDescriptor = VarPtr(SecDesc) ' Creating the mutex with NULL DACL MutexHandle = CreateMutex(ByVal MutexAtts, 0, "VBMUTEX05") Case Else ' ERROR: Unknown Exit Sub End Select End If ' SUCCESS ...
BEGIN TRAN [SQL_QUERY ktoru chceme zanalyzovat] EXEC sp_lock SELECT object_name([ID z vysledku ObjID volania sp_lock]) UNION [dalsie objectnames]...; COMMIT
BEGIN TRAN UPDATE J ... UPDATE V ... UPDATE V ... ... UPDATE V ... COMMIT
SELECT COUNT(*) from J ...
SELECT count(*) from J (NOLOCK) where ...
SELECT count(*) from J (READPAST) where ...
Základný problém prihlasovania sa cez http protokol (pri absencii https), prípadne pri prihlasovaní sa na služby tretích strán, je možnosť odchytenia plaintext hesla, či už na strane poskytovateľa internetového pripojenia (prípadne na trase od klienta na server), alebo priamo na serveri zo strany implementátora služby.
Riešením by bolo, neprenášať heslo v plaintext tvare a tým zamedziť uloženiu a následnému zneužitiu hesla.
CramMD5 autentifikácia je založená na predspracovaní hesla na strane klientskej stanice. Základom je skriptovací jazyk (najčastejšie použitý JavaScript), ktorý vytvorí na základe vstupných dát poskytnutých serverom MD5 hash, ktorý sa použije na porovnanie hesla na strane serveru. Tento hash sa potom prenesie v plaintext forme nezašifrovanou linkou a tým zamedzí odchyteniu plaintext hesla. Takýto hash je potom v závislosti na implementácii platný pre dané spojenie, prípadne obmedzený aj špecificky na IP adresu.
Riešenie CramMD5 autentifikácie sa skladá z klientskej a serverovej časti.
V prípade, že nie je používateľ autentifikovaný, zobrazuje sa – ako v každej klasickej webovej aplikácii – prihlasovací formulár. V prípade CramMD5 autentifikácie je rozšírený o niekoľko skriptov a skryté polia, obsahujúce kontrolné informácie. (Ako konkrétne príklady implementácie použijem zdrojový kód demonštrácie sociálnych sietí.)
<form action="" method="POST" onSubmit="return (SecOnSubmit())"> <b>ID: </b><input name="sec_login" /> <b>PWD:</b><input id="SecPwd" name="sec_password" type="password" /> <input id="SecCraMD5" name="sec_cramd5" value="0" type="hidden" /> <input id="SecCraMD5Hash" name="sec_cramd5_hash" value="<?php echo md5(uniqid(rand(), true)); ?>" type="hidden" /> <input type="submit" value="Submit Credentials" /> <script language="JavaScript"><!-- // will hide the warning if javascript enabled and sets sec_cramd5 to 1 document.getElementById('SecCraMD5').value = '1'; //--></script> </form>
Okrem vstupných polí sec_login a sec_password môžeme vidiet aj skryté polia sec_cramd5 a sec_cramd5_hash. Ich význam je nasledovný:
Po odoslaní takéhoto formulára sa vykoná onsubmit handler SecOnSubmit(), ktorého zdrojový kód vyzerá nasledovne:
function SecOnSubmit() { var pwdObj = document.getElementById('SecPwd'); var hashObj = document.getElementById('SecCraMD5Hash'); pwdObj.value = hex_md5(hashObj.value + hex_md5(pwdObj.value)); return (true); }
Je to multiplatformový JavaScript kód, ktorý zozbiera informácie z formulára, zavolá externý skript, ktorý vygeneruje MD5 hash z vložených údajov a prepíše výsledkom pole password vo formulári. Týmto postupom si zabezpečíme, že v prípade funkčnosti CramMD5 autentifikácie prejde z poľa sec_password len náš hash a v konečnom dôsledku si uľahčíme spracovanie na strane serveru.
V prípade, že CramMD5 nie je podporovaný, handler sa nevykoná a na server je poslané plaintext heslo taktiež cez pole sec_password spolu s informáciou v sec_cramd5, že autentifikácia nie je podporovaná.
<?php include_once dirname(__FILE__).'/passwordList.class.php'; class ESecException extends Exception { /* blank */ } class CSec { static public function authenticate ($in_PwdFile, $in_ID, $in_Password, $in_CraMD5, $in_CraMD5_Hash) { $pwd_Hash = CPasswordList::getPasswordById($in_PwdFile, $in_ID); if (!$pwd_Hash) throw new ESecException('User unknown.'); if ($in_CraMD5 == '1') $sec_Hash = CSec::generateCraMD5Hash($pwd_Hash, $in_CraMD5_Hash); else { $sec_Hash = $pwd_Hash; $in_Password = md5($in_Password); } return ($sec_Hash == $in_Password); } static public function generateCraMD5Hash($in_Pwd_Hash, $in_CraMD5_Hash) { return (md5($in_CraMD5_Hash.$in_Pwd_Hash)); } } ?>
Serverová časť je – ako vidieť na listingu – v tomto prípade veľmi priamočiara, na základe kontrolných údajov vyberie vhodnú metódu autentifikácie a vytvorí požadovaný porovnávací hash. Následne vo výsledku volania funkcie rozhodne o zhode / nezhode hashu a pošle logickú informáciu ako výsledok. Prihlasovací mechanizmus následne rozhodne o ďalšom postupe.
V tejto časti môže byť taktiež implementované bezpečnostné vylepšenie, napríklad kontrola IP adresy, alebo spolupráca s databázou, alebo sessions.
CramMD5 nájde uplatnenie všade tam, kde je podstatná bezpečnosť hesiel a istota používateľov aj bez možnosti preskúmať serverovú časť aplikácie. Technológia zabezpečí, že pri splnení všetkých požiadaviek, nie je používateľovo heslo odosielané na server v žiadnom prípade (pokiaľ nie je požiadavka na zmenu hesla, v tom prípade je nutné posielať toto heslo minimálne v tvare MD5 hashu na uloženie do databázy).
Základom na napísanie tohto článku bol proof-of-concept jednej teórie, ktorá je založená na článku publikovanom na serveri Gamasutra, pojednávajúcom o aplikácii sociálnych sietí v komunikácii NPC postáv v hernom svete. Táto implementácia vyžadovala vytvorenie hodnôt vzťahov jednotlivých postáv, čo bola v navrhovanej implementácii práca game designera, prípadne náhodne rozdelenie vzťahov medzi postavami.
Nasledovný problém bol, ako nadefinovať rozdelenie vzťahov jednotlivých postáv tak, aby reflektovali nejaký sociálny vzor – dve postavy, ktoré sa navzájom akceptujú by mali mať tretiu, ktorá je im obom blízka a akceptujú ju taktiež – pričom treba predpokladať aj stav, že tento predpoklad neplatí.
Riešením bolo, nájsť vzorku reálnych vzťahov existujúcich osôb a využiť ju v nasledovných výpočtoch. Ako dostupná a dostatočne rozmanitá vzorka sa zdala byť užívateľská základňa serveru kyberia.sk. Keďže po zanalyzovaní vzorky, vytvorení a následnom naimplementovaní základných vzorcov a postupov začali vznikať zmysluplné výsledky (overované spoluprácou s niekoľkými osobami, nad ktorých dátami analýzy prebiehali), prišiel som na ideu rozšíriť toto zbieranie údajov na ďalšie spracovanie na jednoduchú demonštráciu sily verejne dostupných údajov, ktorá je zhrnutá v tomto článku.
Základnými údajmi využívanými na analýzu boli verejne dostupné údaje zo serveru kyberia.sk, ktoré si každý užívateľ môže nájsť vo výstupoch systému. Ja som v rámci minimalizácie záťaže na systém využil možnosť prístupu priamo na databázu a vykonal niekoľko databázových požiadaviek, ktoré mi vrátili požadované údaje. Výsledkom zberu dát boli nasledovné súbory (z každého súboru poskytnem aj prvých 10 riadkov, aby bolo zrejmé, že neboli spracovávané nijaké súkromné údaje).
Súbor obsahuje zoznam všetkých užívateľov systému kyberia.sk s ich user_id. Slúži na vytriedenie nesprávnych záznamov v databáze a na zobrazenie korektných používateľských mien.
user_id login 207 \t 1645402 2560 alyosha\t 1493201 ONO 2588 t0mix 2352207 . 1087140 hellish 1670555 lubo 1168554 pietro
Súbor obsahuje vzťahy jednotlivých usernodes a detaily o vzťahoch.
node_id user_id node_bookmark node_permission last_visit visits given_k 104 107 no NULL 2006-07-03 22:31:11 5 no 104 123 no NULL 2006-08-12 02:24:10 0 no 104 138 no NULL 2005-05-24 12:53:56 2 no 104 146 no NULL 2005-04-13 23:07:22 3 no 104 155 no NULL 2005-06-04 23:58:31 1 no 104 193 no NULL 2005-02-01 22:15:24 0 no 104 213 no NULL 2005-09-18 17:20:11 0 no 104 252 no NULL 2006-07-13 18:20:15 1 no 104 313 no NULL 2006-06-24 12:44:28 0 no
Súbor obsahuje všetky friend nody každého užívateľa systému.
node_parent node_creator 433 433 495 495 781 781 120 798 666 940 1100 1100 1165 1165 1170 1170 1246 1246
Na vygenerovanie súborov boli použité SQL požiadavky vykonané nad databázou systému.
select user_id, login from users;
select node_parent, node_creator from nodes where node_parent in (select user_id from users);
select node_id, user_id, node_bookmark, node_permission, last_visit, visits, given_k from node_access where node_id in (select user_id from users);
Teória tejto demonštrácie je založená na vybudovaní siete vzťahov medzi jednotlivými usernodami a následným vypočítaním váh na základe takto definovaných vzťahov a parametrov. Množstvo premenných, s ktorými som mohol pracovať bolo obmedzené údajmi, ktoré som si vyžiadal od databázy, ako aj výpočtovou náročnosťou celého procesu.
Následným analyzovaním a skúšaním hodnôt váh som dospel k rozdeleniu, ktoré poskytovalo na testovacej vzorke zmysluplné a dostatočne presné výsledky, ktoré sa ukázali byť platné aj na ďalších testovaných usernodách.
Systém váh berie do úvahy nasledovné údaje:
Znamená to situáciu, keď sa usernode1 pridala do zoznamu priateľov v usernode2. Takýto vzťah určil základné prepojenia v budovanej sieti a nastavil každú reláciu usernode1 › usernode2 na počiatočnú váhu 2.
Situácia, pri ktorej vieme, že usernode1 navštívil usernode2, prípadne usernode2 zadefinovala špeciálny parameter, obmedzujúci prístup usernode1 (napríklad silence, ban, prípadne access). Taktiež sa v tomto momente upravujú váhy v prípade, že si usernode1 pridala usernode2 do bookmarks, alebo udelila „K“ usernode2.
Jednotlivé váhy sú upravované nasledovne:
V tomto prípade sa berie do úvahy celkové množstvo návštev usernode1 v ostatných nodách (súčasná implementácia berie do úvahy aj návštevy svojej usernode, modifikácia tohoto parametra môže byť ďalším vylepšením algoritmu). Následne sa zoberie počet návštev v usernode2 a vyráta sa percentuálny podiel návštev v tejto node. Z tohoto percentuálneho podielu je vyrátaná váha na základe vzorca:
Influences::USER_VISIT * $t_Relation_Relator->m_VisitPerc // Súčasná implementácia má nastavenú hodnotu konštanty Influences::USER_VISIT na 1.64
Taktiež sa berie do úvahy aj faktor poslednej návštevy usernode1 v usernode2. Tento je skombinovaný s bodmi, získanými vyššie uvedeným vzorcom pomocou prirodzeného logaritmu ošetreného o extrémne prípady a pripočítaný k celkovej váhe prepojenia.
Údaje sú pred zobrazením a vytriedením normalizované na percentá, keďže váhy, ktoré vznikli počítaním sú bezrozmerné čísla a sú nepoužiteľné na ďalšie výpočty. Tieto percentuálne hodnoty sú následne zoradené zostupne a prezentované.
Implementácia celej demonštrácie bola vykonaná použitím jazyka PHP, ktorý poskytuje jednoduché nástroje na prácu s textom a súbormi, využívajúc netypovosť jednotlivých objektov jazyka. Z tohto vyplynul aj základný problém a to rýchlosť a pamäťová náročnosť, keďže prepočítavanie údajov zabralo odhadom 300M pamäte a 10 minút času. Z tohto dôvodu boli neskôr údaje z finálneho prepočtu prevedené do binárnej podoby, nad ktorou je vytvorený index, ktorý umožňuje prácu s údajmi v reálnom čase.
Výsledky jednotlivých prepočtov si každý používateľ môže po zadaní ID (číselného) a hesla aktuálneho k dátumu uvedenému v aplikácii pozrieť na adrese:
Na prihlasovanie je využitá technika CramMD5, ktorá zabraňuje odchyteniu, prípadne uloženiu plaintext hesla na strane serveru, takže je takéto prihlasovanie bezpečné. Pracuje však len v prípade, že je na strane klientského prehliadača povolený JavaScript, čo si systém overí a prípadne zobrazí upozornenie.
V prípade ideálnych podmienok systém vytvorí unikátny hash, ktorý sa pošle na stranu serveru na overenie, takže aj v prípade odchytenia hesla útočník pozná len heslo pre danú reláciu a nie plaintext verziu hesla, prípadne jeho md5 hash.
Úlohou tohto článku a demonštrácie bolo poukázať na možnosť využitia verejne dostupných údajov na získanie bližšieho obrazu o jednotlivcovi, prípadne skupine jednotlivcov. Analýzy, ktoré sú vykonávané touto implementáciou sa orientujú na základe špecifických, ale veľmi obmedzených údajov. Je len na implementátorovi systému, koľko údajov ukladá na ďalšiu analýzu a tým získava vzorku, s ktorou vie zmysluplnejšie pracovať.
Jedným zo serverov, ktorý zakladá svoju silu na analýze údajov od používateľov je Google, ktorý pomocou množstva projektov dokáže zozbierať neuveriteľné množstvo prísne personalizovaných informácií, na základe ktorých dokáže cieliť reklamu a vytvárať demografické štúdie na žiadosť zákazníkov, prípadne pre vlastnú potrebu.
Ďalšie využitie vidím v implementácii niekoľkých vlastností nového systému Kyberia r3, na ktorom sa v posledných týždňoch začína pracovať.
Sociálne siete ako také využívajú napríklad aj systémy Last.fm, Flickr, prípadne najznámejšia sociálna sieť MySpace.