Access Hub Scanner
Đang phát triểnĐồng bộ từ mã nguồn lúc 10:57, 03/10/2026
Skip to content

Bảo mật và cô lập tenant ​

Mô hình đe dọa của chính Access Hub Scanner: một công cụ bảo mật chạy đặc quyền trên hàng nghìn máy khách hàng, đọc cả nội dung tệp chứa bí mật và dữ liệu cá nhân, là mục tiêu hấp dẫn. Access Hub Scanner không đi qua Access Hub Agent hay Access Hub Collector (Q25, ADR 0001); mô hình đe dọa của hai sản phẩm đó (access-hub-collector/docs/07-security.md, access-hub-agent/docs/05-security.md) chỉ là tham khảo cho các phần Scanner chép mẫu (enroll, backoff). Tài liệu này nêu đủ phần của Scanner: bộ đọc, bộ gửi, vai trò ingest, matcher.

17 phút đọcCập nhật 03/10/2026access-hub-scanner, docs/09-security-and-tenancy.md

1. Tài sản ​

Tài sảnVì sao quan trọng
Máy chủ khách hàngScanner đọc được mọi tệp; nếu bị chiếm hoặc có lỗi, nó là cửa ngõ đặc quyền
Danh sách gói, kết quả kiểm tra, findingBản đồ điểm yếu của khách hàng: lộ ra là kẻ tấn công biết đánh vào đâu
DB lỗ hổng và khóa kýDB bị đầu độc thì giấu lỗ hổng thật hoặc gây báo động giả hàng loạt
Ngoại lệLạm dụng để giấu rủi ro khỏi lãnh đạo, kiểm toán
Bí mật và dữ liệu cá nhân trên máyScanner đọc chúng vào bộ nhớ khi quét nội dung; chúng không bao giờ được rời máy (ADR 0011)
Vị trí bí mật và dữ liệu cá nhân (finding nội dung)Bản đồ cho kẻ tấn công: biết tệp nào trên máy nào chứa khóa cloud, tệp nào chứa danh sách khách hàng
Khóa fingerprint K_host, K_companyLộ khóa cho phép thử đoán giá trị có không gian nhỏ khi có fingerprint
Kênh cấu hình quétNếu cho phép quá nhiều, thành kênh điều khiển máy

2. Quyền trên máy ​

2.1 Cần gì ​

