mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-10-01 07:10:46 -05:00
Don't return valid JavaScript from action.php
This avoids an attack where a malicious webpage contains
<script id="data" type="application/json"
src="http://play.pokemonshowdown.com/~~showdown/action.php?act=upkeep"/>
The webpage could then read the value of the `data` element using
standard DOM methods in order to steal the user's login assertion
and login as the user on the `showdown` server.
This commit is contained in:
13
action.php
13
action.php
@@ -30,6 +30,7 @@ if (@$_REQUEST['json']) {
|
||||
$multiReqs = true;
|
||||
}
|
||||
|
||||
$outPrefix = ']'; // JSON output should not be valid JavaScript
|
||||
$outArray = array();
|
||||
|
||||
foreach ($reqs as $reqData) {
|
||||
@@ -175,7 +176,7 @@ foreach ($reqs as $reqData) {
|
||||
// 'userserverdata' => @$user['userdata']['psserver'][$servertoken]
|
||||
);
|
||||
header('Content-type: application/json');
|
||||
die(json_encode($serveruserdata));
|
||||
die($outPrefix . json_encode($serveruserdata));
|
||||
break;
|
||||
case 'ladderupdate':
|
||||
include_once 'lib/ntbb-ladder.lib.php';
|
||||
@@ -200,6 +201,7 @@ foreach ($reqs as $reqData) {
|
||||
$out['p2rating'] = $p2['rating'];
|
||||
unset($out['p1rating']['rpdata']);
|
||||
unset($out['p2rating']['rpdata']);
|
||||
$outPrefix = ''; // No need for prefix since only usable by server.
|
||||
break;
|
||||
case 'prepreplay':
|
||||
include_once 'lib/ntbb-ladder.lib.php';
|
||||
@@ -224,6 +226,7 @@ foreach ($reqs as $reqData) {
|
||||
} else {
|
||||
$out = !!$db->query("INSERT INTO `ntbb_replays` (`id`,`loghash`,`p1`,`p2`,`format`,`date`) VALUES ('".$db->escape($reqData['id'])."','".$db->escape($reqData['loghash'])."','".$db->escape($reqData['p1'])."','".$db->escape($reqData['p2'])."','".$db->escape($reqData['format'])."',".time().")");
|
||||
}
|
||||
$outPrefix = ''; // No need for prefix since only usable by server.
|
||||
break;
|
||||
case 'uploadreplay':
|
||||
function stripNonAscii($str) { return preg_replace('/[^(\x20-\x7F)]+/','', $str); }
|
||||
@@ -255,7 +258,7 @@ foreach ($reqs as $reqData) {
|
||||
$user = $users->getUserData($reqData['user']);
|
||||
$ladder->getAllRatings($user);
|
||||
header('Content-type: application/json');
|
||||
die(json_encode($user['ratings']));
|
||||
die($outPrefix . json_encode($user['ratings']));
|
||||
break;
|
||||
case 'ladderformatget':
|
||||
include_once 'lib/ntbb-ladder.lib.php';
|
||||
@@ -271,7 +274,7 @@ foreach ($reqs as $reqData) {
|
||||
unset($user['rating']['formatid']);
|
||||
unset($user['rating']['rpdata']);
|
||||
header('Content-type: application/json');
|
||||
die(json_encode($user['rating']));
|
||||
die($outPrefix . json_encode($user['rating']));
|
||||
break;
|
||||
case 'ladderformatgetmmr':
|
||||
case 'mmr':
|
||||
@@ -312,8 +315,8 @@ foreach ($reqs as $reqData) {
|
||||
// json output
|
||||
if ($multiReqs) {
|
||||
header('Content-type: application/json');
|
||||
die(json_encode($outArray));
|
||||
die($outPrefix . json_encode($outArray));
|
||||
} else {
|
||||
header('Content-type: application/json');
|
||||
die(json_encode($out));
|
||||
die($outPrefix . json_encode($out));
|
||||
}
|
||||
|
||||
@@ -297,7 +297,15 @@ var basespecieschart = {
|
||||
};
|
||||
|
||||
var Tools = {
|
||||
|
||||
|
||||
safeJson: function(f) {
|
||||
return function(data) {
|
||||
if (data.length < 1) return;
|
||||
if (data[0] == ']') data = data.substr(1);
|
||||
return f.call(this, $.parseJSON(data));
|
||||
};
|
||||
},
|
||||
|
||||
prefs: (function() {
|
||||
var localStorageEntry = 'showdown_prefs';
|
||||
var data = (window.localStorage &&
|
||||
|
||||
14
js/sim.js
14
js/sim.js
@@ -1186,7 +1186,7 @@ function Lobby(id, elem) {
|
||||
case 'ladder':
|
||||
if (!target) target = me.userid;
|
||||
var self = this;
|
||||
$.get(actionphp + '?act=ladderget&serverid='+Config.serverid+'&user='+target, function(data) {
|
||||
$.get(actionphp + '?act=ladderget&serverid='+Config.serverid+'&user='+target, Tools.safeJson(function(data) {
|
||||
try {
|
||||
var buffer = '<div class="ladder"><table>';
|
||||
buffer += '<tr><td colspan="7">User: <strong>'+target+'</strong></td></tr>';
|
||||
@@ -1209,7 +1209,7 @@ function Lobby(id, elem) {
|
||||
self.rawMessage(buffer);
|
||||
} catch(e) {
|
||||
}
|
||||
}, 'json');
|
||||
}), 'text');
|
||||
return false;
|
||||
|
||||
case 'buttonban':
|
||||
@@ -2919,7 +2919,7 @@ function overlaySubmit(e, overlayType) {
|
||||
act: 'login',
|
||||
name: name,
|
||||
pass: $('#overlay_password').val()
|
||||
}, function (data) {
|
||||
}, Tools.safeJson(function (data) {
|
||||
if (!data) data = {};
|
||||
var token = data.assertion;
|
||||
if (data.curuser && data.curuser.loggedin) {
|
||||
@@ -2941,7 +2941,7 @@ function overlaySubmit(e, overlayType) {
|
||||
error: 'Wrong password.'
|
||||
});
|
||||
}
|
||||
}, 'json');
|
||||
}), 'text');
|
||||
overlayClose();
|
||||
break;
|
||||
case 'register':
|
||||
@@ -2953,7 +2953,7 @@ function overlaySubmit(e, overlayType) {
|
||||
password: $('#overlay_password').val(),
|
||||
cpassword: $('#overlay_cpassword').val(),
|
||||
captcha: captcha
|
||||
}, function (data) {
|
||||
}, Tools.safeJson(function (data) {
|
||||
if (!data) data = {};
|
||||
var token = data.assertion;
|
||||
if (data.curuser && data.curuser.loggedin) {
|
||||
@@ -2973,7 +2973,7 @@ function overlaySubmit(e, overlayType) {
|
||||
error: data.actionerror
|
||||
});
|
||||
}
|
||||
}, 'json').error(function (e) {
|
||||
}), 'text').error(function (e) {
|
||||
alert('error: ' + e);
|
||||
});
|
||||
overlayClose();
|
||||
@@ -3232,6 +3232,6 @@ if (!Config.down) {
|
||||
$.post(actionphp, {
|
||||
act: 'upkeep',
|
||||
name: name
|
||||
}, onConnect, 'json');
|
||||
}, Tools.safeJson(onConnect), 'text');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user