Browse Source

Add new login screen to fix branch due to error log flood issue

This fix has been fast tracked to ship with v1.2.1 due to an issue where entry to the login screen causes high CPU load and spamming in the error log due to an error in 2FA checks. Login screen has been redesigned as a multi-step process (Username > Password > 2FA Token) to better validate entry.
Kristan Kenney 5 years ago
parent
commit
7a296d519a

+ 74 - 70
web/login/index.php

@@ -2,18 +2,18 @@
 
 define('NO_AUTH_REQUIRED',true);
 
-
 // Main include
 include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
 
-
-$TAB = 'LOGIN';
+$TAB = 'login';
 
 // Logout
 if (isset($_GET['logout'])) {
     session_destroy();
 }
 
+
+
 // Login as someone else
 if (isset($_SESSION['user'])) {
     if ($_SESSION['user'] == 'admin' && !empty($_GET['loginas'])) {
@@ -33,27 +33,25 @@ if (isset($_SESSION['user'])) {
     exit;
 }
 
-// Basic auth
-if (isset($_POST['user']) && isset($_POST['password'])) {
+function authenticate_user(){
     if(isset($_SESSION['token']) && isset($_POST['token']) && $_POST['token'] == $_SESSION['token']) {
-        $v_user = escapeshellarg($_POST['user']);
-        $v_ip = escapeshellarg($_SERVER['REMOTE_ADDR']);
-        if(isset($_SERVER['HTTP_CF_CONNECTING_IP'])){
-            if(!empty($_SERVER['HTTP_CF_CONNECTING_IP'])){
-                $v_ip = escapeshellarg($_SERVER['HTTP_CF_CONNECTING_IP']);
-            }
+    $v_user = escapeshellarg($_POST['user']);
+    $v_ip = escapeshellarg($_SERVER['REMOTE_ADDR']);
+    if(isset($_SERVER['HTTP_CF_CONNECTING_IP'])){
+        if(!empty($_SERVER['HTTP_CF_CONNECTING_IP'])){
+            $v_ip = escapeshellarg($_SERVER['HTTP_CF_CONNECTING_IP']);
         }
-        if (isset($_POST['twofa'])) {
-            $v_twofa = escapeshellarg($_POST['twofa']);
-        }
-
-        // Get user's salt
-        $output = '';
-        exec (HESTIA_CMD."v-get-user-salt ".$v_user." ".$v_ip." json" , $output, $return_var);
-        $pam = json_decode(implode('', $output), true);
-        if ( $return_var > 0 ) {
-            sleep(5);
-            $ERROR = "<a class=\"error\">".__('Invalid username or password')."</a>";
+    } 
+     // Get user's salt
+    $output = '';
+    exec (HESTIA_CMD."v-get-user-salt ".$v_user." ".$v_ip." json" , $output, $return_var);
+    $pam = json_decode(implode('', $output), true);
+    if ( $return_var > 0 ) {
+        sleep(2);
+        unset($_POST['password']);
+        unset($_POST['user']);
+        $error = "<a class=\"error\">".__('Invalid username or password')."</a>";
+        return $error;
         } else {
             $user = $_POST['user'];
             $password = $_POST['password'];
@@ -86,8 +84,10 @@ if (isset($_POST['user']) && isset($_POST['password'])) {
 
             // Check API answer
             if ( $return_var > 0 ) {
-                sleep(5);
-                $ERROR = "<a class=\"error\">".__('Invalid username or password')."</a>";
+                sleep(2);
+                unset($_POST['password']);
+                $error = "<a class=\"error\">".__('Invalid username or password')."</a>";
+                return $error;
             } else {
 
                 // Make root admin user
@@ -99,64 +99,60 @@ if (isset($_POST['user']) && isset($_POST['password'])) {
 
                 // Check if 2FA is active
                 if ($data[$_POST['user']]['TWOFA'] != '') {
-                    if (isset($v_twofa)){
-                        $v_twofa = str_replace(' ', '', $v_twofa);
+                   if (empty($_POST['twofa'])){
+                       return false;
+                   }else{
+                        $v_twofa = $_POST['twofa'];
                         exec(HESTIA_CMD ."v-check-user-2fa ".$v_user." ".$v_twofa, $output, $return_var);
                         unset($output);
                         if ( $return_var > 0 ) {
-                            sleep(1);
-                            $ERROR = "<a class=\"error\">".__('Invalid or missing 2FA token')."</a>";
+                            sleep(2);
+                            $error = "<a class=\"error\">".__('Invalid or missing 2FA token')."</a>";
+                            return $error;
+                            unset($_POST['twofa']);
                         }
-                    } else {
-                        sleep(1);
-                        $ERROR = "<a class=\"error\">".__('Invalid or missing 2FA token')."</a>";
-                    }
+                   }
+                }
+                // Define session user
+                $_SESSION['user'] = key($data);
+                $v_user = $_SESSION['user'];
+
+                // Define language
+                $output = '';
+                exec (HESTIA_CMD."v-list-sys-languages json", $output, $return_var);
+                $languages = json_decode(implode('', $output), true);
+                if (in_array($data[$v_user]['LANGUAGE'], $languages)){
+                    $_SESSION['language'] = $data[$v_user]['LANGUAGE'];
+                } else {
+                    $_SESSION['language'] = 'en';
                 }
 
-                // Check if 2FA was successfully
-                if ( ! isset($v_twofa) || $ERROR == '' ) {
-                    // Define session user
-                    $_SESSION['user'] = key($data);
-                    $v_user = $_SESSION['user'];
-
-                    // Get user favorites
-                    get_favourites();
-
-                    // Define language
-                    $output = '';
-                    exec (HESTIA_CMD."v-list-sys-languages json", $output, $return_var);
-                    $languages = json_decode(implode('', $output), true);
-                    if (in_array($data[$v_user]['LANGUAGE'], $languages)){
-                        $_SESSION['language'] = $data[$v_user]['LANGUAGE'];
-                    } else {
-                        $_SESSION['language'] = 'en';
-                    }
-
-                    // Regenerate session id to prevent session fixation
-                    session_regenerate_id();
-
-                    // Redirect request to control panel interface
-                    if (!empty($_SESSION['request_uri'])) {
-                        header("Location: ".$_SESSION['request_uri']);
-                        unset($_SESSION['request_uri']);
-                        exit;
+                // Regenerate session id to prevent session fixation
+                session_regenerate_id();
+
+                // Redirect request to control panel interface
+                if (!empty($_SESSION['request_uri'])) {
+                    header("Location: ".$_SESSION['request_uri']);
+                    unset($_SESSION['request_uri']);
+                    exit;
+                } else {
+                    if ($v_user == 'admin') {
+                        header("Location: /list/user/");
                     } else {
-                        if ($v_user == 'admin') {
-                            header("Location: /list/user/");
-                        } else {
-                            header("Location: /list/web/");
-                        }
-                        exit;
+                        header("Location: /list/web/");
                     }
+                    exit;
                 }
             }
         }
-    } else {
-        sleep(1);
-        $ERROR = "<a class=\"error\">".__('Invalid or missing token')."</a>";
     }
 }
 
+if (!empty($_POST['user']) && !empty($_POST['password']) && !empty($_POST['twofa'])){
+    $error = authenticate_user(); 
+} else if (!empty($_POST['user']) && !empty($_POST['password'])) {
+    $error = authenticate_user();    
+}
 // Check system configuration
 load_hestia_config();
 
@@ -180,7 +176,15 @@ if (empty($_SESSION['language'])) {
 
 // Generate CSRF token
 $_SESSION['token'] = md5(uniqid(mt_rand(), true));
-
 require_once($_SERVER['DOCUMENT_ROOT'].'/inc/i18n/'.$_SESSION['language'].'.php');
 require_once('../templates/header.html');
-require_once('../templates/login.html');
+if (empty($_POST['user'])) {
+    require_once('../templates/login.html');
+}else if (empty($_POST['password'])) {
+    require_once('../templates/login_1.html');
+}else if (empty($_POST['twofa'])) {
+    require_once('../templates/login_2.html');    
+} else {
+    require_once('../templates/login.html');
+}
+?>

+ 8 - 55
web/templates/login.html

@@ -17,52 +17,22 @@
                                             </td>
                                         </tr>
                                         <tr>
-                                            <td style="padding: 12px 0 0 2px;">
+                                            <td style="padding: 12px 0 5px 2px;">
                                                 <?php print __('Username');?>
                                             </td>
                                         </tr>
                                         <tr>
                                             <td>
-                                                <input tabindex="1" type="text" size="20px" style="width:240px;" name="user" class="vst-input">
+                                                <input tabindex="1" type="text" size="20px" style="width:240px;" name="user" class="vst-input" autofocus />
                                             </td>
                                         </tr>
                                         <tr>
-                                            <td style="padding: 12px 0 0 2px;">
-                                                <?php print __('Password');?>
-                                                <div style="padding:0 6px 0px 14px; float:right;">
-                                                    <a tabindex="5" class="vst-advanced" href="/reset/">
-                                                        <?php print __('forgot password');?>
-                                                    </a>
-                                                </div>
+                                            <td height="10px">
                                             </td>
                                         </tr>
                                         <tr>
-                                            <td>
-                                                <input tabindex="2" type="password" size="20px"  style="width:240px;" name="password" class="vst-input">
-                                            </td>
-                                        </tr>
-                                        <tr class="twofa" style="display:none;">
-                                            <td style="padding-top: 12px; padding-left:2px;">
-                                                <?php print __('2FA Token');?>
-                                                <div style="padding:0 6px 0px 14px; float:right;">
-                                                    <a tabindex="5" class="vst-advanced" href="/reset2fa/">
-                                                        <?php print __('Forgot token');?>
-                                                    </a>
-                                                </div>
-                                            </td>
-                                        </tr>
-                                        <tr class="twofa" style="display:none;">
-                                            <td>
-                                                <input tabindex="3" type="text" size="20px" style="width:240px;" name="twofa" class="vst-input">
-                                            </td>
-                                        </tr>
-                                        <tr>
-                                            <td height="28px">
-                                            </td>
-                                        </tr>
-                                        <tr>
-                                            <td style="padding: 0 0 12px 0;">
-                                                    <button tabindex="3" type="submit" class="button"><?php print __('Log in');?>&nbsp;&nbsp;&nbsp;<i class="fas fa-sign-in-alt"></i></button>
+                                            <td style="padding: 0 0 5px 0;">
+                                                <button tabindex="3" type="submit" class="button"><?php print __('Next');?>&nbsp;&nbsp;&nbsp;<i class="fas fa-sign-in-alt"></i></button>
                                             </td>
                                         </tr>
                                     </table>
@@ -72,7 +42,7 @@
                         <tr>
                             <td colspan=2>
                                 <div class="login-bottom">
-                                    <div style="height:20px"><?php if (isset($ERROR)) echo $ERROR ?></div>
+                                    <div style="height:20px"><?php if (isset($error)) echo $error ?></div>
                                 </div>
                             </td>
                         </tr>
@@ -80,23 +50,6 @@
                 </tr>
             </table>
         </center>
-        <script type="text/javascript">
-            $(document).ready(function () {
-                $('#form_login').on('input', 'input[name="user"]', function() {
-                    var username = this.value;
-                    $.ajax({
-                        type: 'GET',
-                        url: '/inc/2fa/active.php?user=' + username,
-                        complete: function(xhr) {
-                            if(xhr.status == '200'){
-                                $('.twofa').show();
-                            }else if(xhr.status == '404'){
-                                $('.twofa').hide();
-                            }
-                        }
-                    });
-                });
-            });
-        </script>
+
     </body>
-</html>
+</html>

+ 62 - 0
web/templates/login_1.html

@@ -0,0 +1,62 @@
+        <center>
+            <table class="login">
+                <tr>
+                    <td>
+                        <table>
+                            <tr>
+                                <td style="padding: 22px 30px 0 42px; height: 280px; width: 170px;">
+                                    <a href="/"><img border=0 src="/images/logo.png" alt="<?=__('Hestia Control Panel');?>" style="margin: 20px; margin-top: 64px;" /></a>
+                                </td>
+                                <td style="padding: 40px 60px 0 0;" class="animated fadeIn">
+                                    <form method="post" action="/login/" id="form_login">
+                                    <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
+                                    <input type="hidden" name="user" value="<?php echo $_POST['user']; ?>">
+                                    
+                                    <table class="login-box">
+                                        <tr>
+                                            <td style="padding: 12px 0 0 2px;" class="login-welcome">
+                                                <?php print __('Welcome');?> <?php echo $_POST['user']; ?>!
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                           <td style="padding: 12px 0 0 2px;">
+                                                <?php print __('Password');?>
+                                                <div style="padding:0 6px 0px 14px; float:right;">
+                                                    <a tabindex="5" class="vst-advanced" href="/reset/">
+                                                        <?php print __('forgot password');?>
+                                                    </a>
+                                                </div>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td>
+                                                <input tabindex="2" type="password" size="20px"  style="width:240px;" name="password" class="vst-input" autofocus />
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td height="10px">
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td style="padding: 0 0 5px 0;">
+                                                <button tabindex="3" type="submit" class="button"><?php print __('Login');?>&nbsp;&nbsp;&nbsp;<i class="fas fa-sign-in-alt"></i></button>&nbsp;&nbsp;
+                                                <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </form>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td colspan=2>
+                                <div class="login-bottom">
+                                    <div style="height:20px"><?php if (isset($ERROR)) echo $ERROR ?></div>
+                                </div>
+                            </td>
+                        </tr>
+                    </table>
+                </tr>
+            </table>
+        </center>
+    </body>
+</html>

+ 61 - 0
web/templates/login_2.html

@@ -0,0 +1,61 @@
+        <center>
+            <table class="login">
+                <tr>
+                    <td>
+                        <table>
+                            <tr>
+                                <td style="padding: 22px 30px 0 42px; height: 280px; width: 170px;">
+                                    <a href="/"><img border=0 src="/images/logo.png" alt="<?=__('Hestia Control Panel');?>" style="margin: 20px; margin-top: 64px;" /></a>
+                                </td>
+                                <td style="padding: 40px 60px 0 0;" class="animated fadeIn">
+                                    <form method="post" action="/login/" id="form_login">
+                                    <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
+                                    <input type="hidden" name="user" value="<?php echo $_POST['user']; ?>">
+                                    <input type="hidden" name="password" value="<?php echo $_POST['password']; ?>">
+                                    <table class="login-box">
+                                        <tr>
+                                            <td style="padding: 12px 0 0 2px;" class="login-welcome">
+                                                <?php print __('2 Factor Authentication');?>
+                                            </td>
+                                        </tr>
+                                        <tr class="twofa">
+                                            <td style="padding-top: 12px; padding-left:2px;">
+                                                <?php print __('2FA Token');?>
+                                                <div style="padding:0 6px 0px 14px; float:right;">
+                                                    <a tabindex="5" class="vst-advanced" href="/reset2fa/">
+                                                        <?php print __('Forgot token');?>
+                                                    </a>
+                                                </div>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td>
+                                                <input tabindex="2" type="" size="20px"  style="width:240px;" name="twofa" class="vst-input" autofocus />
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td height="10px">
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td style="padding: 0 0 5px 0;">
+                                                <button tabindex="3" type="submit" class="button"><?php print __('Login');?>&nbsp;&nbsp;&nbsp;<i class="fas fa-sign-in-alt"></i></button>
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </form>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td colspan=2>
+                                <div class="login-bottom">
+                                    <div style="height:20px"><?php if (isset($ERROR)) echo $ERROR ?></div>
+                                </div>
+                            </td>
+                        </tr>
+                    </table>
+                </tr>
+            </table>
+        </center>
+    </body>
+</html>

+ 2 - 2
web/templates/reset2fa.html

@@ -56,8 +56,8 @@
                                             </tr>
                                             <tr>
                                                 <td style="padding: 20px 0 12px 0;">
-                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">&nbsp;&nbsp;
-                                                    <input tabindex="2" type="submit" value="<?php print __('Submit');?>" class="button">
+                                                    <input tabindex="2" type="submit" value="<?php print __('Submit');?>" class="button">&nbsp;&nbsp;
+                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">
                                                 </td>
                                             </tr>
                                         </table>

+ 2 - 2
web/templates/reset_1.html

@@ -42,8 +42,8 @@
                                             </tr>
                                             <tr>
                                                 <td style="padding: 20px 0 12px 0;">
-                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">&nbsp;&nbsp;
-                                                    <input tabindex="2" type="submit" value="<?php print __('Submit');?>" class="button">
+                                                    <input tabindex="2" type="submit" value="<?php print __('Submit');?>" class="button">&nbsp;&nbsp;
+                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">
                                                 </td>
                                             </tr>
                                         </table>

+ 2 - 2
web/templates/reset_2.html

@@ -32,8 +32,8 @@
                                             </tr>
                                             <tr>
                                                 <td style="padding: 20px 0 12px 0;">
-                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/reset/'">&nbsp;&nbsp;
-                                                    <input tabindex="2" type="submit" value="<?php print __('Confirm');?>" class="button">
+                                                    <input tabindex="2" type="submit" value="<?php print __('Confirm');?>" class="button">&nbsp;&nbsp;
+                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/reset/'">
                                                 </td>
                                             </tr>
                                         </table>

+ 2 - 2
web/templates/reset_3.html

@@ -40,8 +40,8 @@
                                             </tr>
                                             <tr>
                                                 <td style="padding: 20px 0 12px 0;">
-                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">&nbsp;&nbsp;
-                                                    <input tabindex="3" type="submit" value="<?php print __('Reset');?>" class="button">
+                                                    <input tabindex="3" type="submit" value="<?php print __('Reset');?>" class="button">&nbsp;&nbsp;
+                                                    <input type="button" class="button cancel" value="<?php print __('Back');?>" onclick="location.href='/login/'">
                                                 </td>
                                             </tr>
                                         </table>