socket-io und Authentifizierung per handshake-Daten?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • socket-io und Authentifizierung per handshake-Daten?

    Hallo liebes Forum,

    als ich eben googelte fand ich eine Lösung um beim connect mit socket-io direkt eigene Daten anzuhängen:

    JavaScript-Quellcode: user (client.js)

    1. var socket = new io.connect('http://127.0.0.1:8080/global', { query: "myvar=myval" });


    Diese konnte ich dann aufm Server bereits erfolgreich abrufen. Http bzw https sollte nicht groß diskutiert werden, das SSL angewendet wird ist ja Standard =)
    Denn ich würde jetzt gerne wissen wie sicher diese Methode ist würde ich dort direkt übermitteln welche User-ID der Verbindung zugeordnet werden soll (als auch wietere Daten wie Berechtigungen, Name etc).

    Sprich so in etwa:
    query: "uid=1" // die anderen Daten könnte sich der Server dann eig. auch selber aus der Datenbank holen

    Aktuell gehe ich dort nämlich einen Umweg über Memcache(d), da erstelle ich mir mit php die Daten die einer Verbindung zugeordnet werden sollen

    Quellcode

    1. $socketSess = ( $args['memberSession'] ) ? [
    2. 'ip' => Tools::sip(),
    3. // 'ua' => $_SERVER['HTTP_USER_AGENT'],
    4. 'uid' => $_SESSION['member']['id'],
    5. 'pid' => $_SESSION['member']['pid'],
    6. 'admin' => $_SESSION['admin'],
    7. 'name' => $args['auth']->getPersonsNames(),
    8. 'contacts' => $args['auth']->getContactList(),
    9. 'follow' => [], // users and profils how i have a abo
    10. 'followers' => [] // users to follow me
    11. ] : [
    12. 'ip' => Tools::sip(),
    13. 'gid' => str_replace('.', '', microtime(true)).rand(1,100),
    14. // 'ua' => $_SERVER['HTTP_USER_AGENT'],
    15. 'admin' => false,
    16. 'contacts' => [],
    17. 'follow' => [], // users and profils how i have a abo
    18. 'followers' => [] // users to follow me
    19. ];
    Alles anzeigen

    Dies landet in Memcache unter den key 'socket_'.$phpSessionID und über handshake holt sich der server die php-sessionid und holt sich dann die Daten.
    Würde diesen Umweg gerne wieder entfernen, wenn obige Variante sicher ist!

    Ich weiß ja nicht ob Hacker bereits während die Seite aufgebaut wird mit Skripten den quellcode manipulieren können oder bevor die Verbindung hergestellt wird.
    Dann wäre es ja möglich die Daten zu verfälschen die der Verbindung zugewiesen werden sollen.


    Oder ist diese Funktion gar nur dazu gedacht einen Tokken zu übertragen? Dann könnte man hier mit der Datenbank ggf. ein Authsystem schaffen, wobei hier ja eigt. dann auch nur der richtige Tokken benötigt wird um sich eine User-ID zu eigen zu machen.


    MfG: Paykoman

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Paykoman ()

  • Hmmm, also ist es mit meiner Memcache-Lösung durch aus der bessere und sicherere Weg?
    Voraussetzung ist das die PHP-Webseite entsprechend gegen Kookie-Diebstahl abgesichert ist, solange keiner die Session-ID des anderen kennt kann er in Socket auch nicht seine Session übernehmen.

    Ich schlüssel dazu mal mein Vorgehen etwas auf.

    1) User öffnet die Webseite, php erstellt wie oben zusehen entweder ein Gast oder Mitglied Array das in Memcache unter den key 'socket_'.$phpsessionID abgelegt wird.

    2) User verbindet sich mit webSocket, über client.handshake werden die Cookies geladen und aus dem php-session-cookie wird die Session-ID geholt, es wird der Präfix 'socket_' vorangestellt und geschaut ob in Memcache ein entsprechendes Objekt hinterlegt ist. Hier greifen dann diverse Abfragen, für reAuth und expired wenn nötig. Mein Manko ist eben das ich nicht sagen kann ob dem client die session-id auch tatsächlich gehört. Jemand mit Langeweile könnte solange das Kookie manipulieren bis er eine session-ID findet die funktioniert.

    Letztlich sehe ich aber auch keine alternative wie man sowas sicher stellen soll.
    Im Grunde kann man ja auch das php Kookie solange manipulieren bis man eine ID hat die eben funktioniert, oder nicht?

    JavaScript-Quellcode: die app.js

    1. // lobby init
    2. var lobby = new lobby(settings.lobby, db, app); // is schon required
    3. /** Server */
    4. app.of(settings.lobby.nsp).on('connection', function(client){ // run server
    5. /** connection handling */
    6. lobby.onConnect(client, false); // add new socket to lobby, this will authorize with cookie/session-ID
    7. client.on('loggedin', function(){ lobby.onConnect(client, true); }); // this for reAuth (if default auth failed will this be called)
    8. client.on('logout', function(){
    9. console.log('user has clicked to logout');
    10. lobby.deleteSession(client.uid, client.id, 'app');
    11. }); // user has clicked to logout
    12. client.on('disconnect', function(){ lobby.disconnect(client.uid, client.id, client.isMember); });
    13. /** track each call of this user */
    14. var fetchOn = client.on;
    15. client.on = function(name, func){
    16. fetchOn.call(this, name, function(){ // var name can not be changed!!!
    17. // check is session expired
    18. if( lobby.isExpired(client.uid) ){ console.log('expired on fetch calls'); return false; }
    19. // spam check - defined emits will not raise the spameScore
    20. if( lobby.asOpt.freeEmits.indexOf(name) == -1 && lobby.spamProtector(name, ((lobby.asOpt.punishDublicates) === true ? JSON.stringify(arguments) : false), client.uid) === true ){
    21. func.apply(this, arguments);
    22. }else{
    23. func.apply(this, arguments);
    24. }
    25. });
    26. };
    27. });
    Alles anzeigen

    JavaScript-Quellcode: in meiner lobby.js

    1. this.onConnect = function(client, reAuth){
    2. // memcache run aSync so we need a var to call the instance to memcache
    3. this.debug(3, client.id+' is connected');
    4. var findSess = this.getCookie(this.opt.authCookieName, client.handshake.headers.cookie);
    5. this.mem.get('socket_'+findSess, function(error, session) // auth erfolgt via memcache über die abzurufende session
    6. {
    7. client.isMember = false;
    8. if( typeof(error) === "undefined" ) // ist ein memcache error aufgetretten erfolgt kein user.add
    9. {
    10. session = JSON.parse(session);
    11. // The session can be null if the user inactive for long time
    12. if( session !== null ){
    13. if( session.hasOwnProperty('uid') ){
    14. client.isMember = true;
    15. session.uid = parseInt(session.uid);
    16. }else{
    17. session['uid'] = parseInt(session['gid']); // on guests we use generated id
    18. delete(session['gid']);
    19. }
    20. client.isAdmin = false;
    21. that.debug(2, client.id+' have find php session.');
    22. that.verify(client, session, reAuth); // verify() need the reAuth to restore a reAuth-process, is reAuth false the user get expired = false on first connection
    23. }
    24. else
    25. {
    26. /** hier sind entsprechende Abfragen was wie gehändelt wird wenn keine session in memcache gefunden wurde (hier tüfftel ich aber gerade noch dran rum) */
    27. }
    28. }else{
    29. that.debug(2, 'Error on memcache: '+error);
    30. client.emit('auth', {e: 'err', err: 'mem', mem: error});
    31. }
    32. });
    33. };
    Alles anzeigen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Paykoman ()

  • Nun PHP war jetzt lediglich drin damit man nachvollziehen kann woher die Daten stammen die socket lädt.
    Stimmt wo Du es erwähnst, das http-only kookie wollte ich auch noch aktivieren und durch testen, hatte nur gelesen das eben zb. browserseitiges JS dann eben nicht mehr auf die Cookies zugreifen kann aber meine Skripte tun dies gelegentlich da müsste ich erst Umwege über xhr einrichten.
    Interessant wäre zu wissen ob der socket-server denn dann noch per handshake auf die cookies zugreifen kann oder auch nicht mehr?

    Im Grunde spielen eben die Kookies und das der Server aufgrund von Kookies die Session zuweist die Hauptrolle.
    Bin am überlegen hier auf digitalen Fingerprint zu setzten, dieser könnte in Memcache abgelegt werden und wenn dieser nicht übereinstimmt scheitert es.
    Der Fingerprint wird natürlich nur dann in Memcache hinterlegt wenn der tatsächliche User sich über die Webseite (php) einloggt, sprich der User dem man übernehmen möchte, muss oben drein auch noch online sein und der Angreifer hat ja keine Einsicht auf den hinterlegten FP in Memcache.
    Wenn im FP die übliche menge an Daten landet (Browsereinstellungen, OS, installierte Sprachen, Zeitzone, Anzahl CPUs u.s.w.), ist die Chance das der Angreifer einen identischen Fingerprint hat eher gleich null.

    JWT schaue ich mir morgen genauer an, habe aber schon bissl reingeschnuppert und die php-libary angesehen.
    Letztlich muss php dann einen Tokken generieren den der Server entschlüsseln muss, wo ich halt nocht nicht ganz weiß wie sinnig das ist, dem Server muss ja mitgeteilt werden mit welchen Schlüsseln er dies tun kann. Naja vllt. wird es etwas klarer wenn ich morgen die ersten schlüssel generiere und diese dann in ihrem Debugger rein haue.

    Also bis morgen mal,
    Paykoman

    PS: schon mal vielen Dank!