NAS: Check and sanitize payload ID

This commit is contained in:
mkwcat 2023-11-21 15:20:55 -05:00
parent 7c7691eed3
commit 81f219da4c
No known key found for this signature in database
GPG Key ID: 7A505679CE9E7AA9
3 changed files with 46 additions and 17 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
# Local configuration file
config.xml
salt.bin
# Payload data
payload

View File

@ -10,11 +10,11 @@ import (
"encoding/hex"
"encoding/pem"
"github.com/logrusorgru/aurora/v3"
"log"
"net/http"
"net/url"
"os"
"strconv"
"wwfc/logging"
)
func getStage1(r *Response, fields map[string]string) map[string]string {
@ -27,56 +27,85 @@ func getStage1(r *Response, fields map[string]string) map[string]string {
return map[string]string{}
}
func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
func handlePayloadRequest(moduleName string, w http.ResponseWriter, r *http.Request) {
// Example request:
// GET /payload?g=RMCPD00&s=4e44b095817f8cfb62e6cffd57e9cfd411004a492784039ea4b2b7ca64717c91&h=9fdb6f60
u, err := url.Parse(r.URL.String())
if err != nil {
log.Printf(aurora.Red("failed to parse URL").String())
logging.Error(moduleName, "Failed to parse URL")
return
}
query, err := url.ParseQuery(u.RawQuery)
if err != nil {
log.Printf(aurora.Red("failed to parse URL query").String())
logging.Error(moduleName, "Failed to parse URL query")
return
}
// TODO: Read payload ID (g) from URL
dat, err := os.ReadFile("payload/binary/RMCPD00.bin")
// Read payload ID (g) from URL
game := query["g"][0]
if len(game) != 7 && len(game) != 9 {
logging.Error(moduleName, "Invalid or missing game ID:", aurora.Cyan(game))
return
}
if (len(game) == 7 && game[4] != 'D') || (len(game) == 9 && game[4] != 'N') {
logging.Error(moduleName, "Invalid game ID:", aurora.Cyan(game))
return
}
for i := 0; i < 4; i++ {
if (game[i] >= 'A' && game[i] <= 'Z') || (game[i] >= '0' && game[i] <= '9') {
continue
}
logging.Error(moduleName, "Invalid game ID char:", aurora.Cyan(game))
return
}
for i := 5; i < len(game); i++ {
if (game[i] >= '0' && game[i] <= '9') || (game[i] >= 'a' && game[i] <= 'f') {
continue
}
logging.Error(moduleName, "Invalid game ID version:", aurora.Cyan(game))
return
}
dat, err := os.ReadFile("payload/binary/payload." + game + ".bin")
if err != nil {
log.Printf(aurora.Red("failed to read payload file").String())
logging.Error(moduleName, "Failed to read payload file")
return
}
salt, ok := query["s"]
if ok {
if len(salt[0]) != 64 {
log.Printf(aurora.Red("invalid salt length").String())
logging.Error(moduleName, "Invalid salt length:", aurora.BrightCyan(len(salt[0])))
return
}
_, err := hex.DecodeString(salt[0])
if err != nil {
log.Printf(aurora.Red("invalid salt hex string").String())
logging.Error(moduleName, "Invalid salt hex string")
return
}
saltHashTest, ok := query["h"]
if !ok {
log.Printf(aurora.Red("Request is missing salt hash").String())
logging.Error(moduleName, "Request is missing salt hash")
return
}
if len(saltHashTest[0]) != 8 {
log.Printf(aurora.Red("Invalid salt hash length").String())
logging.Error(moduleName, "Invalid salt hash length:", aurora.BrightCyan(len(saltHashTest[0])))
return
}
saltHashTestData, err := hex.DecodeString(saltHashTest[0])
if err != nil {
log.Printf(aurora.Red("Invalid salt hash hex string").String())
logging.Error(moduleName, "Invalid salt hash hex string")
return
}
@ -91,7 +120,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
saltHash := hashCtx.Sum(nil)
if !bytes.Equal(saltHashTestData, saltHash[:4]) {
log.Printf(aurora.Red("Invalid salt hash").String())
logging.Error(moduleName, "Salt hash mismatch")
return
}
@ -100,7 +129,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
// TODO: Cache the request for a zero salt
rsaData, err := os.ReadFile("payload/stage1-private-temp.pem")
rsaData, err := os.ReadFile("payload/private-key.pem")
if err != nil {
panic(err)
}
@ -113,7 +142,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
rsaKey, ok := parsedKey.(*rsa.PrivateKey)
if !ok {
log.Fatalf("got unexpected key type: %T", parsedKey)
panic("Unexpected key type")
}
// Hash our data then sign
@ -133,7 +162,6 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
dat = append(append(dat[:0x10], signature...), dat[0x110:]...)
log.Printf(aurora.White("write data").String())
w.Header().Set("Content-Length", strconv.Itoa(len(dat)))
w.Write(dat)
}

View File

@ -69,7 +69,7 @@ func (route *Route) Handle() http.Handler {
// TODO: Move this to its own server
// Check for /payload
if strings.HasPrefix(r.URL.String(), "/payload") {
handlePayloadRequest(w, r)
handlePayloadRequest(moduleName, w, r)
return
}