Skip to content

Instantly share code, notes, and snippets.

@enferas
Created December 30, 2022 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enferas/64fe954283bcb1b070076d6a01a8c309 to your computer and use it in GitHub Desktop.
Save enferas/64fe954283bcb1b070076d6a01a8c309 to your computer and use it in GitHub Desktop.
XSS in phoronix-test-suite

Link: phoronix-test-suite/phoronix-test-suite#650

CVE-2022-40704 is assigned to this discovery.

XSS vulnerability.

In file https://github.com/phoronix-test-suite/phoronix-test-suite/blob/master/pts-core/phoromatic/pages/phoromatic_r_add_test_details.php

\\line 41
// Note: the source
$test_profile = new pts_test_profile($_GET['tp']);

In file https://github.com/phoronix-test-suite/phoronix-test-suite/blob/master/pts-core/objects/pts_test_profile.php

public function __construct($identifier = null, $override_values = null, $normal_init = true){
	parent::__construct($identifier, $normal_init);
        //...
}

In file https://github.com/phoronix-test-suite/phoronix-test-suite/blob/master/pts-core/objects/pts_test_profile_parser.php

public function __construct($read = null, $normal_init = true){
//...
$this->xml = simplexml_load_string($read, 'SimpleXMLElement', $xml_options);
}

Now the input is in the xml property in object $test_profile.

In file https://github.com/phoronix-test-suite/phoronix-test-suite/blob/master/pts-core/phoromatic/pages/phoromatic_r_add_test_details.php

//line 47
if(!empty($supported_os = $test_profile->get_supported_platforms())){
        // Note: the sink
	echo '<p>This test is supported on <strong>' . implode(', ', $supported_os) . '</strong>.</p>';
}

In file https://github.com/phoronix-test-suite/phoronix-test-suite/blob/master/pts-core/objects/pts_test_profile_parser.php

public function get_supported_platforms_raw(){
		return $this->xg('TestProfile/SupportedPlatforms');
}

public function xg($xpath, $default_on_null = null){
		//...
		$r = $this->xml ? $this->xml->xpath($xpath) : null;
                //...
                return $r;
}

In phoromatic_quit_if_invalid_input_found your are checking the $_REQUEST which can carry the value of the $_POST and the $_GET.

function phoromatic_quit_if_invalid_input_found($input_keys = null)
{
	if(empty($input_keys))
	{
		// Check them all if not being selective about what keys to check
		$input_keys = array_keys($_REQUEST);
	}
	// backup as to sanitization and stripping elsewhere, safeguard namely check for things like < for fields that shouldn't have it
	// plus a few simple backups as safeguards for words that really have no legit relevance within Phoromatic...

	foreach(pts_strings::safety_strings_to_reject() as $invalid_string)
	{
		foreach($input_keys as $key)
		{
			if(isset($_REQUEST[$key]) && !empty($_REQUEST[$key]))
			{
				foreach(pts_arrays::to_array($_REQUEST[$key]) as $val_to_check)
				{
					if(stripos($val_to_check, $invalid_string) !== false)
					{
						echo '<strong>Exited due to invalid input ( ' . $invalid_string . ') attempted:</strong> ' . htmlspecialchars($val_to_check);
						exit;
					}
				}
			}
		}
	}
}

What I can do here that sending the post and the get with the same key (tp). I pass the safe value with the $_POST and the injection with the $_GET. Thus phoromatic_quit_if_invalid_input_found will check the value in the $_POST which is safe and I continue my injection with $_GET.

Here just a sample example I create to show that $_REQUEST is printing the value of the $_POST.

//server code
<?php

echo $_GET['tp']; // print getxxxx
echo $_POST['tp']; // print postyy
echo $_REQUEST['tp']; // print postyy
//payload
<?php
?>
<html>
<body>
<form action="http://localhost:8082/server.php?tp=getxxxx" id="myform" method="post" name="myform">
    <input type="hidden" name="tp" value="postyy">
    <input type="submit" value="Add Action" id="clickButton">
  </form>

  </body></html>
  <script>
  window.onload = function(){
    var button = document.getElementById('clickButton');
    button.form.submit();
}
</script>

Thus the input will be controlled by the attacker, saved in the xml then extracted and printed through the variable $supported_os.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment