Fix PoW auth bypass: verify against issued challenge, not new one
Store challenge from handleGetChallenge in session, then verify against it in handleSolve. Previously a fresh challenge was generated for verification, making auth trivially bypassable.
This commit is contained in:
parent
dbb2782dd7
commit
4f6310c2bb
2 changed files with 22 additions and 2 deletions
|
|
@ -233,6 +233,7 @@ func (s *Server) handleStream(ctx context.Context, stream *quic.Stream, sess *Se
|
|||
|
||||
func (s *Server) handleGetChallenge(sess *Session) {
|
||||
challenge := auth.NewChallenge(s.cfg.PoW.Difficulty)
|
||||
sess.SetChallenge(challenge)
|
||||
if st := sess.Stream(); st != nil {
|
||||
st.WriteFrame(byte(types.OpChallenge), challenge.Marshal())
|
||||
}
|
||||
|
|
@ -245,7 +246,12 @@ func (s *Server) handleSolve(sess *Session, payload []byte) {
|
|||
return
|
||||
}
|
||||
|
||||
challenge := auth.NewChallenge(s.cfg.PoW.Difficulty)
|
||||
challenge := sess.GetChallenge()
|
||||
if challenge == nil {
|
||||
sendOpError(sess.Stream(), types.ErrPoWInvalid, "no challenge issued")
|
||||
return
|
||||
}
|
||||
|
||||
if err := challenge.Verify(solution, s.cfg.PoW.ChallengeTTL); err != nil {
|
||||
sendOpError(sess.Stream(), types.ErrPoWInvalid, err.Error())
|
||||
return
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/apernet/quic-go"
|
||||
"github.com/niko/qcc/internal/auth"
|
||||
"github.com/niko/qcc/internal/protocol"
|
||||
"github.com/niko/qcc/internal/transport"
|
||||
)
|
||||
|
|
@ -19,6 +20,7 @@ type Session struct {
|
|||
certDER []byte
|
||||
|
||||
activeCallID uint64
|
||||
lastChallenge *auth.PoWChallenge
|
||||
}
|
||||
|
||||
func NewSession(conn *quic.Conn) *Session {
|
||||
|
|
@ -90,3 +92,15 @@ func (s *Session) ClearCall() {
|
|||
defer s.mu.Unlock()
|
||||
s.activeCallID = 0
|
||||
}
|
||||
|
||||
func (s *Session) SetChallenge(c *auth.PoWChallenge) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.lastChallenge = c
|
||||
}
|
||||
|
||||
func (s *Session) GetChallenge() *auth.PoWChallenge {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.lastChallenge
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue