Potential XSS in content script via StackOverflow about_me in getalby/lightning-browser-extension

Valid

Reported on

May 7th 2023


Description

Alby has a feature called "batteries", which makes tipping on third party sites easier, e.g. by detecting lightning network addresses and so donating using the extensions becomes easy. One of those sites is stackoverflow. The alby extension will use the stackoverflow/stackexchange API to get a users "about_me" text to parse lightning payment info and show a "description". One method that is used during this is called htmlToText which is vulnerable to XSS attacks due to the use of innerHTML.

function htmlToText(html: string) {
  const temp = document.createElement("div");
  temp.innerHTML = html;
  return temp.textContent;
}

As can be seen in the excerpt from src/extension/content-script/batteries/StackOverflow.ts below, the results from the stackoverflow API (userData.about_me) more or less directly flow into the vulnerable function htmlToText.


async function handleProfilePage(userId: string): Promise<Battery | null> {
  const response = await axios.get(
    // The filter can be generated here: https://api.stackexchange.com/docs/users-by-ids
    `https://api.stackexchange.com/2.2/users/${userId}?site=stackoverflow&filter=!-B3yqvQ2YYGK1t-Hg_ydU`,
    { adapter: fetchAdapter }
  );

  if (!response) {
    return null;
  }

  const userInfo = await response.data;

  if (userInfo.error_id) {
    return null;
  }

  const userData = userInfo.items[0];

  if (!userData) {
    return null;
  }

  let address = null;

  if (userData.about_me) {
    address = findLightningAddressInText(userData.about_me);
  }

  if (!address) return null;

  return {
    method: "lnurl",
    address: address,
    ...getOriginData(),
    description: htmlToText(userData.about_me) ?? "",
    icon: userData.profile_image ?? "",
    name: userData.display_name,
  };
}

Proof of Concept

This issue has been identified using code auditing only, thus no PoC exists. However, to prove that the function is vulnerable, the following snippet can be used.

function htmlToText(html) {
  const temp = document.createElement("div");
  temp.innerHTML = html;
  return temp.textContent;
}
htmlToText("<img src onerror=alert(1)>")

Recommendation

I think htmlToText should be replaced by a secure function provided by some library, I'm not aware of a simple secure solution to this. Potentially templates can be used here to avoid javascript execution, but I'm not sure about that. (How does DOMPurify do it? Similar tech should work here.) I do not think you should start to sanitize this HTML, this is not needed.

Impact

Since this is kind of a second-order XSS the impact depends a bit on StackOverflow's API. I have not tested if it is possible to make it return XSS payloads easily, but it's doubtful. However, if SO had such an issue, or it is allowed by design, this becomes exploitable. The XSS seems to fire in the content script, which would allow the attacker to communicate with the background script and potentially mount further attacks.

Occurrences

innerHTML is also dangerous if the element is not appended to the DOM

We are processing your report and will contact the getalby/lightning-browser-extension team within 24 hours. 4 months ago
Finn Westendorf modified the report
4 months ago
Finn Westendorf modified the report
4 months ago
Finn Westendorf modified the report
4 months ago
We have contacted a member of the getalby/lightning-browser-extension team and are waiting to hear back 4 months ago
4 months ago

Maintainer


Hello! thanks a lot for your report! We are reviewing it and will get back to you asap. @bumi

Finn Westendorf
4 months ago

Researcher


Hi, thanks for the quick response! Perhaps the following snippet can help to build suitable fix:

function htmlTotext(html) {
  let parser = new DOMParser()
  let doc = parser.parseFromString(html, "text/html")
  return doc.body.innerText
}

htmlTotext("abc<svg><svg onload=alert(1)</svg></svg>123") // returns abc123 without executing the alert

Ofc, if you have any questions, don't hesitate to ask. I'm fairly confident this is secure, but I haven't done too much research into this.

Finn Westendorf modified the report
4 months ago
4 months ago

Maintainer


Thanks again for your report, I've prepared a PR with a fix for this potential issue:

https://github.com/getAlby/lightning-browser-extension/pull/2436

Should be included in the next release. 🤞

Finn Westendorf
4 months ago

Researcher


Nice! As you seem to agree on this finding, can you triage/verify this report? Would also be good for your stats on huntr.dev (i.e., first interaction & review).

Finn Westendorf
4 months ago

Researcher


@admin fix was merged to master... https://github.com/getAlby/lightning-browser-extension/commit/606aedf409c314a31289d8c918e52330fbb4859e

Ben Harvie validated this vulnerability 4 months ago
Finn Westendorf has been awarded the disclosure bounty
The fix bounty is now up for grabs
The researcher's credibility has increased: +7
Ben Harvie marked this as fixed in 2.0.1 with commit 606aed 4 months ago
The fix bounty has been dropped
This vulnerability will not receive a CVE
Ben Harvie published this vulnerability 4 months ago
StackOverflow.ts#L30 has been validated
Michael Bumann
4 months ago

Maintainer


I need some help setting the correct status here. What is the correct flow here?

Pavlos
3 months ago

Admin


What do you mean Michael?

getalby/lightning-browser-extension maintainer gave praise 3 months ago
Thanks again for the report, Finn! I think what Michael wanted to know was if we need to somehow close this issue now to mark it as completed?
The researcher's credibility has slightly increased as a result of the maintainer's thanks: +1
to join this conversation