Quay lại blog

Cách tránh phát hiện tự động hóa qua các cuộc tấn công thời gian: bảo vệ trong Selenium và Puppeteer

Tấn công theo thời gian là một trong những phương pháp phát hiện tự động hóa khó khăn nhất. Chúng ta sẽ phân tích cách bảo vệ khỏi việc phân tích thời gian thực hiện các hành động trong trình duyệt.

📅10 tháng 1, 2026
```html

Các cuộc tấn công timing — là phương pháp phát hiện bot dựa trên phân tích thời gian thực hiện hành động trong trình duyệt. Các hệ thống chống gian lận hiện đại của Facebook, Google, TikTok và các nền tảng khác không chỉ phân tích những gì bạn làm, mà còn cả tốc độ thực hiện. Những cú nhấp chuột quá nhanh, tải trang ngay lập tức, thiếu các khoảng dừng tự nhiên — tất cả đều cho thấy sự tự động hóa. Trong bài viết này, chúng ta sẽ xem xét các phương pháp kỹ thuật để bảo vệ khỏi các cuộc tấn công timing cho các nhà phát triển làm việc với Selenium, Puppeteer và các trình duyệt chống phát hiện.

Các cuộc tấn công timing là gì và chúng hoạt động như thế nào

Các cuộc tấn công timing — là phương pháp phát hiện tự động hóa dựa trên việc đo lường khoảng thời gian giữa các hành động của người dùng. Các hệ thống chống gian lận thu thập dữ liệu telemetry: thời gian từ khi tải trang đến cú nhấp chuột đầu tiên, tốc độ cuộn của người dùng, có khoảng dừng khi điền vào các biểu mẫu hay không. Những dữ liệu này được so sánh với các mô hình hành vi của những người thực.

Các chỉ số thời gian chính mà các hệ thống bảo vệ phân tích:

  • Thời gian đến tương tác đầu tiên (TTFI) — thời gian từ khi tải trang đến hành động đầu tiên (nhấp chuột, cuộn, nhập văn bản). Các bot thường bắt đầu hành động ngay lập tức sau khi tải DOM, trong khi con người — từ 0.5 đến 3 giây.
  • Mẫu thời gian nhấp chuột — khoảng thời gian giữa các cú nhấp chuột. Các kịch bản tự động thường nhấp chuột với tần suất giống nhau (ví dụ: chính xác mỗi 2 giây), trong khi con người — một cách ngẫu nhiên.
  • Độ nhất quán tốc độ gõ — tốc độ nhập văn bản. Các bot nhập văn bản ngay lập tức hoặc với độ trễ cố định giữa các ký tự, trong khi con người — với tốc độ biến đổi và có khoảng dừng.
  • Tốc độ chuyển động chuột — tốc độ di chuyển con trỏ. Selenium theo mặc định dịch chuyển con trỏ ngay lập tức đến điểm cần thiết, trong khi con người di chuyển chuột với gia tốc và giảm tốc.
  • Hành vi cuộn — các mẫu cuộn trang. Các bot thường cuộn chính xác một số pixel cố định, trong khi con người — không đều, với các điểm dừng.

Các hệ thống phát hiện sử dụng học máy để phân tích những chỉ số này. Chúng xây dựng hồ sơ hành vi và tính toán xác suất rằng người dùng là bot. Nếu các mẫu thời gian quá hoàn hảo hoặc quá nhanh — đó là dấu hiệu đỏ.

Quan trọng: Các cuộc tấn công timing đặc biệt hiệu quả chống lại tự động hóa hàng loạt. Nếu bạn khởi động 100 trình duyệt với các mẫu thời gian giống nhau, hệ thống chống gian lận sẽ dễ dàng phát hiện chúng qua các bất thường thống kê.

Các phương pháp phát hiện tự động hóa thông qua các mẫu thời gian

Các hệ thống chống gian lận hiện đại sử dụng nhiều lớp phân tích các đặc điểm thời gian. Chúng ta hãy xem xét các kỹ thuật cụ thể mà Facebook, Google, Cloudflare và các nền tảng khác áp dụng.

1. Phân tích Performance API

Các trình duyệt cung cấp Performance API, thu thập dữ liệu telemetry chi tiết về việc tải trang. Các hệ thống chống gian lận phân tích:

// Ví dụ về dữ liệu Performance API
performance.timing = {
  navigationStart: 1234567890000,
  domLoading: 1234567890150,      // +150ms
  domInteractive: 1234567890300,  // +300ms
  domComplete: 1234567890500,     // +500ms
  loadEventEnd: 1234567890600     // +600ms
}

// Các mẫu nghi ngờ cho bot:
// - Tải quá nhanh (domComplete < 200ms)
// - Các khoảng thời gian giữa các sự kiện hoàn hảo
// - Không có độ trễ khi tải các tài nguyên bên ngoài

Các trình duyệt headless (đặc biệt là các phiên bản cũ của Puppeteer và Selenium) thường hiển thị các giá trị navigationStart và domLoading nhanh bất thường, vì chúng không tải hình ảnh, phông chữ và các tài nguyên khác giống như một trình duyệt thông thường.

2. Phân tích Thời gian Sự kiện

Các trình theo dõi JavaScript theo dõi các dấu thời gian của tất cả các sự kiện (nhấp chuột, di chuyển chuột, nhấn phím) và phân tích các mẫu:

// Ví dụ về thu thập dữ liệu telemetry sự kiện
const events = [];

document.addEventListener('click', (e) => {
  events.push({
    type: 'click',
    timestamp: performance.now(),
    x: e.clientX,
    y: e.clientY
  });
});

// Phân tích các mẫu nghi ngờ:
// - Các cú nhấp chuột xảy ra chính xác mỗi N mili giây
// - Không có chuyển động vi mô của chuột trước khi nhấp chuột
// - Cú nhấp chuột đầu tiên xảy ra ngay lập tức sau khi tải trang

3. Động lực Gõ phím

Khi điền vào các biểu mẫu, các hệ thống chống gian lận phân tích động lực gõ phím — một chỉ số sinh trắc học độc đáo của mỗi người:

  • Thời gian giữ phím — thời gian giữ phím (từ keydown đến keyup). Ở người, nó dao động từ 50 đến 200 ms, ở bot — là hằng số.
  • Thời gian bay — thời gian giữa việc nhả một phím và nhấn phím tiếp theo. Ở người — từ 100 đến 500 ms với các biến thể, ở bot — độ trễ cố định.
  • Nhịp độ gõ — nhịp độ tổng thể của việc gõ. Con người có các khoảng dừng ở các dấu câu, sửa lỗi, trong khi bot — không.

Ví dụ về phát hiện: Nếu bạn sử dụng element.send_keys("văn bản") trong Selenium, toàn bộ văn bản được nhập trong 1-2 mili giây — điều này ngay lập tức cho thấy sự tự động hóa.

Mô phỏng các độ trễ giống như con người trong mã

Cấp độ bảo vệ đầu tiên chống lại các cuộc tấn công timing — là thêm độ trễ giữa các hành động. Nhưng điều quan trọng không chỉ là chèn time.sleep(2), mà còn phải mô phỏng hành vi tự nhiên.

Mô phỏng cơ bản độ trễ trong Python (Selenium)

import time
import random
from selenium import webdriver
from selenium.webdriver.common.by import By

def human_delay(min_sec=0.5, max_sec=2.0):
    """Độ trễ ngẫu nhiên, mô phỏng con người"""
    delay = random.uniform(min_sec, max_sec)
    time.sleep(delay)

driver = webdriver.Chrome()
driver.get("https://example.com")

# Độ trễ trước hành động đầu tiên (con người đọc trang)
human_delay(1.5, 4.0)

# Nhấp chuột vào phần tử
button = driver.find_element(By.ID, "submit-btn")
button.click()

# Độ trễ trước hành động tiếp theo
human_delay(0.8, 2.5)

Mô phỏng nâng cao với phân phối chuẩn

Phân phối đồng đều (uniform) trông không tự nhiên. Các độ trễ của con người tuân theo phân phối chuẩn với các ngoại lệ:

import numpy as np

def realistic_delay(mean=1.5, std_dev=0.5, min_val=0.3, max_val=5.0):
    """
    Độ trễ với phân phối chuẩn
    mean: thời gian độ trễ trung bình
    std_dev: độ lệch chuẩn
    min_val, max_val: giới hạn (để tránh các giá trị cực đoan)
    """
    delay = np.random.normal(mean, std_dev)
    delay = max(min_val, min(max_val, delay))  # Giới hạn phạm vi
    time.sleep(delay)
    return delay

# Sử dụng
realistic_delay(mean=2.0, std_dev=0.7)  # Trung bình 2 giây, nhưng có biến thể

Độ trễ theo ngữ cảnh

Các hành động khác nhau yêu cầu thời gian khác nhau. Tạo các hồ sơ độ trễ cho các kịch bản khác nhau:

class HumanBehavior:
    """Hồ sơ độ trễ cho các loại hành động khác nhau"""
    
    @staticmethod
    def page_load_delay():
        """Độ trễ sau khi tải trang (đọc nội dung)"""
        return realistic_delay(mean=2.5, std_dev=1.0, min_val=1.0, max_val=6.0)
    
    @staticmethod
    def before_click():
        """Độ trễ trước khi nhấp chuột (tìm kiếm phần tử bằng mắt)"""
        return realistic_delay(mean=0.8, std_dev=0.3, min_val=0.3, max_val=2.0)
    
    @staticmethod
    def before_typing():
        """Độ trễ trước khi bắt đầu nhập văn bản"""
        return realistic_delay(mean=1.2, std_dev=0.5, min_val=0.5, max_val=3.0)
    
    @staticmethod
    def between_form_fields():
        """Độ trễ giữa các trường biểu mẫu"""
        return realistic_delay(mean=0.6, std_dev=0.2, min_val=0.2, max_val=1.5)

# Sử dụng trong kịch bản
driver.get("https://example.com/login")
HumanBehavior.page_load_delay()

username_field = driver.find_element(By.ID, "username")
HumanBehavior.before_typing()
# ... nhập tên đăng nhập ...

HumanBehavior.between_form_fields()

password_field = driver.find_element(By.ID, "password")
HumanBehavior.before_typing()
# ... nhập mật khẩu ...

Ngẫu nhiên hóa thời gian thực hiện hành động

Các độ trễ giống hệt nhau giữa các hành động — là một bất thường thống kê. Nếu bạn khởi động 100 phiên bản kịch bản và tất cả đều nhấp chuột vào nút chính xác sau 2.5 giây sau khi tải — điều này dễ dàng bị phát hiện. Cần có sự ngẫu nhiên hóa ở nhiều cấp độ.

1. Ngẫu nhiên hóa thứ tự hành động

Thêm sự biến đổi vào thứ tự hành động. Ví dụ, trước khi điền vào biểu mẫu, đôi khi cuộn trang, đôi khi — không:

def fill_form_naturally(driver):
    # 30% xác suất cuộn trang trước khi điền
    if random.random() < 0.3:
        driver.execute_script("window.scrollBy(0, 200)")
        human_delay(0.5, 1.5)
    
    # 20% xác suất nhấp vào một vị trí ngẫu nhiên (mô phỏng việc đọc)
    if random.random() < 0.2:
        body = driver.find_element(By.TAG_NAME, "body")
        body.click()
        human_delay(0.3, 0.8)
    
    # Hành động chính — điền vào biểu mẫu
    username_field = driver.find_element(By.ID, "username")
    type_like_human(username_field, "myusername")

2. Tốc độ gõ văn bản biến đổi

Thay vì nhập văn bản ngay lập tức, hãy mô phỏng việc gõ từng ký tự với tốc độ biến đổi:

def type_like_human(element, text):
    """Nhập văn bản với mô phỏng tốc độ gõ của con người"""
    for char in text:
        element.send_keys(char)
        
        # Độ trễ cơ bản giữa các ký tự
        base_delay = random.uniform(0.05, 0.15)
        
        # Các khoảng dừng bổ sung ở các dấu cách và dấu câu
        if char in [' ', '.', ',', '!', '?']:
            base_delay += random.uniform(0.1, 0.3)
        
        # Các "sự chần chừ" ngẫu nhiên (5% xác suất về độ trễ dài)
        if random.random() < 0.05:
            base_delay += random.uniform(0.5, 1.5)
        
        time.sleep(base_delay)
    
    # Đôi khi mắc lỗi chính tả và sửa lại (10% xác suất)
    if random.random() < 0.1:
        time.sleep(random.uniform(0.2, 0.5))
        element.send_keys(Keys.BACKSPACE)
        time.sleep(random.uniform(0.1, 0.3))
        element.send_keys(text[-1])  # Nhập lại ký tự cuối cùng

3. Puppeteer: nhập văn bản chậm

Trong Puppeteer, có tùy chọn tích hợp delay cho phương thức type(), nhưng cần phải ngẫu nhiên hóa:

// Sử dụng cơ bản (KHÔNG được khuyến nghị — độ trễ cố định)
await page.type('#username', 'myusername', { delay: 100 });

// Cách tiếp cận đúng — ngẫu nhiên hóa cho mỗi ký tự
async function typeWithVariableSpeed(page, selector, text) {
  await page.click(selector);
  
  for (const char of text) {
    await page.keyboard.type(char);
    
    // Độ trễ ngẫu nhiên từ 50 đến 150 ms
    let delay = Math.random() * 100 + 50;
    
    // Độ trễ bổ sung ở các dấu cách
    if (char === ' ') {
      delay += Math.random() * 200 + 100;
    }
    
    // Các độ trễ dài ngẫu nhiên (5% xác suất)
    if (Math.random() < 0.05) {
      delay += Math.random() * 1000 + 500;
    }
    
    await page.waitForTimeout(delay);
  }
}

// Sử dụng
await typeWithVariableSpeed(page, '#username', 'myusername');

Chuyển động chuột tự nhiên và tốc độ cuộn

Selenium và Puppeteer theo mặc định không di chuyển con trỏ chuột — chúng ngay lập tức dịch chuyển nó đến điểm cần thiết và nhấp chuột. Đây là một trong những dấu hiệu rõ ràng nhất của sự tự động hóa. Để mô phỏng chuyển động chuột của con người, cần có các thư viện đặc biệt.

Thư viện pyautogui cho chuyển động chuột mượt mà

Thư viện pyautogui cho phép di chuyển con trỏ theo đường cong Bézier với gia tốc và giảm tốc:

import pyautogui
from selenium.webdriver.common.action_chains import ActionChains

def move_mouse_naturally(driver, element):
    """Chuyển động chuột mượt mà đến phần tử với mô phỏng con người"""
    # Lấy tọa độ của phần tử
    location = element.location
    size = element.size
    
    # Điểm mục tiêu (giữa phần tử + một chút ngẫu nhiên)
    target_x = location['x'] + size['width'] / 2 + random.randint(-5, 5)
    target_y = location['y'] + size['height'] / 2 + random.randint(-5, 5)
    
    # Chuyển động mượt mà với tốc độ biến đổi
    # duration — thời gian di chuyển (0.5-1.5 giây để thực tế)
    duration = random.uniform(0.5, 1.5)
    
    # tweening — hàm gia tốc (easeInOutQuad mô phỏng chuyển động của con người)
    pyautogui.moveTo(target_x, target_y, duration=duration, tween=pyautogui.easeInOutQuad)
    
    # Một khoảng dừng nhỏ trước khi nhấp chuột (con người không nhấp chuột ngay lập tức)
    time.sleep(random.uniform(0.05, 0.15))
    
    # Nhấp chuột
    element.click()

Quan trọng: Phương pháp này chỉ hoạt động nếu Selenium điều khiển một cửa sổ trình duyệt thực (không phải headless). Đối với chế độ headless, chuyển động chuột là vô ích, vì các hệ thống chống gian lận không thấy con trỏ.

Puppeteer: mô phỏng chuyển động chuột

Trong Puppeteer, bạn có thể sử dụng thư viện ghost-cursor để chuyển động con trỏ thực tế:

// Cài đặt: npm install ghost-cursor
const { createCursor } = require("ghost-cursor");
const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  const cursor = createCursor(page);
  
  await page.goto("https://example.com");
  
  // Chuyển động mượt mà đến phần tử và nhấp chuột
  const button = await page.$("#submit-btn");
  await cursor.click(button);  // Con trỏ di chuyển theo đường cong Bézier!
  
  // Hoặc — di chuyển đến tọa độ
  await cursor.move("#username");  // Chỉ di chuyển con trỏ mà không nhấp chuột
  await page.waitForTimeout(300);
  await cursor.click();  // Nhấp chuột ở vị trí hiện tại
})();

Mô phỏng cuộn

Con người không cuộn trang chính xác 500 pixel một lần. Việc cuộn cần phải không đều, với các khoảng dừng và đôi khi cuộn ngược lại:

def scroll_like_human(driver, target_position=None):
    """
    Mô phỏng việc cuộn của con người
    target_position: vị trí mục tiêu tính bằng pixel (nếu None — cuộn đến cuối)
    """
    current_position = driver.execute_script("return window.pageYOffset;")
    
    if target_position is None:
        # Cuộn đến cuối trang
        target_position = driver.execute_script("return document.body.scrollHeight;")
    
    while current_position < target_position:
        # Bước cuộn ngẫu nhiên (100-400 pixel)
        scroll_step = random.randint(100, 400)
        current_position += scroll_step
        
        # Cuộn
        driver.execute_script(f"window.scrollTo(0, {current_position});")
        
        # Khoảng dừng giữa các lần cuộn (con người đọc nội dung)
        time.sleep(random.uniform(0.3, 1.2))
        
        # Đôi khi cuộn ngược một chút (10% xác suất)
        if random.random() < 0.1:
            back_scroll = random.randint(50, 150)
            current_position -= back_scroll
            driver.execute_script(f"window.scrollTo(0, {current_position});")
            time.sleep(random.uniform(0.2, 0.6))

# Sử dụng
scroll_like_human(driver, target_position=2000)  # Cuộn đến 2000px

Thời gian tải trang và các yêu cầu AJAX

Các hệ thống chống gian lận phân tích không chỉ hành động của người dùng mà còn cả các đặc điểm tải trang. Các trình duyệt headless thường tải nhanh bất thường, vì chúng không tải hình ảnh, không thực hiện một số kịch bản, không render CSS.

Vấn đề: tải quá nhanh

So sánh các giá trị điển hình của Performance API cho một trình duyệt thông thường và headless:

Chỉ số Trình duyệt thông thường Headless (đáng ngờ)
domContentLoaded 800-2000 ms 50-200 ms
loadEventEnd 2000-5000 ms 100-500 ms
Số lượng tài nguyên đã tải 50-200 (hình ảnh, CSS, JS) 5-20 (chỉ những cái quan trọng)

Giải pháp: độ trễ tải cưỡng bức

Thêm một độ trễ nhân tạo sau khi tải trang để các chỉ số trông tự nhiên hơn:

def load_page_naturally(driver, url):
    """Tải trang với mô phỏng thời gian tải tự nhiên"""
    start_time = time.time()
    driver.get(url)
    
    # Chờ tải hoàn toàn DOM
    WebDriverWait(driver, 10).until(
        lambda d: d.execute_script("return document.readyState") == "complete"
    )
    
    # Tính toán thời gian tải thực tế
    actual_load_time = time.time() - start_time
    
    # Nếu tải quá nhanh (< 1 giây), thêm độ trễ
    if actual_load_time < 1.0:
        additional_delay = random.uniform(1.0, 2.5) - actual_load_time
        time.sleep(additional_delay)
    
    # Độ trễ bổ sung để "đọc trang"
    time.sleep(random.uniform(0.5, 2.0))

# Sử dụng
load_page_naturally(driver, "https://example.com")

Chờ các yêu cầu AJAX

Các trang web hiện đại tải nội dung một cách bất đồng bộ qua AJAX. Nếu kịch bản của bạn bắt đầu hành động trước khi tất cả các yêu cầu AJAX hoàn tất — điều này rất đáng ngờ. Sử dụng các chờ rõ ràng:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def wait_for_ajax(driver, timeout=10):
    """Chờ hoàn tất tất cả các yêu cầu AJAX (jQuery)"""
    WebDriverWait(driver, timeout).until(
        lambda d: d.execute_script("return jQuery.active == 0")
    )

# Đối với các trang không có jQuery — chờ một phần tử cụ thể
def wait_for_dynamic_content(driver, selector, timeout=10):
    """Chờ sự xuất hiện của phần tử được tải động"""
    WebDriverWait(driver, timeout).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, selector))
    )
    # Độ trễ bổ sung sau khi phần tử xuất hiện
    time.sleep(random.uniform(0.3, 0.8))

Cấu hình bảo vệ trong các trình duyệt chống phát hiện

Nếu bạn làm việc với các công việc như phân bổ, đa tài khoản hoặc các nhiệm vụ khác mà sự ẩn danh là rất quan trọng, hãy sử dụng các trình duyệt chống phát hiện: Dolphin Anty, AdsPower, Multilogin, GoLogin. Chúng có các cơ chế bảo vệ tích hợp chống lại các cuộc tấn công timing, nhưng cần được cấu hình đúng cách.

Dolphin Anty: cấu hình Human Typing

Trong Dolphin Anty có chức năng "Human Typing" — mô phỏng tự động việc gõ văn bản của con người. Cấu hình:

  • Mở hồ sơ trình duyệt → tab "Automation"
  • Bật "Mô phỏng Gõ văn bản của Con người"
  • Cấu hình các tham số:
    • Tốc độ gõ trung bình: 150-250 ký tự/phút (tốc độ thực tế)
    • Biến thể: 30-50% (biến động tốc độ giữa các ký tự)
    • Khoảng dừng ở dấu câu: bật (khoảng dừng ở các dấu câu)
    • Lỗi chính tả ngẫu nhiên: 2-5% (lỗi chính tả ngẫu nhiên với việc sửa chữa)

Sau đó, bất kỳ việc nhập văn bản nào qua API Dolphin sẽ tự động mô phỏng con người.

AdsPower: cấu hình Chuyển động Chuột

AdsPower cho phép ghi lại các mẫu chuyển động chuột của người dùng thực và phát lại chúng:

  1. Mở hồ sơ → "Cài đặt Nâng cao" → "Hành vi Chuột"
  2. Chọn chế độ "Ghi lại Người dùng Thực":
    • Mở trình duyệt ở chế độ thông thường
    • Thực hiện các hành động điển hình (nhấp chuột, cuộn, di chuyển chuột)
    • AdsPower sẽ ghi lại các quỹ đạo chuyển động
  3. Khi tự động hóa qua API, AdsPower sẽ phát lại các mẫu đã ghi với các biến thể

Multilogin: Canvas Noise và WebGL Timing

Multilogin thêm tiếng ồn (noise) vào Canvas và WebGL fingerprints, điều này ảnh hưởng đến các cuộc tấn công timing liên quan đến việc render:

  • Hồ sơ → "Cài đặt Fingerprint" → "Canvas"
  • Bật "Canvas Noise" (thêm độ trễ nhỏ vào việc render Canvas)
  • Bật "WebGL Metadata Masking" (che giấu các đặc điểm GPU, ảnh hưởng đến tốc độ render)

Điều này bảo vệ khỏi phát hiện thông qua phân tích thời gian thực hiện Canvas.toDataURL() và các thao tác WebGL.

Khuyến nghị: Nếu bạn làm việc với đa tài khoản trên Facebook, Instagram hoặc TikTok, hãy chắc chắn sử dụng các trình duyệt chống phát hiện kết hợp với các proxy dân cư chất lượng — điều này sẽ giảm thiểu rủi ro bị cấm chuỗi và phát hiện qua IP.

Các kỹ thuật nâng cao để vượt qua phát hiện timing

Đối với các nền tảng có bảo vệ đặc biệt (Google, Facebook, các trang web ngân hàng), các phương pháp cơ bản có thể không đủ. Chúng ta hãy xem xét các kỹ thuật nâng cao.

1. Thay thế Performance API

Có thể ghi đè các phương thức Performance API để trả về các giá trị thực tế thay vì thực:

// Tiêm kịch bản để thay thế performance.now()
const script = `
  (function() {
    const originalNow = performance.now.bind(performance);
    let offset = 0;
    let lastValue = 0;
    
    performance.now = function() {
      const realValue = originalNow();
      // Thêm tiếng ồn ngẫu nhiên vào thời gian
      const noise = Math.random() * 2 - 1; // từ -1 đến +1 ms
      let fakeValue = realValue + offset + noise;
      
      // Đảm bảo tính đơn điệu (thời gian không quay ngược)
      if (fakeValue <= lastValue) {
        fakeValue = lastValue + 0.1;
      }
      
      lastValue = fakeValue;
      return fakeValue;
    };
  })();
