ishefi/semantle-he

XSS Vulnerability

Closed this issue · 2 comments

There is an unlikely but possible XSS vulnerablity. If someone is convinced to paste a guess, then an attacker can execute arbitrary JS on the victim's browser.

How to reproduce:

  1. Go to semantel
  2. Paste the following in the text input (with the quotes in the end): היי&"><iframe src="/" onload="alert('PWND')" width="0px" height="0px" />"
  3. Press the button and observe the result:
    image

There are two parts to exploiting the vulnerability:

  1. First, we have to make the server return a response that recognizes the guessed word. Since, if the server returns an empty response the guess row element is not generated and we get an error.

In order to do that, we can just write an actual word; e.g. היי, add the & character in order to make the server think it's a different parameter and add arbitrary text afterwards.
When we send היי&Malicious code here and get a response from the server as if we only sent היי.
Sanitizing the input before executing the following lines of code should solve this problem.

const url = "/api/distance" + '?word=' + word;
const response = await fetch(url);
  1. The use of innerHTML in function guessRow, specifically here:
return `<tr><td>${guessNumber}</td>
<td style="color:${color}" onclick="select('${oldGuess}', secretVec);">${oldGuess}</td>
<td align="right" dir="ltr">${similarity.toFixed(2)}</td>
<td class="${cls}">${percentileText}${progress}
</td></tr>`;

Using an alternative to innerHTML or escaping the input should also help preventing this attack.

Combining these two vulnerabilities, when we enter the malicious input, the following dangerous HTML is generated:

<tr>
   <td>1</td>
   <td style="color:#c0c" onclick="select('היי&amp;">
      <iframe src="/" onload="alert('PWND')" width="0px" height="0px">"', secretVec);">היי&">
      <iframe src="/" onload="alert('PWND')" width="0px" height="0px" />
         "
   </td>
   <td align="right" dir="ltr">24.84</td>
   <td class="">(רחוק)
   </td>
</tr>
<tr><td colspan=4><hr></td></tr></iframe></td></tr>
ishefi commented

@JPDevelop seems like this doesn't happen anymore. Maybe thanks to fastapi upgrade?

I don't think so, this is probably due to a fix in the FE where you take the guess word from the server's response instead of the user's input.

Closing.