Skip to content

Commit

Permalink
Add support for SHA-1 CodeIgniter cookies.
Browse files Browse the repository at this point in the history
  • Loading branch information
iangcarroll committed Jan 10, 2025
1 parent 309afe8 commit 074e770
Showing 1 changed file with 40 additions and 9 deletions.
49 changes: 40 additions & 9 deletions pkg/monster/codeigniter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import (
"encoding/hex"
"fmt"
"net/url"
"strings"
)

type codeigniterParsedData struct {
body string
signature string
decodedSignature []byte
algorithm string

parsed bool
}
Expand All @@ -26,6 +28,9 @@ func (d *codeigniterParsedData) String() string {
const (
codeigniterDecoder = "codeigniter"
codeigniterMinLength = 100

codeigniterAlgoithmSha1 = "sha1"
codeigniterAlgoithmMd5 = "md5"
)

func codeigniterDecode(c *Cookie) bool {
Expand All @@ -34,17 +39,32 @@ func codeigniterDecode(c *Cookie) bool {
}

rawData := c.raw
// If the cookie doesn't contain the expected fields, it's not a CodeIgniter cookie.
if !strings.Contains(rawData, "session_id") || !strings.Contains(rawData, "user_agent") {
return false
}

var parsedData codeigniterParsedData

// The last 32 characters are the hex-encoded MD5 signature.
hashComponent := rawData[len(rawData)-32:]
parsedData.body = rawData[:len(rawData)-32]
// The last 32 or 40 characters are the hex-encoded MD5 or SHA1 signature.
hashComponent := rawData[len(rawData)-40:]
parsedData.body = rawData[:len(rawData)-40]
parsedData.signature = hashComponent
parsedData.algorithm = codeigniterAlgoithmSha1

decodedSignature, err := hex.DecodeString(hashComponent)

// If we failed to decode the signature, it could be using MD5.
if err != nil {
return false
hashComponent = rawData[len(rawData)-32:]
parsedData.body = rawData[:len(rawData)-32]
parsedData.signature = hashComponent
parsedData.algorithm = codeigniterAlgoithmMd5

decodedSignature, err = hex.DecodeString(hashComponent)
if err != nil {
return false
}
}

urlDecodedBody, err := url.QueryUnescape(parsedData.body)
Expand All @@ -63,9 +83,20 @@ func codeigniterUnsign(c *Cookie, secret []byte) bool {
// We need to extract `toBeSigned` to prepare what we'll be signing.
parsedData := c.parsedDataFor(codeigniterDecoder).(*codeigniterParsedData)

// Derive the correct signature, if this was the correct secret key.
computedSignature := md5Digest(parsedData.body + string(secret))

// Compare this signature to the one in the `Cookie`.
return bytes.Equal(parsedData.decodedSignature, computedSignature)
switch parsedData.algorithm {
case codeigniterAlgoithmMd5:
// Derive the correct signature, if this was the correct secret key.
computedSignature := md5Digest(parsedData.body + string(secret))

// Compare this signature to the one in the `Cookie`.
return bytes.Equal(parsedData.decodedSignature, computedSignature)
case codeigniterAlgoithmSha1:
// Derive the correct signature, if this was the correct secret key.
computedSignature := sha1Digest(parsedData.body + string(secret))

// Compare this signature to the one in the `Cookie`.
return bytes.Equal(parsedData.decodedSignature, computedSignature)
default:
panic("Unknown algorithm")
}
}

0 comments on commit 074e770

Please sign in to comment.