Re-encode topic from WAMP msg to safeguard

The client is supposed to send a string as a topic but we're goign to re-json'ify the topic in case of bad client input.

fixes #516
This commit is contained in:
Chris Boden 2017-10-01 11:11:38 -04:00
parent c03b1b0f56
commit 810429a6fe
2 changed files with 52 additions and 29 deletions

View File

@ -62,9 +62,9 @@ class ServerProtocol implements MessageComponentInterface, WsServerInterface {
$subs[] = 'wamp'; $subs[] = 'wamp';
return $subs; return $subs;
} else {
return array('wamp');
} }
return ['wamp'];
} }
/** /**
@ -93,6 +93,10 @@ class ServerProtocol implements MessageComponentInterface, WsServerInterface {
throw new Exception("Invalid WAMP message format"); throw new Exception("Invalid WAMP message format");
} }
if (isset($json[1]) && !is_string($json[1])) {
$json[1] = json_encode($json[1]);
}
switch ($json[0]) { switch ($json[0]) {
case static::MSG_PREFIX: case static::MSG_PREFIX:
$from->WAMP->prefixes[$json[1]] = $json[2]; $from->WAMP->prefixes[$json[1]] = $json[2];
@ -122,13 +126,13 @@ class ServerProtocol implements MessageComponentInterface, WsServerInterface {
$exclude = (array_key_exists(3, $json) ? $json[3] : null); $exclude = (array_key_exists(3, $json) ? $json[3] : null);
if (!is_array($exclude)) { if (!is_array($exclude)) {
if (true === (boolean)$exclude) { if (true === (boolean)$exclude) {
$exclude = array($from->WAMP->sessionId); $exclude = [$from->WAMP->sessionId];
} else { } else {
$exclude = array(); $exclude = [];
} }
} }
$eligible = (array_key_exists(4, $json) ? $json[4] : array()); $eligible = (array_key_exists(4, $json) ? $json[4] : []);
$this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2], $exclude, $eligible); $this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2], $exclude, $eligible);
break; break;

View File

@ -4,9 +4,9 @@ use Ratchet\Mock\Connection;
use Ratchet\Mock\WampComponent as TestComponent; use Ratchet\Mock\WampComponent as TestComponent;
/** /**
* @covers Ratchet\Wamp\ServerProtocol * @covers \Ratchet\Wamp\ServerProtocol
* @covers Ratchet\Wamp\WampServerInterface * @covers \Ratchet\Wamp\WampServerInterface
* @covers Ratchet\Wamp\WampConnection * @covers \Ratchet\Wamp\WampConnection
*/ */
class ServerProtocolTest extends \PHPUnit_Framework_TestCase { class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
protected $_comp; protected $_comp;
@ -23,13 +23,13 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
} }
public function invalidMessageProvider() { public function invalidMessageProvider() {
return array( return [
array(0) [0]
, array(3) , [3]
, array(4) , [4]
, array(8) , [8]
, array(9) , [9]
); ];
} }
/** /**
@ -40,7 +40,7 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
$conn = $this->newConn(); $conn = $this->newConn();
$this->_comp->onOpen($conn); $this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode(array($type))); $this->_comp->onMessage($conn, json_encode([$type]));
} }
public function testWelcomeMessage() { public function testWelcomeMessage() {
@ -82,16 +82,16 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
} }
public function callProvider() { public function callProvider() {
return array( return [
array(2, 'a', 'b') [2, 'a', 'b']
, array(2, array('a', 'b')) , [2, ['a', 'b']]
, array(1, 'one') , [1, 'one']
, array(3, 'one', 'two', 'three') , [3, 'one', 'two', 'three']
, array(3, array('un', 'deux', 'trois')) , [3, ['un', 'deux', 'trois']]
, array(2, 'hi', array('hello', 'world')) , [2, 'hi', ['hello', 'world']]
, array(2, array('hello', 'world'), 'hi') , [2, ['hello', 'world'], 'hi']
, array(2, array('hello' => 'world', 'herp' => 'derp')) , [2, ['hello' => 'world', 'herp' => 'derp']]
); ];
} }
/** /**
@ -102,7 +102,7 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
$paramNum = array_shift($args); $paramNum = array_shift($args);
$uri = 'http://example.com/endpoint/' . rand(1, 100); $uri = 'http://example.com/endpoint/' . rand(1, 100);
$id = uniqid(); $id = uniqid('', false);
$clientMessage = array_merge(array(2, $id, $uri), $args); $clientMessage = array_merge(array(2, $id, $uri), $args);
$conn = $this->newConn(); $conn = $this->newConn();
@ -145,8 +145,8 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
public function testPublishAndEligible() { public function testPublishAndEligible() {
$conn = $this->newConn(); $conn = $this->newConn();
$buddy = uniqid(); $buddy = uniqid('', false);
$friend = uniqid(); $friend = uniqid('', false);
$this->_comp->onOpen($conn); $this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', false, array($buddy, $friend)))); $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', false, array($buddy, $friend))));
@ -265,4 +265,23 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
$this->_comp->onOpen($conn); $this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, $message); $this->_comp->onMessage($conn, $message);
} }
public function testBadClientInputFromNonStringTopic() {
$conn = new WampConnection($this->newConn());
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode([5, ['hells', 'nope']]));
$this->assertEquals('["hells","nope"]', $this->_app->last['onSubscribe'][1]);
}
public function testBadPrefixWithNonStringTopic() {
$conn = new WampConnection($this->newConn());
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode([1, ['hells', 'nope'], ['bad', 'input']]));
$this->_comp->onMessage($conn, json_encode([7, ['bad', 'input'], 'Hider']));
$this->assertEquals('["bad","input"]', $this->_app->last['onPublish'][1]);
}
} }