Neuigkeiten:

moziloCMS verwendet Cookies. Wenn Sie auf unserer Seite weitersurfen, stimmen Sie der Cookie-Nutzung zu Datenschutzerklärung
moziloCMS Layouts
moziloCMS Plugins

Hauptmenü

Mozilo Sicherheitsproblem

Begonnen von MarcAurel, 17. März 2016, 20:43:20

« vorheriges - nächstes »

MarcAurel

Bei einigen Test ist mir ein Sicherheitsaspekt aufgefallen, das vielleicht anderen entgangen ist.
Mozilo sendet das Passwort bei der Anmeldung offen über das Internet im Klartext.

Das Problem ist , meiner Meinung nach groß, aber lässt sich einfach beheben.
Hier der Auszug aus einem kleinen Sniffer :

POST /admin/index.php HTTP/1.1
Host: publius.lima-city.de
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0
bytes: 40
bytes: 796
POST /admin/index.php HTTP/1.1
Host: publius.lima-city.de
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://publius.lima-city.de/admin/index.php?logout=true
Cookie: mozilo_editor_settings=true,false,mozilo,12px; _lcp=a; SimpleCounter=01d7d5bb5ea52904e05b8775c9ab32ab; _lcp2=a; _lcp3=a; LCWSID=a359817cd8eaefec5d7fb166b2ca29a7; MOZILOID_99f1e189003a0d35c2593b575137008b=fb1e0e30b65c201531a3a1a2510a8513
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 48

username=MarcAurel&password=MarcAurel&login=Login - 796
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 40
bytes: 694
POST /admin/mod_rewrite_t_e_s_t.html HTTP/1.1
Host: publius.lima-city.de
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html, */*; q=0.01
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
X-Requested-With: XMLHttpRequest
Referer: http://publius.lima-city.de/admin/index.php
Cookie: mozilo_editor_settings=true,false,mozilo,12px; _lcp=a; SimpleCounter=01d7d5bb5ea52904e05b8775c9ab32ab; _lcp2=a; _lcp3=a; LCWSID=a359817cd8eaefec5d7fb166b2ca29a7; MOZILOID_99f1e189003a0d35c2593b575137008b=fb1e0e30b65c201531a3a1a2510a8513
Connection: keep-alive
Content-Length: 0

- 694
bytes: 40
bytes: 93
bytes: 40


Natürlich sind Username und Passwort von mir editiert worden, aber im Original stand genauso im Klartext.

Ich habe gesehen dass intern die Passwörter mit MD5 gehascht werden.

MD5 und SH1 sin längst geknackt worden, im Internet gibt es lookup tables  für sämtliche  mögliche Kombinationen, die ein passendes Passwort liefern. Allerdings hilft die interne Verschlüsselung wenig, wenn die Passwörter offen über das Netz gesendet werden.
Es sollte ein SHA2 eingesetzt werden z.B SHA 256 um die Passwörter vor dem Senden zu verschlüsseln.
Wenn man mir genau sagt wo die Schnittstelle in JavaScript-Code ist, kann ich es selber einfügen und hier die Lösung präsentieren, oder ich kann die entsprechenden JavaScript Funktionen für SHA 256 um das Problem zu beheben liefern.

Gruß



Paul

Ich finde, dass man die Hinweise von @MarcAurel ernst nehmen sollte. Eine spezielle Frage habe ich aber noch an MarcAurel:  Kann man das Passwort bei Nutzung von SSL (also https://, geht ja bei Lima-City auch) das Passwort ähnlich leicht mit einem Sniffer auslesen?
Website: BPGS.DE

MarcAurel

Zitat von: Paul am 20. März 2016, 15:17:28
  Kann man das Passwort bei Nutzung von SSL (also https://, geht ja bei Lima-City auch) das Passwort ähnlich leicht mit einem Sniffer auslesen?

Bei SSL nein.

Ich habe gerade das AccesControl angepasst wie oben beschrieben und es  funktioniert.
Ich werde demnächst auch das Admin-Modul anpassen und  die Lösung(en) hier präsentieren.


hausl78

Seiten ohne SSL werden es bald schwer haben, hab ich letztens erst gelesen..  Die Bowserhersteller haben schon Pläne, Seiten ohne SSL "rot" anzuzeigen. http://t3n.de/news/https-google-markiert-bald-alle-675146/

Dazu noch - also Info:
ZitatEs sollte ein SHA2 eingesetzt werden
http://php.net/manual/de/faq.passwords.php

laborix

Zitat von: MarcAurel am 17. März 2016, 20:43:20... Das Problem ist , meiner Meinung nach groß, aber lässt sich einfach beheben. ...
Das Passwort wird bei vielen anderen CMS System ebenfalls im Klartext übertragen. Das sichere Übertragen funktioniert nur mit einem HTTPS-Formular oder diversen Lösungen per Javascript Libraries.

Bei großen Onlineshops oder großen Internet Communities ist das Anmelden schon lange nur noch per HTTPS möglich. Solange der normale Privat-Kunde beim Erwerb eines Webspaces das HTTPS/SSL extra bezahlen muss wird das Passwort bei vielen CMS Systemen weiterhin ohne Verschlüsselung verschickt.


MarcAurel

#5
Zitat von: laborix am 22. März 2016, 18:45:02
Das Passwort wird bei vielen anderen CMS System ebenfalls im Klartext übertragen.

Ist das ein Grund um über eine Sicherheitslücke in Mozilo hinweg zu sehen?

Wobei es lässt sich relativ einfach beheben.
Statt das Passwort im Klartext zu senden, kann  dies vorher client side per  Jacascript mit einem mindestens SHA 256 gehasht werden und so gesendet werden.

Meines Wissens nach SHA2 ist sicher , für ein Passwort mit einer mindestlänge von 8 Charakteren.

Wozu bemüht man sich das Passwort in der Datenbank zu  verschlüsseln wenn sowieso bei jedem Einloggen im Klartext zum Server gesendet wird?



Zitat von: laborix am 22. März 2016, 18:45:02
oder diversen Lösungen per Javascript Libraries.


Es sind nur 3 kleine Funktionen  die man ohne weiteres in Php-Script einfügen kann. Ich habe mich angeboten die Lösung zu liefern wenn Interessen vorhanden sind.
:)

laborix

Zitat von: MarcAurel am 22. März 2016, 19:08:26Meines Wissens nach SHA2 ist sicher , für ein Passwort mit einer mindestlänge von 8 Charakteren.
Was bringt eine Verschlüsselung wenn ein Passwort verwendet wird, das auf SHA-x-Listen schon zur Verfügung steht?

[ot]
Abgesehen davon, um das Passwort auszulesen, muss man den Traffic mitschneiden. Geht in vielen Firmen mittels Proxy oder ähnlichen Produkten. Bei Privatpersonen im WLAN per Backdoor Trojaner oder allen die das WLAN Passwort kennen. Man könnte aber auch die Straße aufreißen und dort die Leitung anzwacken, oder über dem Ärmelkanal die großen Jungs fragen.

Ich frage mich oft warum sich jemand darüber Gedanken macht, aber auf dem Handy G..gle oder anderen Apps vollen Zugriff auf alles gibt? Dann spielt Klartext eine Rolle. Aber dafür interessiert sich niemand.
[/ot]

Nicht böse sein, aber in dem Fall wenn HTTPS zum Standard wird, gibt es mit Sicherheit wieder eine Möglichkeit Passwörter mitzuschneiden.

MarcAurel

Zitat von: laborix am 22. März 2016, 19:34:03

Was bringt eine Verschlüsselung wenn ein Passwort verwendet wird, das auf SHA-x-Listen schon zur Verfügung steht?

Ich sagte bereits am Anfang, für MD5 SHA1 gibt es komplette lookup tables, für SHA2 nicht, es ist sicher.

MarcAurel

Hallo Leute hier ist die Lösung "ready to use" eingefügt in AccesControl.
Es funktioniert mit oder ohne JavaScript, natürlich dann ohne Verschlüsselung.

function get_login($horizontal = false) {
        if(AC_LOGGED_USER !== false)
            return "";

        $css_horizontal = "";
        $tmpl = '{ERROR}<ul>'
            .'<li>{USER_TEXT}<br />{INPUT_USER}</li>'
            .'<li>{PW_TEXT}<br />{INPUT_PW}</li>'
            .'<li>{BUTTON}</li>'
            .'</ul>';
        if($horizontal) {
            $css_horizontal = " ac-login-horizontal";
            $tmpl = '{ERROR}<ul>'
                .'<li>{USER_PW_TEXT}</li>'
                .'<li>{INPUT_USER}{INPUT_PW}{BUTTON}</li>'
                .'</ul>';
        }
        if(!$horizontal and strlen($this->settings->get('login_config')) > 7)
            $tmpl = $this->settings->get('login_config');
        elseif($horizontal and strlen($this->settings->get('login_config_horizontal')) > 7)
            $tmpl = $this->settings->get('login_config_horizontal');
        $tmpl_error = "";
        if($_SESSION['AC_LOGIN_STATUS'] == 'login_error') {
            $error_text = $this->cms_lang->getLanguageValue("login_errorcheck");
            if(strlen($this->settings->get('login_user_error')) > 7)
                $error_text = $this->settings->get('login_user_error');
                $tmpl_error = '<div class="ac-login-error">'.$error_text.'</div>';
        }
        $_SESSION['AC_LOGIN_STATUS'] = false;
   
         
         $form ='<noscript> <div class="ac-login-error">login not secure</div></noscript>'
         .'<form accept-charset="'.CHARSET.'" method="post" action="'.$this->current_url.'">'
         .'<input id="ac_password_hash" type="hidden" name="ac_password_hash" value="" />'
            .str_replace(array("{USER_TEXT}","{PW_TEXT}","{USER_PW_TEXT}","{INPUT_USER}","{INPUT_PW}","{BUTTON}","{ERROR}"),
                array($this->cms_lang->getLanguageValue("user"),
                    $this->cms_lang->getLanguageValue("pw"),
                    $this->cms_lang->getLanguageValue("user_pw_horizontal"),
                    '<input type="text" name="ac_user" value="" />',
                    '<input id="ac_password" type="password" name="ac_password" value="" />',               
                    '<input onclick="GetHash()" type="submit" value="'.$this->cms_lang->getLanguageValue("login").'" />',
                    $tmpl_error
                ),
            $tmpl)
            .'<input type="hidden" name="ac_action" value="login" /></form>';
        return '<div class="ac-user-login'.$css_horizontal.'">'.$form.'</div>' . $this->getJavaScriptForHash();
    }

function getJavaScriptForHash(){
      $script = '<script type="text/javascript">'
      .'var password = document.getElementById("ac_password");'
      .'var passwordHasch = document.getElementById("ac_password_hash");'
      .'function GetHash() {'
      .'passwordHasch.value = SHA256(password.value);'
      .'password.value = passwordHasch.value;'       
      .'}'
      .'function SHA256(s){'
      .'    var chrsz   = 8;'
      .'    var hexcase = 0;'
      .'    function safe_add (x, y) {'
      .'        var lsw = (x & 0xFFFF) + (y & 0xFFFF);'
      .'        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);'
      .'        return (msw << 16) | (lsw & 0xFFFF);'
      .'    }'
      .'    function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }'
      .'    function R (X, n) { return ( X >>> n ); }'
      .'    function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }'
      .'    function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }'
      .'    function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }'
      .'    function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }'
      .'    function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }'
      .'    function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }'
      .'    function core_sha256 (m, l) {'
      .'        var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2);'
      .'        var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);'
      .'        var W = new Array(64);'
      .'        var a, b, c, d, e, f, g, h, i, j;'
      .'        var T1, T2;'
      .'        m[l >> 5] |= 0x80 << (24 - l % 32);'
      .'        m[((l + 64 >> 9) << 4) + 15] = l;'
      .'        for ( var i = 0; i<m.length; i+=16 ) {'
      .'            a = HASH[0];'
      .'            b = HASH[1];'
      .'            c = HASH[2];'
      .'            d = HASH[3];'
      .'            e = HASH[4];'
      .'            f = HASH[5];'
      .'            g = HASH[6];'
      .'            h = HASH[7];'
      .'            for ( var j = 0; j<64; j++) {'
      .'                if (j < 16) W[j] = m[j + i];'
      .'                else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);'
      .'                T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);'
      .'                T2 = safe_add(Sigma0256(a), Maj(a, b, c));'
      .'                h = g;'
      .'                g = f;'
      .'                f = e;'
      .'                e = safe_add(d, T1);'
      .'                d = c;'
      .'                c = b;'
      .'                b = a;'
      .'                a = safe_add(T1, T2);'
      .'            }'
      .'            HASH[0] = safe_add(a, HASH[0]);'
      .'            HASH[1] = safe_add(b, HASH[1]);'
      .'            HASH[2] = safe_add(c, HASH[2]);'
      .'            HASH[3] = safe_add(d, HASH[3]);'
      .'            HASH[4] = safe_add(e, HASH[4]);'
      .'            HASH[5] = safe_add(f, HASH[5]);'
      .'            HASH[6] = safe_add(g, HASH[6]);'
      .'            HASH[7] = safe_add(h, HASH[7]);'
      .'        }'
      .'        return HASH;'
      .'    }'
      .'    function str2binb (str) {'
      .'        var bin = Array();'
      .'        var mask = (1 << chrsz) - 1;'
      .'        for(var i = 0; i < str.length * chrsz; i += chrsz) {'
      .'            bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);'
      .'        }'
      .'        return bin;'
      .'    }'
      .'    function Utf8Encode(string) {'
      .'        string = string.replace(/\r\n/g,"\n");'
      .'        var utftext = "";'
      .'        for (var n = 0; n < string.length; n++) {'
      .'            var c = string.charCodeAt(n);'
      .'            if (c < 128) {'
      .'                utftext += String.fromCharCode(c);'
      .'            }'
      .'            else if((c > 127) && (c < 2048)) {'
      .'                utftext += String.fromCharCode((c >> 6) | 192);'
      .'                utftext += String.fromCharCode((c & 63) | 128);'
      .'            }'
      .'            else {'
      .'                utftext += String.fromCharCode((c >> 12) | 224);'
      .'                utftext += String.fromCharCode(((c >> 6) & 63) | 128);'
      .'                utftext += String.fromCharCode((c & 63) | 128);'
      .'            }'
      .'        }'
      .'        return utftext;'
      .'    }'
      .'    function binb2hex (binarray) {'
      .'        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";'
      .'        var str = "";'
      .'        for(var i = 0; i < binarray.length * 4; i++) {'
      .'            str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +'
      .'            hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);'
      .'        }'
      .'        return str;'
      .'    }'
      .'    s = Utf8Encode(s);'
      .'    return binb2hex(core_sha256(str2binb(s), s.length * chrsz));'
      .'}'
      .'</script>';
      return $script;
   }

  function check_login() {
        # Plugin wurde schonnmal aufgerufen
        if(defined('AC_LOGGED_USER'))
            return;
        $action = getRequestValue("ac_action","post",false);
        # Prüfen, ob action=login oder action=logout.
        if(!empty($action)) {
            $user = getRequestValue("ac_user","post",false);
            $pw = getRequestValue("ac_password","post",false);
         $pwh = getRequestValue("ac_password_hash","post",false);         
            if($action == "login" and !empty($user) and !empty($pw)) {
                $_SESSION['AC_LOGIN_STATUS'] = 'login_error';
            
            if ($pwh != ""){
               if($this->checkLoginDataJavascript($user, $pwh)) {
                  $_SESSION['AC_LOGGED_USER_IN'] = $user;
                  $_SESSION['AC_LOGGED_USER_TIMEOUT'] = time() + $this->ac_users[$user][1];
                  $_SESSION['AC_LOGIN_STATUS'] = 'login_ok';
               }
            }
            else{
               if($this->checkLoginData($user, $pw)) {
                  $_SESSION['AC_LOGGED_USER_IN'] = $user;
                  $_SESSION['AC_LOGGED_USER_TIMEOUT'] = time() + $this->ac_users[$user][1];
                  $_SESSION['AC_LOGIN_STATUS'] = 'login_ok';
               }
            }

....


  protected function checkLoginData($user, $pass) {
        // if(isset($this->ac_users[$user]) and (true === $this->hasher->CheckPassword($pass,$this->ac_users[$user][0]))) {
            // return true;
        // }
      if(isset($this->ac_users[$user]) and (hash('sha256', $pass) == $this->ac_users[$user][0])) {
            return true;
        }
        return false;
    }
   
    protected function checkLoginDataJavascript($user, $hash) {      
        if(isset($this->ac_users[$user]) and ($hash == $this->ac_users[$user][0])) {
            return true;
        }
        return false;
    }

MarcAurel

Zu meinem ,,Verbesserungsvorschlag"  zur Sicherheit  von Mozilo von vorhin, um eine kleine Datenklau-Paranoia weiter zu spinnen, man könnte noch  zu dem Anmeldeformular (Passworteingabe) auch ein Javascript-Virtual-Keyboard anbieten, um eventuelle Keylogger zu verhindern dass Anmelde-Daten ablesen und weiter senden. Etwas wie das hier.

Der Sniffer  in einem früheren Posten erwähnt, genauso wie ein  Keylogger  die nicht von Antivirus-Software erfasst werden können, sind relativ einfach zu erstellenden Programme wenn man weißt wie und weiter verbreitet als man vermutet.
Ich war selbst oft angewiesen an Internet aus den Internet-Cafes , Hotels und fremden Firmen-Computer von fremden  Firmen auch im Ausland. Ein sichereres Werkzeug   zu meinen Daten wäre mir lieber gewesen.

Ich habe noch ein paar Ideen aber...  :)


MarcAurel

Zitat von: hausl78 am 22. März 2016, 17:04:37
Seiten ohne SSL werden es bald schwer haben, hab ich letztens erst gelesen..  Die Bowserhersteller haben schon Pläne, Seiten ohne SSL "rot" anzuzeigen.

Vor einem halben Jahr schrieb Stefan hier, dass Mozilo  jetzt auch SSL kann und auf einmal soll es nicht mehr ohne SSL weiter gehen?
Ich befürchte dass dieses "bald" noch einigen Jahren dauern wird.

Eine Lösung für Mozilo um eine schnelle Verschlüsselung für jedermann anzubieten, sehr einfach zu implementieren und kostenlos für den privaten Bereich findet man hier.

laborix

Zitat von: MarcAurel am 23. März 2016, 21:56:32...Vor einem halben Jahr schrieb Stefan hier, dass Mozilo  jetzt auch SSL kann und auf einmal soll es nicht mehr ohne SSL weiter gehen? ...
SSL funktioniert in moziloCMS 2.0 wenn auf dem Webspace SSL aktiviert ist.

Mehr als 75% aller Privatnutzer haben SSL nicht in ihrem Webspace Vertrag. Um SSL auf dem Webspace nutzen zu können muss das extra für mehr Geld erworben werden.

laborix

Zitat von: MarcAurel am 23. März 2016, 20:03:46... Ich habe noch ein paar Ideen aber...
Nur eine kurze Frage:
Warum hast du dein eigenes CMS aufgegeben wenn alles so einfach mit ein paar Ideen umsetzbar ist?

MarcAurel

Zitat von: laborix am 25. März 2016, 10:04:19
Nur eine kurze Frage:
Warum hast du dein eigenes CMS aufgegeben wenn alles so einfach mit ein paar Ideen umsetzbar ist?

Die Antwort ist relativ einfach, es war veraltet und nicht z.B. wie Mozilo durch Plugins erweiterbar.
Zufällig habe ich Mozilo entdeckt und entspricht mit kleinen Ausnahmen die ich hier erwähnt habe (und auch behoben) ganz meinen Erwartungen.

Und die hier gefunden Plugins sind  auch sehr interessant und erweiterbar.

Ich bin aber hergekommen nicht nur um zu nehmen sondern auch zu geben, wenn ich es auch kann.
Ist das nicht erwünscht?


laborix

ZitatZitat auf der mozilo.de Startseite

moziloCMS ist ein einfaches und übersichtliches Content-Management-System (CMS). Es richtet sich vor allem an Benutzer mit geringen HTML-Kenntnissen und besticht durch seine einsteigerfreundliche Bedienung.

moziloCMS ist eine kleine Community, hier geht das nicht so hoppla hopp.