I have a old forum script that is allowing users to inject silly javascript code because the forum script cannot not handle incoming data that is url encoded multiple times, so I am trying to figure out how to urldecode()
incoming variables again and again until there are no more url encoded characters found in the incoming variable.
I am also trying to do the same thing for html entities, but that seems even more complicated because every time you process one html entity, the string size changes and the html entity you just decoded could be a part of another html entity that also needs to be decoded.
Anyhow... I am thinking I need to put the url decoder in a while()
loop and keep running urldecode()
on the variable until the variable is fully url decoded, but I am having a hard time figuring how to implement that without getting myself caught in a never ending while()
loop.
your forum script shouldn't be decoding anything, it should just properly html-encode the text when sending it back out. if we imagine that this is your current view script:
foreach($db->query("SELECT `author`,`message` FROM messages WHERE thread_id = ".((int)$thread_id)." ORDER BY date ASC",PDO::FETCH_ASSOC) as $message){
echo '<div style="message"><span style="message-author">'
.$message["author"].'</style>
'.$message["message"].'</div>';
}
(and this example code is indeed wide open to javascript-injection), you'll need to add html encoding to it, which can be done like:
/**
* convert any string to valid HTML, as losslessly as possible, assuming UTF-8
*
* @param string $str
* @return string
*/
function hhb_tohtml(string $str): string {
return htmlentities ( $str, ENT_QUOTES | ENT_HTML401 | ENT_SUBSTITUTE | ENT_DISALLOWED, 'UTF-8', true );
}
foreach($db->query("SELECT `author`,`message` FROM messages WHERE thread_id = ".((int)$thread_id)." ORDER BY date ASC",PDO::FETCH_ASSOC) as $message){
echo '<div style="message"><span style="message-author">'
.hhb_tohtml($message["author"]).'</style>
'.hhb_tohtml($message["message"]).'</div>';
}