`;

// Puppeteer: tiêm khi tạo trang
await page.evaluateOnNewDocument(script);

Lưu ý: Phương pháp này có thể bị phát hiện thông qua kiểm tra tính toàn vẹn của các phương thức gốc. Chỉ sử dụng trên các trang web không có bảo vệ mạnh.

2. Throttling CPU và Mạng

Giao thức Chrome DevTools cho phép làm chậm CPU và mạng một cách nhân tạo, để các chỉ số tải trông tự nhiên hơn:

// Puppeteer: làm chậm CPU gấp 2 lần
const client = await page.target().createCDPSession();
await client.send('Emulation.setCPUThrottlingRate', { rate: 2 });

// Làm chậm mạng (mô phỏng 3G)
await page.emulateNetworkConditions({
  offline: false,
  downloadThroughput: 1.5 * 1024 * 1024 / 8, // 1.5 Mbps
  uploadThroughput: 750 * 1024 / 8,          // 750 Kbps
  latency: 40                                 // độ trễ 40ms
});

Điều này sẽ tăng thời gian tải trang và thực hiện JavaScript, làm cho hồ sơ trông giống như một người dùng thực với tốc độ internet trung bình.

3. Mô phỏng hoạt động nền

Người dùng thực không ngồi trên một tab — họ chuyển đổi giữa các tab, thu nhỏ cửa sổ, bị phân tâm. Hãy mô phỏng điều này:

async function simulateTabSwitch(page) {
  // Mô phỏng chuyển đổi sang tab khác (Page Visibility API)
  await page.evaluate(() => {
    Object.defineProperty(document, 'hidden', {
      get: () => true,
      configurable: true
    });
    
    document.dispatchEvent(new Event('visibilitychange'));
  });
  
  // Khoảng dừng (người dùng nhìn vào tab khác)
  await page.waitForTimeout(Math.random() * 3000 + 2000);
  
  // Quay lại tab
  await page.evaluate(() => {
    Object.defineProperty(document, 'hidden', {
      get: () => false,
      configurable: true
    });
    
    document.dispatchEvent(new Event('visibilitychange'));
  });
}

// Sử dụng: ngẫu nhiên "bị phân tâm" trong khi làm việc
if (Math.random() < 0.15) {  // 15% xác suất
  await simulateTabSwitch(page);
}

4. Sử dụng các dấu thời gian thực tế của User Timing

Một số trang web tạo ra các dấu thời gian riêng thông qua User Timing API. Thêm các dấu thời gian thực tế:

// Tạo các dấu thời gian thực tế
await page.evaluate(() => {
  // Mô phỏng "suy nghĩ" của người dùng trước hành động
  performance.mark('user-started-reading');
  
  setTimeout(() => {
    performance.mark('user-found-button');
    performance.measure('reading-time', 'user-started-reading', 'user-found-button');
  }, Math.random() * 2000 + 1000);
});

5. Xoay vòng proxy để giảm tương quan thống kê

Ngay cả khi mỗi phiên bản của kịch bản của bạn có các độ trễ ngẫu nhiên hóa, các hệ thống chống gian lận có thể phát hiện tương quan nếu tất cả các yêu cầu đến từ một IP. Sử dụng xoay vòng proxy:

  • Đối với việc thu thập dữ liệu và các nhiệm vụ hàng loạt: proxy trung tâm dữ liệu với xoay vòng tự động mỗi 5-10 phút
  • Đối với việc làm việc với mạng xã hội và quảng cáo: proxy dân cư với liên kết đến phiên (sticky sessions)
  • Đối với các nền tảng di động (Instagram, TikTok): proxy di động với xoay vòng theo thời gian hoặc theo yêu cầu

Việc xoay vòng IP giảm khả năng hệ thống chống gian lận có thể thu thập đủ dữ liệu để phân tích thống kê các mẫu timing của bạn.

Kết luận

Các cuộc tấn công timing — là một phương pháp phát hiện tự động hóa phức tạp, yêu cầu một cách tiếp cận toàn diện để bảo vệ. Các kết luận chính:

  • Không sử dụng các độ trễ cố định — luôn ngẫu nhiên hóa thời gian giữa các hành động bằng cách sử dụng phân phối chuẩn
  • Mô phỏng các độ trễ theo ngữ cảnh — các hành động khác nhau yêu cầu thời gian khác nhau (đọc trang ≠ nhấp chuột vào nút)
  • Thêm sự biến đổi vào thứ tự hành động — cuộn ngẫu nhiên, nhấp chuột, chuyển đổi tab
  • Sử dụng chuyển động chuột mượt mà — các thư viện ghost-cursor (Puppeteer) hoặc pyautogui (Selenium)
  • Mô phỏng tốc độ gõ văn bản tự nhiên — nhập từng ký tự với các khoảng dừng ở các dấu câu
  • Cấu hình các trình duyệt chống phát hiện — Dolphin Anty, AdsPower và Multilogin có các cơ chế bảo vệ tích hợp chống lại các cuộc tấn công timing
  • Kết hợp với các proxy chất lượng — xoay vòng IP giảm khả năng phân tích thống kê

Hãy nhớ: không có sự bảo vệ hoàn hảo. Các hệ thống chống gian lận liên tục tiến hóa, thêm các phương pháp phát hiện mới. Nhiệm vụ của bạn là làm cho hành vi của kịch bản gần giống với người dùng thực nhất có thể và thường xuyên cập nhật các phương pháp vượt qua.

Nếu bạn làm việc với tự động hóa trình duyệt cho việc thu thập dữ liệu, kiểm tra hoặc các nhiệm vụ khác, chúng tôi khuyên bạn nên sử dụng proxy dân cư — chúng cung cấp mức độ ẩn danh tối đa và giảm thiểu rủi ro phát hiện qua địa chỉ IP. Đối với các nền tảng di động, proxy di động là lựa chọn tốt hơn, mô phỏng người dùng thực của các nhà mạng di động.

```