enricog
enricog

Reputation: 4273

Sanitizing user input as part of an url

I get a string, from an external clientside script, which must later be attached as part of an url. Now I am wondering what is the best way to santitize such data?

The string I get will have a structure like this:
dynamicVal#staticVal:dynamicVal

This value will then be added to an url:
http://the-page.com/dynamicVal#staticVal:dynamicVal

The url is then used as followed:

$link = htmlspecialchars("http://external-page.com/dynamicVal#staticVal:dynamicVal", ENT_QUOTES);
$var = "<a href=\"javascript: window.open('$link')\">'Open URL'</a>";

Problem is, htmlspecialchars wont help to prevent execution of random javascript code, e.g. by adding this alert to the value:

dynamicVal#staticVal:dynamicVal'+alert(\"breakout\")+'

Using rawurlencode wont help either, because it is not a value of a parameter but a real part of the url.
So what is the best way to sanitize the passed string when concatenating to the url?

Thanks in advance.

Edit: Using rawurlencode only on the dynamic parts actually also didn't solve the issue, the javascript still got executed.
Test snippet:

$splitVal = "#staticVal:";
$tmpArr = explode($splitVal, "dynamicVal#staticVal:dynamicVal'+alert(\"breakout\")+'");
$link = htmlspecialchars(sprintf("http://external-page.com/"."%s$splitVal%s", rawurlencode($tmpArr[0]), rawurlencode($tmpArr[1])), ENT_QUOTES);
echo "<a href=\"javascript: window.open('$link')\">'Open URL'</a>";

Edit2: Using json_encode when passing the string as javascript argument didn't help either. Adapted test snippet:

$splitVal = "#staticVal:";
$tmpArr = explode($splitVal, "dynamicVal#staticVal:dynamicVal\"+alert('breakout')+\"");
$link = htmlspecialchars(sprintf("http://external-page.com/"."%s$splitVal%s", rawurlencode($tmpArr[0]), rawurlencode($tmpArr[1])), ENT_QUOTES);
echo  "<a href=\"javascript: window.open(".htmlspecialchars(json_encode($link), ENT_QUOTES).")\">'Open URL'</a>";

Adaptions done:
Switched the quotes in the malicous JS.
Moved htmlspecialchars around json_encode, because a double quoted string gets returned which would break the html otherwise.

Upvotes: 0

Views: 1509

Answers (2)

enricog
enricog

Reputation: 4273

For completenes, I was able to solve that issue by simply putting addslashes on the dynamic part before using rawurlencode.
Both function calls are needed to prevent breaking out. Using addslashes prevents normal quotes (',") and rawurlencode prevents already encoded quotes (%29,%22) to cause harm.

So final solution looks like this:

$splitVal = "#staticVal:";
$tmpArr = explode($splitVal, "dynamicVal#staticVal:dynamicVal'+alert(\"breakout\")+'");
$link = htmlspecialchars(sprintf("http://external-page.com/"."%s$splitVal%s", rawurlencode(addslashes($tmpArr[0])), rawurlencode(addslashes($tmpArr[1]))), ENT_QUOTES);
echo "<a href=\"javascript: window.open('$link')\">'Open URL'</a>";

Upvotes: 0

Stefan Gehrig
Stefan Gehrig

Reputation: 83692

You should use urlencode() for this. Not on the whole string but on the dynamic parts only.

$link = sprintf('http://external-page.com/%s#staticVal:%s', urlencode('dynamicVal'), urlencode('dynamicVal'));
$var  = "<a href=\"javascript: window.open('$link')\">'Open URL'</a>";

EDIT:

OK - I see your problem. I didn't realize that you insert the code into a JavaScript function call. You'll have to ensure that the JavaScript interpreter treats your link as a string argument to window.open():

$link = sprintf('http://external-page.com/%s#staticVal:%s', urlencode('dynamicVal'), urlencode('dynamicVal'));
$var  = "<a href=\"javascript: window.open(".json_encode($link).")\">'Open URL'</a>";

Upvotes: 3

Related Questions