ARTEX 安全排查、项目搭建与本地镜像部署

整理日期:2026-11-05
适用环境:Windows 11、PowerShell、Docker Desktop、WSL2

文档结构

  1. 危险项目信息与后门 IOC
  2. 本机安全排查命令
  3. ARTEX 项目搭建与本地构建
  4. 本地镜像拉取、保存、加载与启动

脱敏说明: 本文不包含真实数据库密码、API Key、Token、Windows 用户名或不必要的本机专属标识。公开告警中的仓库名、镜像名和威胁特征予以保留,以便安全排查。

重要边界: 告警内容中的后门行为应视为待核验威胁情报。文档会区分告警指称、源码审查结果和本机检查结果,不因单一 IOC 命中或未命中直接判定感染或安全。


第一部分:危险项目信息与后门 IOC

1. 风险摘要

告警描述了一起 ARTEX 二开仓库的 Docker 镜像供应链投毒事件:

  • 二开仓库据称只修改 docker-compose.yml 中的 ARTEX 镜像地址。
  • 源码可能与正常项目相似,但运行时拉取的预编译镜像来自另一个 Docker
    Hub 命名空间。
  • 被报告的恶意逻辑位于登录接口处理路径,而不是必须能从公开源码中直接发现。
  • 后门被指称可在认证前执行系统命令,并将执行结果返回给请求方。

安全原则:源码干净不等于镜像可信。 必须核对仓库 remote、Compose
实际镜像、镜像 digest、二进制哈希和构建来源。

2. 需要重点关注的项目和镜像


类型 名称 / 特征 处理建议


被告警指称的二开仓库 trhhubsd/ARTEX 暂停使用;核对仓库和提交历史

告警提及的可疑提交 a4f4d38 对比该提交的 Compose 镜像地址变更

被告警指称的镜像 tomicdd/artex 不要拉取或运行;排查本机镜像、容器和历史

告警中原始镜像写法 autumn27/artex:${ARTEX_TAG:-latest} 仅作为告警所述对照,不代表当前可直接信任或仍可用

告警中被替换的镜像写法 tomicdd/artex:${ARTEX_TAG:-latest} 高风险 IOC

告警提到该恶意镜像拉取量接近 7,954 次、相关仓库约 1.3k
Star。这些数字属于告警中的统计说法,具有时间性,本文不将其作为独立核实的当前数据。

3. 被报告的后门行为

被报告的入口:

POST /api/auth/login

被报告的逻辑特征:

  1. 登录 JSON 请求中额外读取 captcha / Captcha 字段。
  2. 字段内容若以 ! 开头,则去掉 !。
  3. 将剩余内容交给 Shell(告警描述为 sh -c)执行。
  4. 执行发生在正常用户名、密码认证之前。
  5. 命令输出通过 HTTP 响应返回。
  6. 命令在容器内以 root
    身份执行(这是告警所述影响,不代表所有部署都必然具有相同容器权限)。

告警提供的特征字符串:

captcha
Captcha
verifyCaptcha
/api/auth/login
sh -c

不要对公网目标发送利用请求。
这些字符串用于源码审查、日志排查和本地隔离取证。

4. IOC:摘要和哈希

告警原文提供的镜像 digest 只有缩写形式:

sha256:ce85d836...392745e

这是不完整摘要,不能直接作为精确 digest
比对值。需要从原始威胁情报、镜像仓库取证记录或可信扫描报告获取完整 64
位十六进制摘要后再做精确匹配。

不要把未经原始来源确认的补全哈希当成 IOC。精确比对时必须使用完整
digest。

5. 如何识别危险配置

危险配置示例:

services:
  artex:
    image: tomicdd/artex:${ARTEX_TAG:-latest}

本地构建部署的预期配置(本机项目当前采用的方式):

services:
  artex:
    image: artex:local

检查 Compose 实际使用的镜像:

docker compose config --images

检查仓库 remote:

git remote -v

6. 当前项目来源说明

本机此前 git remote -v 记录为:

https://github.com/Hinln/ARTEX.git

这是本机当前克隆项目的来源记录,不应仅凭仓库名称推断它是原作者唯一官方维护仓库。使用前仍需核对仓库说明、提交历史、上游来源和许可证。

