Fix: potential token time attack
This commit is contained in:
parent
257fcef0b8
commit
4c3c64a34a
@ -2,11 +2,13 @@ package route
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/subtle"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
@ -96,6 +98,12 @@ func Start(addr string, secret string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func safeEuqal(a, b string) bool {
|
||||||
|
aBuf := unsafe.Slice(unsafe.StringData(a), len(a))
|
||||||
|
bBuf := unsafe.Slice(unsafe.StringData(b), len(b))
|
||||||
|
return subtle.ConstantTimeCompare(aBuf, bBuf) == 1
|
||||||
|
}
|
||||||
|
|
||||||
func authentication(next http.Handler) http.Handler {
|
func authentication(next http.Handler) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
if serverSecret == "" {
|
if serverSecret == "" {
|
||||||
@ -106,7 +114,7 @@ func authentication(next http.Handler) http.Handler {
|
|||||||
// Browser websocket not support custom header
|
// Browser websocket not support custom header
|
||||||
if websocket.IsWebSocketUpgrade(r) && r.URL.Query().Get("token") != "" {
|
if websocket.IsWebSocketUpgrade(r) && r.URL.Query().Get("token") != "" {
|
||||||
token := r.URL.Query().Get("token")
|
token := r.URL.Query().Get("token")
|
||||||
if token != serverSecret {
|
if !safeEuqal(token, serverSecret) {
|
||||||
render.Status(r, http.StatusUnauthorized)
|
render.Status(r, http.StatusUnauthorized)
|
||||||
render.JSON(w, r, ErrUnauthorized)
|
render.JSON(w, r, ErrUnauthorized)
|
||||||
return
|
return
|
||||||
@ -119,7 +127,7 @@ func authentication(next http.Handler) http.Handler {
|
|||||||
bearer, token, found := strings.Cut(header, " ")
|
bearer, token, found := strings.Cut(header, " ")
|
||||||
|
|
||||||
hasInvalidHeader := bearer != "Bearer"
|
hasInvalidHeader := bearer != "Bearer"
|
||||||
hasInvalidSecret := !found || token != serverSecret
|
hasInvalidSecret := !found || !safeEuqal(token, serverSecret)
|
||||||
if hasInvalidHeader || hasInvalidSecret {
|
if hasInvalidHeader || hasInvalidSecret {
|
||||||
render.Status(r, http.StatusUnauthorized)
|
render.Status(r, http.StatusUnauthorized)
|
||||||
render.JSON(w, r, ErrUnauthorized)
|
render.JSON(w, r, ErrUnauthorized)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user