Fork me on GitHub
Subscribe 2

Ticket #1114 (open bug)

Code tags can go places no code tag should go

  • Created: 2018-05-29 18:24:50
  • Reported by: Different55
  • Assigned to: None
  • Milestone: 1.5.11
  • Component: parser
  • Priority: normal

For example, inside [url ] tags.

[url][code]Whoops.[/code][/url]

This BBCode passes through the parser without a fuss and makes some nice invalid HTML that breaks the page slightly. Only tested it in Firefox so far, not sure about the best way to fix it.

History

Different55 2018-05-29 19:05:58

  • Description changed. (Diff)

Franz 2018-05-30 21:13:40

  • Milestone set to 1.5.11.

Nice catch, thanks for the report.

Visman 2018-07-19 05:07:46

Most of the bb-codes allow you to place the code tags inside.
Cause: the parser does not participate in processing the code tags

Different55 2018-09-22 13:29:22

In case anyone else's users are abusing this to trash topics and PMs and wherever else, I used this function to detect their tomfoolery. It ain't pretty but in the 5 minutes I've used it, nothing's blown up.

//
// Check the structure of code tags to make sure nobody's doing anything funny.
//
function pre_preparse_tags($text) {
	global $pun_user;
	$split_text = preg_split('%(\[[\*a-zA-Z0-9-/]*?(?:=.*?)?\])%', $text, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

	$open_tags = array('quote');

	foreach ($split_text as $current)
	{
		$top_tag = array_slice($open_tags, -1)[0];
		if (substr($current, 0, 1) == '[' && substr($current, -1, 1) == ']')
		{

			// Get the name of the tag
			$current_arg = '';
			$closing = false;
			if (strpos($current, '/') === 1)
			{
				$current_tag = substr($current, 2, -1);
				$closing = true;
			}
			else if (strpos($current, '=') === false)
			{
				$current_tag = substr($current, 1, -1);
			}
			else
			{
				$current_tag = substr($current, 1, strpos($current, '=')-1);
				$current_arg = substr($current, strpos($current, '=')+1, -1);
			}

			if ($top_tag == 'code')
			{
				if ($current_tag == 'code' && $closing)
					array_pop($open_tags);
				else
					continue;
			}
			else if ($top_tag == $current_tag && $closing)
			{
				array_pop($open_tags);
			}
			else if ($current_tag == 'code' && $top_tag != 'quote')
			{
				return true;
			}
			else if (!$closing) {
				$open_tags[] = $current_tag;
			}
		}
	}
	return false;
}

It needs to be slipped into parser.php, and call it from inside preparse_bbcode right before this bit:

// If the message contains a code tag we have to split it up (text within [code ][/ code] shouldn't be touched)

The function returns true if they're trying to mess with the forums or false if they're okay on that front. Typically you'd just add a little note to the errors like

if (pre_preparse_tags($text))
	$errors[] = sprintf($lang_common['BBCode error invalid nesting'], 'code', 'literally anything else');

but my personal favorite is

if (pre_preparse_tags($text))
	message($lang_common['Ban message'].' '.$lang_common['Ban message 3'].'<br /><br /><strong>Gosh darn it, Marie, what are you tryna pull?</strong><br /><br />'.$lang_common['Ban message 4'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.', true, 403);

It's a fake ban page. Substitute with a real ban if they're really getting on your nerves.

Comment edited 3 times (Diff, Diff 2, Diff 3)

Franz 2018-09-29 21:33:12

@Different55: Did you have problems with people abusing this bug on your forum?

Different55 2018-09-29 21:42:56

Little bit, yeah. Discovered it in the first place when a drunk user decided to drunkenly smash the BBCode buttons and happened to break the topic. That event was recently re-discovered and everyone went nuts with it.