diff --git a/src/hush.h b/src/hush.h index 4863547d7..fad5be098 100644 --- a/src/hush.h +++ b/src/hush.h @@ -591,6 +591,14 @@ int32_t hush_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryi opretlen += (scriptbuf[len++] << 8); } opoffset = len; + // SECURITY (Finding #4): opretlen is attacker-controlled (up to 65535 via OP_PUSHDATA2) + // and was previously used with no bounds check. scriptbuf is a fixed DRAGON_MAXSCRIPTSIZE + // stack buffer in hush_connectblock, so an oversized opretlen drives out-of-bounds reads in + // the downstream 'K'/KV and notarization paths (persisted to disk, leaked via kvsearch RPC, + // reliable crash on block connect). Reject any opret claiming more bytes than actually + // remain in the real script; this mirrors the no-OP_RETURN fall-through so nothing valid changes. + if ( opretlen < 0 || opretlen > scriptlen - len ) + return(notaryid); matched = 0; if ( SMART_CHAIN_SYMBOL[0] == 0 ) { @@ -933,7 +941,7 @@ int32_t hush_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) { memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); - if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) + if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac && numvalid < (int32_t)(sizeof(pubkeys)/sizeof(pubkeys[0])) ) { memcpy(pubkeys[numvalid++],scriptbuf+1,33); for (k=0; k<33; k++)