7. 参考来源与证据等级

结论边界: 将 tomicdd/artex 等作为高优先级 IOC
排查;只有在获得镜像、二进制或行为证据后,才能对具体主机是否感染下结论。


第二部分:本机安全排查命令

0. 设置项目路径

$ProjectRoot = "D:\Path\To\ARTEX"  # 改为本机 ARTEX 项目目录
Set-Location $ProjectRoot

排查期间优先使用只读命令。取证完成前不要删除容器、镜像、数据卷或日志。

1. 核对 Git 来源和工作区

git remote -v
git rev-parse HEAD
git status --short
git log -5 --oneline --decorate

检查: - remote 是否为自己预期的仓库。 -
是否存在不认识的提交、脚本或工作区修改。 - 是否有人修改过
docker-compose.yml 中的镜像命名空间。

2. 检查镜像和容器

docker images --digests --no-trunc |
  Select-String -Pattern "artex|tomicdd|autumn27|trhhubsd"

docker ps -a --no-trunc |
  Select-String -Pattern "artex|tomicdd|autumn27|trhhubsd"

docker ps -a --no-trunc --filter ancestor=tomicdd/artex

检查 Compose 实际镜像:

docker compose config --images
docker compose ps

检查镜像元数据:

docker image inspect artex:local --format `
'ID={{.Id}}
RepoTags={{json .RepoTags}}
RepoDigests={{json .RepoDigests}}
Created={{.Created}}'

注意:当前镜像清单没有命中,只能说明目前仍保留的镜像中未发现;不能证明历史上从未拉取或运行过恶意镜像。

3. 检查 Compose 是否引用危险镜像或开放端口

Select-String -Path .\docker-compose.yml `
  -Pattern 'image:|build:|privileged:|docker.sock|network_mode:|8787|8788'

docker compose config --images

重点检查: - ARTEX 是否使用经过审计的本地镜像 artex:local。 - 是否出现
tomicdd/artex 等未知镜像命名空间。 - 是否启用 privileged: true。 -
是否挂载 Docker Socket。 - Web/API 端口是否只绑定 127.0.0.1。

4. 检查登录后门字符串

Select-String -Path .\server\auth.go `
  -Pattern 'func .*authLogin|captcha|verifyCaptcha|exec.Command|CommandContext' `
  -Context 8,18

git grep -n -i -E `
  'verifyCaptcha|captcha|exec\.Command|os/exec|/bin/sh|sh -c' `
  -- '*.go'

重点审查: - 登录请求结构体是否出现 captcha / Captcha。 - 是否出现
verifyCaptcha。 - 是否在密码校验前执行系统命令。 - 是否将 HTTP
请求参数拼接到 Shell 命令。 - 是否把命令输出返回给未认证请求者。

说明:exec.CommandContext
本身不等于后门;需要结合调用链、输入来源、授权检查和执行权限判断。

5. 审查自定义工具执行逻辑

Select-String -Path .\server\customtool.go `
  -Pattern 'exec.CommandContext|CommandContext|interp|tmp' `
  -Context 12,20

Get-Content .\server\customtool.go |
  Select-Object -Skip 330 -First 110

重点检查命令白名单、人工审批、执行超时、工作目录限制、临时脚本权限和参数注入风险。

6. 审查自动更新逻辑

Get-Content .\selfupdate\bootstrap.go |
  Select-Object -First 240

Get-ChildItem .\selfupdate -Recurse -File |
  Select-String -Pattern 'http|https|Download|WriteFile|Rename|exec.Command|github'

检查下载来源、TLS、签名或哈希校验、文件替换和回滚逻辑。不要只审
start.sh:启动脚本负责启动和重启,更新逻辑在 Go 程序中。

7. 检查容器权限、挂载和运行身份