Dữ liệuQuyền tối thiểu
/var/lib/dpkg/status, /etc/os-release, /proc/net/*, /proc/sys/*, phần lớn /etcNgười dùng thường
rpmdbThường đọc được bởi mọi người, cần kiểm chứng theo distro (S4)
/etc/shadow, /etc/gshadow, /etc/sudoers, /etc/sudoers.d/*, sshd_config trên một số distro, thư mục bị giới hạn khi duyệt tệpĐọc tệp bỏ qua quyền: CAP_DAC_READ_SEARCH
Nội dung tệp trong phạm vi quét nội dung, gồm thư mục nhà (/home, /root)CAP_DAC_READ_SEARCH cộng ProtectHome=read-only chỉ ở unit nội dung (ADR 0009 mục 6)
Trạng thái dịch vụ (P6, nếu Q44 đồng ý)Phương thức chỉ đọc của systemd qua D-Bus hệ thống (AF_UNIX), không cần capability thêm
Ánh xạ cổng sang tiến trìnhTruy cập /proc/<pid>/fd của tiến trình khác: cần quyền kiểu ptrace (CAP_SYS_PTRACE), mạnh hơn nhiều. Mặc định không cấp (Q17)
Danh sách luật tường lửaCAP_NET_ADMIN (cũng cho phép sửa luật). Mặc định không cấp (Q16)

2.2 Phương án ​

Phương ánĐánh giá
Chạy root đầy đủĐơn giản, nhưng lỗi parser thành chiếm máy với mọi quyền. Không chọn
Tài khoản accesshub-scanner + ambient CAP_DAC_READ_SEARCH, bounding set chỉ gồm capability đóKhuyến nghị. Đọc được mọi tệp, không ghi được tệp hệ thống, không đổi chủ sở hữu, không nạp module, không có mạng
Root nhưng CapabilityBoundingSet=CAP_DAC_READ_SEARCHDự phòng cho kernel không hỗ trợ ambient capability. Vẫn là uid 0 (sở hữu nhiều tệp), phải dựa vào ProtectSystem=strict để chặn ghi. Cần kiểm chứng trên CentOS 7 (kernel 3.10, systemd 219 thiếu nhiều chỉ thị bảo vệ) ở spike S4

2.3 Unit đề xuất (accesshub-scanner.service, chạy bởi accesshub-scanner.timer) ​

ini
[Service]
Type=oneshot
User=accesshub-scanner
Group=accesshub-scanner
AmbientCapabilities=CAP_DAC_READ_SEARCH
CapabilityBoundingSet=CAP_DAC_READ_SEARCH
NoNewPrivileges=yes
ExecStart=/usr/bin/accesshub-scanner scan
StateDirectory=accesshub-scanner
LogsDirectory=accesshub-scanner
ReadWritePaths=/var/lib/accesshub-scanner /var/log/accesshub-scanner
UMask=0027
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX
IPAddressDeny=any
SystemCallArchitectures=native
SystemCallFilter=@system-service
MemoryMax=192M
CPUQuota=50%
Nice=19
IOSchedulingClass=idle
LimitCORE=0
TimeoutStartSec=15min

2.3b Unit lượt nội dung (accesshub-scanner-content.service, chạy bởi accesshub-scanner-content.timer trong khung giờ yên tĩnh) ​

Giống unit trên, khác ở các dòng sau (ADR 0009):

ini
[Service]
ExecStart=/usr/bin/accesshub-scanner scan --content
ProtectHome=read-only
MemoryMax=256M
CPUQuota=25%
LimitCORE=0
TimeoutStartSec=4h
# Giới hạn băng thông IO theo thiết bị (tùy chọn, cgroup v2), đo ở S9:
# IOReadBandwidthMax=/ 16M

TimeoutStartSec là lưới an toàn; scanner tự dừng khi hết khung giờ, hết ngân sách CPU hoặc byte (SNFR-12, SNFR-14).

Ghi chú:

  • Không dùng PrivateNetwork=yes: /proc/net/tcp hiển thị socket của network namespace của tiến trình đọc, namespace riêng sẽ làm danh sách cổng nghe rỗng. Chặn mạng bằng RestrictAddressFamilies=AF_UNIX cộng IPAddressDeny=any.
  • ProtectHome=yes ở unit siêu dữ liệu khớp với việc kiểm tra AHS-FS-* không duyệt thư mục nhà (05 mục 5). Chỉ unit nội dung được đọc thư mục nhà, và chỉ đọc.
  • LimitCORE=0 ở cả hai unit: tiến trình giữ bí mật trong bộ nhớ không để lại core dump.
  • Bộ chỉ thị tham khảo unit của Agent (chép, không phụ thuộc); bộ gửi accesshub-scan-uploader có unit riêng: không capability, RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX, ProtectSystem=strict, ProtectHome=yes, chỉ ghi /var/lib/accesshub-scan-uploader, MemoryMax=32M. systemd cũ bỏ qua chỉ thị không biết kèm cảnh báo, nên mức bảo vệ thực tế phải đo theo distro (S4).

2.4 Đầu vào không tin cậy ngay trên máy ​

Scanner đặc quyền đọc tệp mà người khác có thể ảnh hưởng. Biện pháp:

  • Duyệt tệp chỉ lstat, không theo symlink, không đọc nội dung.
  • Mở tệp cấu hình bằng O_NOFOLLOW khi đường dẫn không được là symlink; với tệp nhạy cảm (sshd, sudoers, PAM) kiểm tra chủ sở hữu là root trước khi phân tích; tệp do người khác sở hữu thì báo fail ở kiểm tra quyền thay vì tin nội dung.
  • Mọi parser (dpkg status, rpmdb, apk, sshd_config, sudoers, login.defs, PAM, mountinfo) có giới hạn kích thước đọc, độ sâu Include, số dòng, và được fuzz trong CI (11).
  • Cấu hình từ trung tâm (config.pb) được kiểm tra lại ở bộ đọc dù ingest và bộ gửi đã kiểm tra.
  • Quét nội dung: chỉ mở tệp thường, O_NOFOLLOW | O_NONBLOCK, fstat sau khi mở để chắc vẫn là tệp đã lstat (chống đổi tệp giữa chừng), không mở FIFO, socket, thiết bị; regex là RE2 (thời gian tuyến tính, không ReDoS); bộ phân tích PEM, OpenSSH, JSON, YAML, OOXML có giới hạn kích thước, độ sâu, số phần tử, tỷ lệ nén; tất cả được fuzz.
  • Kẻ tấn công cục bộ có thể cố tình rải chuỗi giống bí mật để làm nhiễu (gây dương tính giả) hoặc tạo cây thư mục rất lớn để tiêu hết ngân sách: trần số mục, điểm dừng, độ phủ được báo cáo; không ảnh hưởng an toàn của máy.

3. Mô hình đe dọa (STRIDE rút gọn) ​

Đe dọaKịch bảnBiện pháp
SpoofingMáy A gửi báo cáo nhận là máy B hoặc công ty khácDanh tính chỉ từ chữ ký Ed25519 của máy Scanner tra trong registry (host_id); trường danh tính trong payload bị bỏ (07 mục 1, 3.0)
SpoofingLấy mã enroll để gắn máy lạ vào công tyMã một lần dùng, hết hạn 24 giờ, băm trong Access Hub, chỉ người có security.hosts.manage tạo; enroll đếm vào hạn mức và ghi audit; máy mới hiện trên trang máy Scanner để thu hồi
ElevationChiếm bộ gửi (có mạng) để đọc tệp của máyBộ gửi không capability, không đọc gì ngoài spool và thư mục của mình (systemd); khóa máy Scanner bị lộ chỉ cho gửi báo cáo giả của đúng máy đó, thu hồi trong Access Hub
TamperingKẻ có root trên máy sửa scanner hoặc báo cáo để giấu góiKhông ngăn được với kẻ đã có root. Phát hiện: inventory giảm đột ngột quá 50%, phiên bản scanner lùi, kernel_running khác kernel mà giám sát báo cho cùng Server (chỉ khi khách hàng có cả hai sản phẩm), chỉ gửi HASH_ONLY quá lâu trong khi kiểm kê Agent đổi. Finding hiển thị nhãn "tự báo cáo"
TamperingĐầu độc DB lỗ hổng (CDN, nguồn upstream, pipeline dựng)Chữ ký Ed25519 khóa riêng trong KMS hoặc HSM; kiểm tra hợp lý (số bản ghi không giảm quá 5%); bản cập nhật làm đóng hơn 1.000 finding vì advisory_changed trên toàn nền tảng bị giữ lại chờ người duyệt trước khi phát hành; dựng lại độc lập từ bản thô (30 ngày) để so băm
TamperingCấu hình quét độc hại từ trung tâm bị chiếmCấu hình chỉ bật, tắt mã có sẵn và ngưỡng số học; không đường dẫn tùy ý để đọc (loại trừ chỉ làm giảm phạm vi), không lệnh; kiểm tra ở ba nơi
RepudiationNgười dùng phủ nhận đã chấp nhận rủi roNgoại lệ Auditable, người duyệt khác người yêu cầu, hạn bắt buộc
Information disclosureBáo cáo chứa bí mậtDanh sách trắng bằng chứng trong mã, giới hạn ở ingest, kiểm thử "không lộ bí mật" với fixture chứa bí mật giả (11)
Information disclosureCông ty A xem gói, finding của BMục 6
Information disclosureDò bảng CVE toàn cục để biết có khách hàng dính CVE XKhông có endpoint liệt kê security_vulnerabilities cho tenant, chỉ join qua finding của mình (08 mục 2)
Information disclosureNhân viên nền tảng đọc dữ liệu quétKhông màn hình, không phiên truy cập; chỉ thống kê ẩn danh có ngưỡng k
DoSScanner làm chậm máyCPUQuota, MemoryMax, Nice, IOSchedulingClass=idle, trần số inode, TimeoutStartSec
DoSBáo cáo khổng lồ làm sập secmatchGiới hạn 07 mục 3.2, tốc độ 6 mỗi giờ mỗi máy Scanner; ingest tách khỏi matcher
ElevationLỗi parser trong scanner đặc quyềnKhông mạng, chỉ một capability, không ghi được tệp hệ thống, fuzz, Go an toàn bộ nhớ, không CGO
ElevationBiến scanner thành kênh khắc phục từ xaKhông có mã thực thi (ADR 0003); thêm khắc phục tự động cần ADR mới thay thế ADR 0003 và ADR 0005 của Agent (Q7)
Information disclosureGiá trị bí mật hoặc dữ liệu cá nhân rời máy qua báo cáo, log, lỗi, core dumpKiểu kết quả detector không có trường giá trị; preview giới hạn, rỗng với dữ liệu cá nhân; log có kiểu, không chuỗi tự do từ nội dung tệp; LimitCORE=0; kiểm tra lớp hai ở Collector; bộ "không giá trị rời máy" là cổng phát hành (ADR 0011)
Information disclosureDò ngược fingerprint bằng cách thử mọi số điện thoại, CCCDDữ liệu cá nhân và bí mật entropy thấp dùng K_host không rời máy; K_company chỉ cho bí mật entropy cao (ADR 0011 mục 3)
Information disclosureBản build scanner bị chiếm giấu giá trị trong fingerprint hoặc đường dẫnChuỗi cung ứng (mục 4), review hai người cho mã trong ranh giới che giấu; giới hạn định dạng ở ingest chỉ làm hẹp kênh (R17)
Information disclosureTài khoản Access Hub bị chiếm dùng danh sách vị trí bí mật làm bản đồ tấn côngQuyền security.secrets.view, security.pii.view tách khỏi security.view; thông báo, webhook không đường dẫn; audit khi xem chi tiết và xuất; khuyến nghị 2FA (R21)
TamperingCấu hình trung tâm bị chiếm đặt gốc tùy chọn để dùng scanner như "máy dò" nội dungGốc chỉ trong giới hạn (16 mục, danh sách cấm cứng), detector biên dịch sẵn nên không hỏi được câu tùy ý về nội dung, kết quả chỉ là các trường ADR 0011; quản trị viên máy phủ quyết bằng allow_central_roots = false, deny_roots; audit ở Access Hub
DoSLượt nội dung làm chậm máy sản xuấtKhung giờ yên tĩnh, CPUQuota=25%, IO idle, giới hạn tốc độ, PSI, POSIX_FADV_DONTNEED, tăng dần (ADR 0009)

4. Chuỗi cung ứng ​

  • Binary tĩnh CGO_ENABLED=0, -trimpath, Go ghim phiên bản, govulncheck, osv-scanner trên chính phụ thuộc, SBOM CycloneDX mỗi bản phát hành, gói .deb, .tar.gz (sau này .rpm) phát hành như artifact riêng (Q21); ký gói bằng khóa riêng của Scanner.
  • Gói accesshub-scanner chứa bộ đọc và bộ gửi, không khai báo phụ thuộc gói accesshub-agent và ngược lại (Q25, ADR 0001). Mã mẫu từ repo Agent chỉ được chép, có ghi nguồn.
  • Phụ thuộc mới (thư viện rpmdb, SQLite thuần Go) phải xem xét giấy phép, kích thước, bảo trì trước khi dùng (P0, ADR 0007).
  • Secmatch: image distroless, không shell, chạy không root.
  • Khóa ký DB riêng, khác khóa ký gói, khóa cập nhật của Agent, khóa DeploymentLicense (Q23). Nhiều khóa công khai nhúng trong secmatch để xoay.

5. Tối thiểu hóa dữ liệu ​

Gửi điKhông bao giờ gửi
Hệ điều hành, kernel đang chạy và đã càiNội dung tệp
Gói: tên, phiên bản, kiến trúc, gói nguồn, nhà phát hành, moduleDanh sách tệp của gói
Socket đang nghe: giao thức, địa chỉ, cổngTên tiến trình đầy đủ, dòng lệnh, biến môi trường, danh sách tiến trình
Kết quả kiểm tra: trạng thái và bằng chứng trong danh sách trắng (giá trị chỉ thị như PermitRootLogin=yes, giá trị sysctl, chế độ và chủ sở hữu tệp, tối đa 50 đường dẫn cho kiểm tra tệp)Băm mật khẩu, khóa riêng, chứng chỉ riêng, token, nội dung dòng sudoers đầy đủ
Tên tài khoản liên quan (AHS-AUTH-001, 002, 006) nếu Q12 đồng ýThư mục nhà, lịch sử lệnh, nội dung mạng, địa chỉ MAC
Thống kê lần quét (thời gian, CPU, RSS, số tệp đã duyệt, mã lỗi)Thông điệp lỗi thô có thể chứa nội dung tệp (chỉ gửi mã lỗi)
Finding nội dung: mã detector, đường dẫn, dòng, cột, preview che giấu (chỉ bí mật dài từ 16 ký tự), fingerprint có khóa, mức độ, mốc thời gian, match_count, confidence, exposure (ADR 0011)Giá trị bí mật, dữ liệu cá nhân dưới mọi dạng; đoạn văn bản quanh vị trí khớp; tên khóa cấu hình; claim JWT; tên người dùng trong chuỗi kết nối; độ dài chính xác của giá trị
Thống kê tệp theo gốc, tệp đáng chú ý (siêu dữ liệu)Danh sách đầy đủ mọi tệp (ở lại trong chỉ mục cục bộ)
Dịch vụ, phần mềm ngoài gói (tên, phiên bản, đường dẫn, purl)Cấu hình của dịch vụ, biến môi trường của unit
Thống kê lượt nội dung (độ phủ, byte đã đọc, số lần nhường, rules_version)K_host

Tên tài khoản và đường dẫn có thể là dữ liệu cá nhân hoặc nhạy cảm (ví dụ tên người trong tên tài khoản): là dữ liệu vận hành nội bộ của công ty, lưu có cô lập tenant, không mã hóa ứng dụng (theo quyết định ENC-2: chỉ bí mật mới mã hóa), xóa khi xóa máy hoặc công ty.

6. Cô lập tenant ​

LớpBiện phápKiểm thử
MáySpool chỉ chứa dữ liệu của máy đó; bộ gửi ký bằng khóa của máy ScannerKhông áp dụng
Ingest (secmatch)Danh tính từ registry máy Scanner theo chữ ký, bỏ trường danh tính trong payload, khử trùng theo host_id, kiểm giấy phép theo công tyMa trận hai tenant cho /scan/v1/*: hai công ty, cùng report_id, khóa máy của A ký báo cáo khai là B, mã enroll của A dùng cho B
SecmatchMọi bảng có company_id, khóa chính gồm company_id; mọi truy vấn qua lớp truy cập bắt buộc tham số company_id; API nội bộ không có endpoint "tất cả công ty" trừ stats/global (đã gộp, ngưỡng k); xóa theo công ty có bia mộHai công ty có cùng server_id giả, cùng gói: tra cứu, tìm gói, xóa của A không thấy, không đụng B; fuzz tham số truy vấn
Access HubCompanyScope trên mọi model tenant, company_id, server_id gửi secmatch lấy từ bản ghi, không từ tham số; sự kiện từ secmatch kiểm tra máy thuộc công tyPest hai công ty cho mọi endpoint, job, xuất, thông báo, webhook
Nền tảngBảng thống kê không định danh công ty, ngưỡng kKiểm thử cấu trúc bảng và ngưỡng
DB lỗ hổngDữ liệu toàn cục công khai, không chứa dữ liệu khách hàngKiểm thử gói DB không chứa trường nào từ inventory
Finding nội dungTrạng thái ở secmatch khóa theo (company_id, server_id); finding_key gồm company_id; fingerprint c dùng khóa riêng từng công ty nên không so được chéo công ty; tra "cùng bí mật trên N máy" luôn lọc theo company_idHai công ty có cùng bí mật canary trên máy: fingerprint khác nhau, không thấy nhau; xóa của A không đụng B
K_companySinh và mã hóa theo từng công ty (ENC-2), chỉ phát xuống máy Scanner của công ty đó qua GET /scan/v1/configMáy Scanner công ty A không nhận khóa của B (ma trận hai tenant ở ingest)
Thống kê nền tảng về nội dungChỉ số đếm theo họ detector, ngưỡng k; không đường dẫn, fingerprint, previewKiểm thử cấu trúc bảng

7. Bí mật (ENC-2) ​

Bí mậtNơi giữ
Token ingest và token admin của secmatchKho bí mật của nền tảng triển khai (biến môi trường, secret manager), không vào repo
Token Sanctum của tài khoản dịch vụ secmatchNhư token dịch vụ hiện có của Access Hub; Access Hub chỉ giữ băm
Khóa riêng Ed25519 của máy ScannerChỉ trên máy, /var/lib/accesshub-scan-uploader/host.key (0600, chủ accesshub-scan-uploader), sinh lúc enroll; trung tâm chỉ giữ khóa công khai
Mã enroll ScannerAccess Hub giữ băm SHA-256, bản rõ chỉ hiện một lần
API key NVDKho bí mật của hạ tầng secdb-build, không bao giờ vào gói DB hay secmatch của khách hàng
Khóa riêng ký DBKMS hoặc HSM, không có trên máy dựng thường
Bí mật webhookĐã có cơ chế ENC-2 với khóa theo công ty (CompanyCrypto)
K_company (khóa fingerprint theo công ty)Access Hub, mã hóa bằng CompanyCrypto (ENC-2); phát xuống qua SecurityConfig trên TLS; trên máy ở config.pb (0640, chủ accesshub-scan-uploader, bộ đọc đọc bằng CAP_DAC_READ_SEARCH) và tệp khóa của scanner (0600); không log
K_host (khóa fingerprint theo máy)Chỉ trên máy, /var/lib/accesshub-scanner/keys/fp_host.key (0600), sinh lúc cài, không bao giờ gửi đi

Finding (kể cả finding nội dung, vì chúng không chứa giá trị), gói, kết quả kiểm tra, ngoại lệ không mã hóa ứng dụng (phải tìm kiếm, lọc). Mã hóa đĩa theo chính sách hạ tầng.

8. Danh sách kiểm tra trước mỗi bản phát hành ​

  • [ ] Kiểm thử hai công ty đạt ở ingest, matcher, Access Hub.
  • [ ] Bộ "không giá trị rời máy" (canary cho mọi detector, mọi đầu ra, mọi tầng) đạt.
  • [ ] Precision và recall của detector không giảm so với bản trước (SNFR-47, SNFR-48).
  • [ ] Ngân sách lượt nội dung đạt trên ma trận, p99 tải chuẩn không xấu đi (SNFR-12 đến SNFR-17).
  • [ ] Review hai người cho mọi thay đổi trong ranh giới che giấu (internal/detect, dựng phần nội dung của báo cáo).
  • [ ] Fuzz các parser trong thời gian giới hạn không lỗi.
  • [ ] Unit systemd được kiểm bằng systemd-analyze security trên các distro hỗ trợ, điểm không kém bản trước.
  • [ ] Gói ký, SBOM đính kèm, govulncheck sạch.
  • [ ] Xác minh chữ ký DB từ máy sạch; thử DB sai chữ ký và DB hạ phiên bản bị từ chối.
Trang này có giúp được bạn không?
Sửa trang này

Nội dung đồng bộ từ kho mã access-hub-scanner lúc 10:57, 03/10/2026. Khi tài liệu và mã khác nhau, mã thắng.