Browse Source

security: prevent same passcode from being reused

Reported by @cezar97.
Unknwon 6 years ago
parent
commit
01ccc2cc96
7 changed files with 145 additions and 115 deletions
  1. 1 0
      conf/locale/locale_en-US.ini
  2. 1 1
      gogs.go
  3. 5 0
      models/user.go
  4. 11 0
      models/user_cache.go
  5. 112 112
      pkg/bindata/bindata.go
  6. 14 1
      routes/user/auth.go
  7. 1 1
      templates/.VERSION

+ 1 - 0
conf/locale/locale_en-US.ini

@@ -351,6 +351,7 @@ two_factor_or_enter_secret = Or enter the secret:
 two_factor_then_enter_passcode = Then enter passcode:
 two_factor_verify = Verify
 two_factor_invalid_passcode = The passcode you entered is not valid, please try again!
+two_factor_reused_passcode = The passcode you entered has already been used, please try another one!
 two_factor_enable_error = Enable Two-factor authentication failed: %v
 two_factor_enable_success = Two-factor authentication has enabled for your account successfully!
 two_factor_recovery_codes_title = Two-factor Authentication Recovery Codes

+ 1 - 1
gogs.go

@@ -16,7 +16,7 @@ import (
 	"github.com/gogits/gogs/pkg/setting"
 )
 
-const APP_VER = "0.11.48.0426"
+const APP_VER = "0.11.49.0521"
 
 func init() {
 	setting.AppVer = APP_VER

+ 5 - 0
models/user.go

@@ -120,6 +120,11 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) {
 	}
 }
 
+// IDStr returns string representation of user's ID.
+func (u *User) IDStr() string {
+	return com.ToStr(u.ID)
+}
+
 func (u *User) APIFormat() *api.User {
 	return &api.User{
 		ID:        u.ID,

+ 11 - 0
models/user_cache.go

@@ -0,0 +1,11 @@
+// Copyright 2018 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+// TwoFactorCacheKey returns key used for cache two factor passcode.
+// e.g. TwoFactor_1_012664
+func (u *User) TwoFactorCacheKey(passcode string) string {
+	return "TwoFactor_" + u.IDStr() + "_" + passcode
+}

File diff suppressed because it is too large
+ 112 - 112
pkg/bindata/bindata.go


+ 14 - 1
routes/user/auth.go

@@ -209,7 +209,9 @@ func LoginTwoFactorPost(c *context.Context) {
 		c.ServerError("GetTwoFactorByUserID", err)
 		return
 	}
-	valid, err := t.ValidateTOTP(c.Query("passcode"))
+
+	passcode := c.Query("passcode")
+	valid, err := t.ValidateTOTP(passcode)
 	if err != nil {
 		c.ServerError("ValidateTOTP", err)
 		return
@@ -224,6 +226,17 @@ func LoginTwoFactorPost(c *context.Context) {
 		c.ServerError("GetUserByID", err)
 		return
 	}
+
+	// Prevent same passcode from being reused
+	if c.Cache.IsExist(u.TwoFactorCacheKey(passcode)) {
+		c.Flash.Error(c.Tr("settings.two_factor_reused_passcode"))
+		c.Redirect(setting.AppSubURL + "/user/login/two_factor")
+		return
+	}
+	if err = c.Cache.Put(u.TwoFactorCacheKey(passcode), 1, 60); err != nil {
+		log.Error(2, "Failed to put cache 'two factor passcode': %v", err)
+	}
+
 	afterLogin(c, u, c.Session.Get("twoFactorRemember").(bool))
 }
 

+ 1 - 1
templates/.VERSION

@@ -1 +1 @@
-0.11.48.0426
+0.11.49.0521

Some files were not shown because too many files changed in this diff