docker inspect artex-artex-1 --format `
'Privileged={{.HostConfig.Privileged}}
ReadonlyRootfs={{.HostConfig.ReadonlyRootfs}}
CapAdd={{json .HostConfig.CapAdd}}
CapDrop={{json .HostConfig.CapDrop}}
SecurityOpt={{json .HostConfig.SecurityOpt}}
NetworkMode={{.HostConfig.NetworkMode}}
PidMode={{.HostConfig.PidMode}}
Mounts={{json .Mounts}}'

docker exec artex-artex-1 id
docker inspect artex-artex-1 --format '{{json .Mounts}}'

检查容器是否以 root 运行、是否有额外
capabilities、是否挂载宿主机敏感目录或 Docker Socket。

8. 比较容器二进制与本地构建产物

docker exec artex-artex-1 sh -c 'sha256sum /app/artex'

docker cp artex-artex-1:/app/artex .\artex-container-copy
Get-FileHash .\artex-container-copy -Algorithm SHA256

Get-FileHash .\dist\amd64\artex -Algorithm SHA256

容器文件和本地构建产物 SHA-256
一致,才能证明二者字节一致。哈希不同需要调查构建产物、容器创建时间和镜像来源。

9. 检查运行日志

docker compose logs --tail 200 artex
docker compose logs --tail 200 postgres

检查异常登录、未知下载地址、意外进程启动、异常重启和不认识的更新记录。

10. 检查 PowerShell 历史中的可疑镜像命令

$history = "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"

if (Test-Path $history) {
  Select-String -Path $history -Pattern `
    'tomicdd/artex|trhhubsd/ARTEX|docker pull .*artex|docker compose'
}

历史记录可能不完整或已被清理;无命中不能证明从未执行。

11. 检查 Windows 持久化线索(只读初筛)

Get-ScheduledTask |
  Select-Object TaskName, TaskPath, State

Get-CimInstance Win32_Process |
  Select-Object ProcessId, ParentProcessId, Name, ExecutablePath

$sshKeys = "$env:USERPROFILE\.ssh\authorized_keys"
if (Test-Path $sshKeys) {
  Get-Item $sshKeys | Select-Object FullName, Length, LastWriteTime
}

不要仅凭进程名或计划任务名称判定恶意;需要结合路径、签名、创建时间和行为分析。

12. 排查后处置原则

若发现可疑镜像或容器: 1. 先记录镜像 ID、RepoDigest、容器
inspect、创建时间、日志和挂载信息。 2.
保存必要证据后,停止可疑容器并隔离网络。 3.
不要直接删除数据卷;先评估是否含有证据、凭据或业务数据。 4.
从已核验源码重新构建镜像。 5. 轮换可能暴露的 API Key、GitHub
Token、数据库密码和其他凭据。 6. 检查宿主机持久化和外联行为。

本文件是排查清单,不是感染判定器。没有命中 IOC 不代表绝对安全。


第三部分:ARTEX 项目搭建与本地构建

1. 环境准备

需要: - Windows 11 - Docker Desktop(Linux containers / WSL2
backend) - Git - Node.js 与 npm - Go 工具链 - PowerShell

检查版本:

git --version
node -v
npm -v
go version
docker version
docker compose version

2. 获取源码

新机器克隆:

$ProjectRoot = "D:\Path\To\ARTEX"  # 改成希望放置项目的路径
git clone https://github.com/Hinln/ARTEX.git $ProjectRoot
Set-Location $ProjectRoot

已有项目不要重复 clone;先核对:

git remote -v
git rev-parse HEAD
git status --short

保留本地修改。不要盲目执行 git reset --hard 或 git clean -fd。

3. 安装前端依赖

Set-Location "$ProjectRoot\web"
npm ci

npm ci 使用 package-lock.json 安装锁定版本依赖。

4. 构建静态前端

项目静态构建脚本使用 POSIX 环境变量写法。PowerShell 下使用:

$env:NEXT_EXPORT = "1"
npx next build

$buildCode = $LASTEXITCODE
Remove-Item Env:NEXT_EXPORT -ErrorAction SilentlyContinue

if ($buildCode -ne 0) {
  throw "Next.js 静态构建失败,停止后续步骤"
}

Test-Path .\out

预期生成 web\out。

5. 复制前端文件到 Go embed 目录

Set-Location $ProjectRoot

if (Test-Path .\server\webui\dist) {
  Remove-Item .\server\webui\dist -Recurse -Force
}

New-Item -ItemType Directory .\server\webui\dist -Force |
  Out-Null

