mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
fix(channelserver): add max-size guards to binary blob save handlers
A malicious or buggy client could send arbitrarily large payloads that get written directly to PostgreSQL, wasting disk and memory. Each save handler now rejects payloads exceeding a generous upper bound derived from the known data format sizes. Covers all remaining items from #158: partner, hunternavi, savemercenary, scenariodata, platedata, platebox, platemyset, rengokudata, mezfes, savefavoritequest, house_furniture, mission. Closes #158
This commit is contained in:
@@ -183,6 +183,11 @@ func handleMsgMhfLoaddata(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveScenarioData)
|
pkt := p.(*mhfpacket.MsgMhfSaveScenarioData)
|
||||||
|
if len(pkt.RawDataPayload) > 65536 {
|
||||||
|
s.logger.Warn("Scenario payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
dumpSaveData(s, pkt.RawDataPayload, "scenario")
|
dumpSaveData(s, pkt.RawDataPayload, "scenario")
|
||||||
_, err := s.server.db.Exec("UPDATE characters SET scenariodata = $1 WHERE id = $2", pkt.RawDataPayload, s.charID)
|
_, err := s.server.db.Exec("UPDATE characters SET scenariodata = $1 WHERE id = $2", pkt.RawDataPayload, s.charID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ import (
|
|||||||
|
|
||||||
func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveMezfesData)
|
pkt := p.(*mhfpacket.MsgMhfSaveMezfesData)
|
||||||
|
if len(pkt.RawDataPayload) > 4096 {
|
||||||
|
s.logger.Warn("MezFes payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
if _, err := s.server.db.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.charID); err != nil {
|
if _, err := s.server.db.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.charID); err != nil {
|
||||||
s.logger.Error("Failed to save mezfes data", zap.Error(err))
|
s.logger.Error("Failed to save mezfes data", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ FROM warehouse
|
|||||||
|
|
||||||
func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfUpdateInterior)
|
pkt := p.(*mhfpacket.MsgMhfUpdateInterior)
|
||||||
|
if len(pkt.InteriorData) > 64 {
|
||||||
|
s.logger.Warn("Interior payload too large", zap.Int("len", len(pkt.InteriorData)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
if _, err := s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID); err != nil {
|
if _, err := s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID); err != nil {
|
||||||
s.logger.Error("Failed to update house furniture", zap.Error(err))
|
s.logger.Error("Failed to update house furniture", zap.Error(err))
|
||||||
}
|
}
|
||||||
@@ -253,6 +258,11 @@ func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo)
|
pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo)
|
||||||
|
if len(pkt.Data) > 512 {
|
||||||
|
s.logger.Warn("MyhouseInfo payload too large", zap.Int("len", len(pkt.Data)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
if _, err := s.server.db.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.charID); err != nil {
|
if _, err := s.server.db.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.charID); err != nil {
|
||||||
s.logger.Error("Failed to update myhouse mission", zap.Error(err))
|
s.logger.Error("Failed to update myhouse mission", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSavePartner)
|
pkt := p.(*mhfpacket.MsgMhfSavePartner)
|
||||||
|
if len(pkt.RawDataPayload) > 65536 {
|
||||||
|
s.logger.Warn("Partner payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
dumpSaveData(s, pkt.RawDataPayload, "partner")
|
dumpSaveData(s, pkt.RawDataPayload, "partner")
|
||||||
_, err := s.server.db.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
_, err := s.server.db.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -69,6 +74,11 @@ func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi)
|
pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi)
|
||||||
|
if len(pkt.RawDataPayload) > 4096 {
|
||||||
|
s.logger.Warn("HunterNavi payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
saveStart := time.Now()
|
saveStart := time.Now()
|
||||||
|
|
||||||
s.logger.Debug("Hunter Navi save request",
|
s.logger.Debug("Hunter Navi save request",
|
||||||
@@ -187,6 +197,11 @@ func handleMsgMhfCreateMercenary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveMercenary)
|
pkt := p.(*mhfpacket.MsgMhfSaveMercenary)
|
||||||
|
if len(pkt.MercData) > 65536 {
|
||||||
|
s.logger.Warn("Mercenary payload too large", zap.Int("len", len(pkt.MercData)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
dumpSaveData(s, pkt.MercData, "mercenary")
|
dumpSaveData(s, pkt.MercData, "mercenary")
|
||||||
if len(pkt.MercData) >= 4 {
|
if len(pkt.MercData) >= 4 {
|
||||||
temp := byteframe.NewByteFrameFromBytes(pkt.MercData)
|
temp := byteframe.NewByteFrameFromBytes(pkt.MercData)
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ func handleMsgMhfLoadPlateData(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSavePlateData)
|
pkt := p.(*mhfpacket.MsgMhfSavePlateData)
|
||||||
|
if len(pkt.RawDataPayload) > 262144 {
|
||||||
|
s.logger.Warn("PlateData payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
saveStart := time.Now()
|
saveStart := time.Now()
|
||||||
|
|
||||||
s.logger.Debug("PlateData save request",
|
s.logger.Debug("PlateData save request",
|
||||||
@@ -149,6 +154,11 @@ func handleMsgMhfLoadPlateBox(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSavePlateBox)
|
pkt := p.(*mhfpacket.MsgMhfSavePlateBox)
|
||||||
|
if len(pkt.RawDataPayload) > 32768 {
|
||||||
|
s.logger.Warn("PlateBox payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if pkt.IsDataDiff {
|
if pkt.IsDataDiff {
|
||||||
var data []byte
|
var data []byte
|
||||||
@@ -224,6 +234,11 @@ func handleMsgMhfLoadPlateMyset(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSavePlateMyset(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSavePlateMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSavePlateMyset)
|
pkt := p.(*mhfpacket.MsgMhfSavePlateMyset)
|
||||||
|
if len(pkt.RawDataPayload) > 4096 {
|
||||||
|
s.logger.Warn("PlateMyset payload too large", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
saveStart := time.Now()
|
saveStart := time.Now()
|
||||||
|
|
||||||
s.logger.Debug("PlateMyset save request",
|
s.logger.Debug("PlateMyset save request",
|
||||||
|
|||||||
@@ -206,6 +206,11 @@ func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest)
|
pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest)
|
||||||
|
if len(pkt.Data) > 65536 {
|
||||||
|
s.logger.Warn("FavoriteQuest payload too large", zap.Int("len", len(pkt.Data)))
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
dumpSaveData(s, pkt.Data, "favquest")
|
dumpSaveData(s, pkt.Data, "favquest")
|
||||||
if _, err := s.server.db.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.charID); err != nil {
|
if _, err := s.server.db.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.charID); err != nil {
|
||||||
s.logger.Error("Failed to save favorite quest", zap.Error(err))
|
s.logger.Error("Failed to save favorite quest", zap.Error(err))
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
// saved every floor on road, holds values such as floors progressed, points etc.
|
// saved every floor on road, holds values such as floors progressed, points etc.
|
||||||
// can be safely handled by the client
|
// can be safely handled by the client
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveRengokuData)
|
pkt := p.(*mhfpacket.MsgMhfSaveRengokuData)
|
||||||
if len(pkt.RawDataPayload) < 91 {
|
if len(pkt.RawDataPayload) < 91 || len(pkt.RawDataPayload) > 4096 {
|
||||||
s.logger.Warn("Rengoku payload too short", zap.Int("len", len(pkt.RawDataPayload)))
|
s.logger.Warn("Rengoku payload size out of range", zap.Int("len", len(pkt.RawDataPayload)))
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user