Copy-Item .\web\out\* .\server\webui\dist\ -Recurse -Force

Test-Path .\server\webui\dist\index.html

6. 下载并验证 Go 依赖

Set-Location $ProjectRoot
go mod download
go mod verify

只有 go mod verify 成功,才能说明本地模块缓存与 Go module
校验信息一致;它不是完整的源码安全审计。

7. 编译 Linux/amd64 二进制

Windows 默认编译结果不能直接运行在 Linux 容器中,需要交叉编译:

Set-Location $ProjectRoot

New-Item -ItemType Directory .\dist\amd64 -Force |
  Out-Null

$env:GOOS = "linux"
$env:GOARCH = "amd64"
$env:CGO_ENABLED = "0"

go build -tags embedui -o .\dist\amd64\artex .\cmd\artex

$buildCode = $LASTEXITCODE

Remove-Item Env:GOOS -ErrorAction SilentlyContinue
Remove-Item Env:GOARCH -ErrorAction SilentlyContinue
Remove-Item Env:CGO_ENABLED -ErrorAction SilentlyContinue

if ($buildCode -ne 0) {
  throw "Go Linux/amd64 编译失败"
}

检查 ELF 文件头:

$bytes = [System.IO.File]::ReadAllBytes(
  (Resolve-Path .\dist\amd64\artex)
)
[BitConverter]::ToString($bytes, 0, 4)

预期:

7F-45-4C-46

记录构建信息和哈希:

go version -m .\dist\amd64\artex
Get-FileHash .\dist\amd64\artex -Algorithm SHA256

8. 检查 Dockerfile

Dockerfile 应将预编译的 Linux 二进制复制到运行镜像,例如:

ARG TARGETARCH
COPY dist/${TARGETARCH}/artex /app/artex

如需让构建阶段使用代理,Dockerfile 应在相应 RUN
指令前声明代理构建参数:

ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG http_proxy
ARG https_proxy

APT 网络不稳定时,可把 Debian 源改为 HTTPS,并在 apt-get update 使用:

-o Acquire::http::Pipeline-Depth=0
-o Acquire::https::Pipeline-Depth=0
-o Acquire::ForceIPv4=true

Dockerfile 多行 RUN 命令的 \ 必须放在续行行尾,不要单独放一行。

9. 构建本地镜像

如果 HTTP 代理监听 Windows 的 127.0.0.1:8080,Docker
容器访问宿主机代理应使用 host.docker.internal:8080。

通过代理构建:

Set-Location $ProjectRoot

docker buildx build --load --platform linux/amd64 `
  --build-arg TARGETARCH=amd64 `
  --build-arg HTTP_PROXY=http://host.docker.internal:7890 `
  --build-arg HTTPS_PROXY=http://host.docker.internal:7890 `
  --build-arg http_proxy=http://host.docker.internal:7890 `
  --build-arg https_proxy=http://host.docker.internal:7890 `
  -t artex:local .

不使用代理:

docker buildx build --load --platform linux/amd64 `
  --build-arg TARGETARCH=amd64 `
  -t artex:local .

确认镜像:

docker image inspect artex:local --format 'ID={{.Id}} Created={{.Created}}'
docker image ls artex

10. 配置 Compose 和环境文件

Compose 的 ARTEX 服务应使用本地镜像:

artex:
  image: artex:local

端口建议仅绑定本机:

ports:
  - "127.0.0.1:8787:8787"
  - "127.0.0.1:8788:8788"

如果没有 .env,可以从模板创建:

Set-Location $ProjectRoot

if (-not (Test-Path .\.env)) {
  Copy-Item .\.env.example .\.env
}

编辑 .env,设置强随机 POSTGRES_PASSWORD,按需设置模型服务 API
Key。不要把 .env 内容贴到公开聊天、提交到 Git 或写进报告。

验证 Compose:

docker compose config --quiet
if ($LASTEXITCODE -ne 0) {
  throw "Compose 配置无效"
}

11. 启动和验证

docker compose up -d --no-build
docker compose ps
docker compose logs --tail 100 artex
curl.exe --noproxy "*" -I http://127.0.0.1:8787

浏览器访问:

http://127.0.0.1:8787

12. 重要说明

  • 当前 Compose 若只有 image: artex:local、没有 build:,则
    docker compose build 不会替你构建该镜像;使用上面的
    docker buildx build。
  • --build-arg 主要影响 Dockerfile RUN 构建阶段;不保证解决 Docker
    Hub 拉取基础镜像、Dockerfile frontend 或 Registry token 的问题。
  • # syntax=docker/dockerfile:1 可能触发 BuildKit 拉取 Dockerfile
    frontend。若网络无法访问 Docker Hub,先备份
    Dockerfile,再考虑移除该行并使用 BuildKit 内置 frontend;需确认
    Dockerfile 语法兼容。
  • 构建成功不代表源码安全。构建前应完成危险字符串、更新机制、自定义命令执行和依赖审查。

第四部分:本地镜像拉取、保存、加载与启动

1. 先区分三种情况


场景 正确方式


本机已经构建 artex:local docker image ls 检查,不需要 pull

本机没有镜像,但有源码 按本地构建执行
docker buildx build --load

另一台电脑需要使用已构建镜像 在原机器 docker save,在新机器
docker load

需要 PostgreSQL 基础镜像 docker pull postgres:16-alpine

不要执行 docker pull artex:local 来获取本地构建镜像。
artex:local 不是公共 Registry 地址;Docker 会尝试从默认 Registry
查找它,通常会失败。

2. 检查本机是否已有 ARTEX 镜像

docker image ls artex
docker image inspect artex:local

如果镜像存在,可直接启动:

Set-Location "D:\Path\To\ARTEX"  # 改成实际项目目录
docker compose up -d --no-build
docker compose ps

3. 拉取 PostgreSQL 基础镜像

当前 Compose 使用:

postgres:
  image: postgres:16-alpine

拉取命令:

docker pull postgres:16-alpine
docker image inspect postgres:16-alpine

注意:标签可能随上游更新而变化。长期或生产环境应核对并固定经过验证的
digest。

4. 将本机 ARTEX 镜像导出成文件

在已经有 artex:local 的电脑上:

docker image inspect artex:local
docker save -o .\artex-local.tar artex:local
Get-FileHash .\artex-local.tar -Algorithm SHA256

将 artex-local.tar
通过可信介质传到另一台电脑。不要把镜像文件上传到公开网盘或公开仓库,因为镜像可能包含内部配置、工具和代码。

5. 在另一台电脑导入镜像

docker load -i .\artex-local.tar
docker image ls artex
docker image inspect artex:local

如果 Compose 项目也在新电脑上,进入项目目录并启动:

Set-Location "D:\Path\To\ARTEX"
docker compose config --quiet
docker compose up -d --no-build
docker compose ps

确保新电脑上已经准备好正确的 .env,不要复制或公开含真实密钥的文件。

6. 如果需要从私有 Registry 拉取

只有当团队已经把镜像推送到自己控制、经过审计的 Registry 时,才使用:

docker login <可信Registry域名>
docker pull <可信Registry域名>/<项目镜像>:<固定版本标签>
docker image inspect <可信Registry域名>/<项目镜像>:<固定版本标签>

更推荐固定 digest:

docker pull <可信Registry域名>/<项目镜像>@sha256:<完整且已核验的digest>

以上是模板命令,尖括号内容必须替换为实际可信 Registry 和完整
digest;不要把占位符原样执行。

7. 不要拉取的可疑镜像

根据收到的安全告警,排查时重点关注:

tomicdd/artex

不要为了"验证是否有毒"而在日常工作环境中拉取或运行可疑镜像。若必须取证,应在隔离实验环境中由安全人员按证据保全流程处理。

8. 常用启动与维护命令

启动:

docker compose up -d --no-build

状态:

docker compose ps
docker image ls artex

日志:

docker compose logs --tail 100 artex

停止:

docker compose stop

移除容器但保留默认命名数据卷:

docker compose down

不要随意使用 docker compose down -v,它会删除 Compose
管理的数据卷,可能造成 PostgreSQL 数据丢失。

posted @ 2026-11-05 22:27  yeran烨染  阅读(1)  评论(0)    收藏  举报