
Terrier는 이미지 및 컨테이너 분석 도구로, 이미지와 컨테이너를 스캔하여 특정 파일의 존재 여부를 해당 파일의 해시를 기반으로 식별하고 검증하는 데 사용할 수 있습니다.
Terrier는 OCI 이미지와 컨테이너를 스캔하여 특정 파일의 존재 여부를 해시 값 기준으로 식별하고 검증하는 데 사용할 수 있는 이미지 및 컨테이너 분석 도구입니다. Terrier에 대한 자세한 설명은 Heroku 블로그(https://blog.heroku.com/terrier-open-source-identifying-analyzing-containers)에서 확인할 수 있습니다.
바이너리 설치 방법은 릴리스 페이지를 참조하십시오.
$ go get github.com/heroku/terrier
Go를 통해
$ go build
또는
$ make all
$ ./terrier -h
Usage of ./terrier:
-cfg string
Load config from provided yaml file (default "cfg.yml")
스캔할 OCI 이미지의 TAR 파일이 필요하며, 이는 cfg.yml의 "Image" 값을 통해 Terrier에 제공됩니다.
다음 Docker 명령어를 사용하여 Docker 이미지를 Terrier가 스캔할 수 있는 TAR 파일로 변환할 수 있습니다.
# docker save imageid -o image.tar
$ ./terrier
[+] Loading config: cfg.yml
[+] Analysing Image
[+] Docker Image Source: image.tar
[*] Inspecting Layer: 05c3c2c60920f68b506d3c66e0f6148b81a8b0831388c2d61be5ef02190bcd1f
[!] All components were identified and verified: (493/493)
Terrier는 YAML을 파싱합니다. 아래는 설정 예시입니다.
#THIS IS AN EXAMPLE CONFIG, MODIFY TO YOUR NEEDS
mode: image
image: image.tar
# mode: container
# path: merged
# verbose: true
# veryverbose: true
files:
- name: '/usr/bin/curl'
hashes:
- hash: '2353cbb7b47d0782ba8cdd9c7438b053c982eaaea6fbef8620c31a58d1e276e8'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2aaa'
- hash: '9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96'
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521faa'
- name: '/usr/bin/go'
hashes:
- hash: '2353cbb7b47d0782ba8cdd9c7438b053c982eaaea6fbef8620c31a58d1e276e8'
#UNCOMMENT TO ANALYZE HASHES
# hashes:
# - hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521faa'
# - hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2aa'
# - hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41aa'
Terrier는 CLI 도구로서 다음을 수행할 수 있습니다:
Terrier는 특정 OCI 이미지가 특정 바이너리를 사용하고 있는지 확인하는 데 사용할 수 있으며, 이는 공급망 검증 시나리오에서 유용합니다. 예를 들어, 특정 Docker 이미지가 특정 버전의 cURL을 사용하고 있는지 확인할 수 있습니다. 이 경우 Terrier에는 신뢰할 수 있는 바이너리의 SHA256 해시가 제공됩니다.
이 시나리오의 예시 YAML 파일은 다음과 같을 수 있습니다:
mode: image
# verbose: true
# veryverbose: true
image: golang1131.tar
files:
- name: '/usr/local/bin/analysis.sh'
hashes:
- hash: '9adc0bf7362bb66b98005aebec36691a62c80d54755e361788c776367d11b105'
- name: '/usr/bin/curl'
hashes:
- hash: '23afbfab4f35ac90d9841a6e05f0d1487b6e0c3a914ea8dab3676c6dde612495'
- name: '/usr/local/bin/staticcheck'
hashes:
- hash: '73f89162bacda8dd2354021dc56dc2f3dba136e873e372312843cd895dde24a2'
Terrier는 제공된 해시 집합에 따라 OCI 이미지에 특정 파일이 존재하는지 확인하는 데 사용할 수 있습니다. 이는 OCI 이미지에 악성 파일이나 식별이 필요한 파일이 포함되어 있는지 확인하는 데 유용합니다.
이 시나리오의 예시 YAML 파일은 다음과 같을 수 있습니다:
mode: image
# verbose: true
# veryverbose: true
image: alpinetest.tar
hashes:
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521f'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2'
- hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41'
- hash: '9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96'
Terrier는 /var/lib/docker/overlay2/.../merged의 내용을 분석하여 런타임에 컨테이너의 구성 요소를 확인하는 데 사용할 수 있습니다. 이 시나리오의 예시 YAML 파일은 다음과 같을 수 있습니다:
mode: container
verbose: true
# veryverbose: true
# image: latestgo13.tar
path: merged
files:
- name: '/usr/local/bin/analysis.sh'
hashes:
- hash: '9adc0bf7362bb66b98005aebec36691a62c80d54755e361788c776367d11b105'
- name: '/usr/local/go/bin/go'
hashes:
- hash: '23afbfab4f35ac90d9841a6e05f0d1487b6e0c3a914ea8dab3676c6dde612495'
- name: '/usr/local/bin/staticcheck'
hashes:
- hash: '73f89162bacda8dd2354021dc56dc2f3dba136e873e372312843cd895dde24a2'
- name: '/usr/local/bin/gosec'
hashes:
- hash: 'e7cb8304e032ccde8e342a7f85ba0ba5cb0b8383a09a77ca282793ad7e9f8c1f'
- name: '/usr/local/bin/errcheck'
hashes:
- hash: '41f725d7a872cad4ce1f403938937822572e0a38a51e8a1b29707f5884a2f0d7'
- name: '/var/lib/dpkg/info/apt.postrm'
hashes:
- hash: '6a8f9af3abcfb8c6e35887d11d41a83782b50f5766d42bd1e32a38781cba0b1c'
Terrier는 CLI이며 YAML을 사용합니다. YAML 설정 예시:
mode: image
# verbose: true
# veryverbose: true
image: alpinetest.tar
files:
- name: '/usr/local/go/bin/go'
hashes:
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521f'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2aaa'
- hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41aaa'
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521faa'
- name: '/usr/bin/delpart'
hashes:
- hash: '9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96aaa'
- name: '/usr/bin/stdbuf'
hashes:
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521faa'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2aa'
- hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41aa'
아래 예제에서 Terrier는 위 YAML을 통해 여러 파일을 확인하도록 지시받았습니다.
$./terrier
[+] Loading config: cfg.yml
[+] Analysing Image
[+] Docker Image Source: alpinetest.tar
[*] Inspecting Layer: 05c3c2c60920f68b506d3c66e0f6148b81a8b0831388c2d61be5ef02190bcd1f
[*] Inspecting Layer: 09c25a178d8a6f8b984f3e72ca5ec966215b24a700ed135dc062ad925aa5eb23
[*] Inspecting Layer: 36351e8e1da92268d40245cfbcd499a1173eeacc23be428386c8fc0a16f0b10a
[*] Inspecting Layer: 7224ca1e886eeb7e63a9e978b1a811ed52f4a53ccb65f7c510fa04a0d1103fdf
[*] Inspecting Layer: 7a2e464d80c7a1d89dab4321145491fb94865099c59975cfc840c2b8e7065014
[*] Inspecting Layer: 88a583fe02f250344f89242f88309c666671042b032411630de870a111bea971
[*] Inspecting Layer: 8db14b6fdd2cf8b4c122824531a4d85e07f1fecd6f7f43eab7f2d0a90d8c4bf2
[*] Inspecting Layer: 9196e3376d1ed69a647e728a444662c10ed21feed4ef7aaca0d10f452240a09a
[*] Inspecting Layer: 92db9b9e59a64cdf486203189d02acff79c3360788b62214a49d2263874ee811
[*] Inspecting Layer: bc4bb4a45da628724c9f93400a9149b2dd8a5d437272cb4e572cfaec64512d98
[*] Inspecting Layer: be7d600e4e8ed3000e342ef6482211350069d935a14aeff4d9fc3289e1426ed3
[*] Inspecting Layer: c4cec85dfa44f0a8856064922cff1c39b872b506dd002e33664d11a80f75a149
[*] Inspecting Layer: c998d6f023b7b9e3c186af19bcd1c2574f0d01b943077281ac5bd32e02dc57a5
[!] All components were identified and verified: (493/493)
Terrier는 테스트 결과에 따라 반환 코드를 설정합니다. 위 테스트의 경우 제공된 각 구성 요소의 인스턴스가 1개 식별되고 확인되었으므로 반환 코드는 성공을 의미하는 "0"이 됩니다.
Terrier는 제공된 이미지에서 제공된 SHA256 해시와 일치하는 파일을 식별하도록 지시받습니다. YAML 파일 cfg.yml
mode: image
# verbose: true
# veryverbose: true
image: 1070caa1a8d89440829fd35d9356143a9d6185fe7f7a015b992ec1d8aa81c78a.tar
hashes:
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521f'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2'
- hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41'
- hash: '9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96'
Terrier 실행.
./terrier
[+] Loading config: cfg.yml
[+] Docker Image Source: golang.tar
[*] Inspecting Layer: 1070caa1a8d89440829fd35d9356143a9d6185fe7f7a015b992ec1d8aa81c78a
[*] Inspecting Layer: 414833cdb33683ab8607565da5f40d3dc3f721e9a59e14e373fce206580ed40d
[*] Inspecting Layer: 6bd93c6873c822f793f770fdf3973d8a02254a5a0d60d67827480797f76858aa
[*] Inspecting Layer: c40c240ae37a2d2982ebcc3a58e67bf07aeaebe0796b5c5687045083ac6295ed
[*] Inspecting Layer: d2850df0b6795c00bdce32eb9c1ad9afc0640c2b9a3e53ec5437fc5539b1d71a
[*] Inspecting Layer: f0c2fe7dbe3336c8ba06258935c8dae37dbecd404d2d9cd74c3587391a11b1af
[!] Found file 'f0c2fe7dbe3336c8ba06258935c8dae37dbecd404d2d9cd74c3587391a11b1af/usr/bin/curl' with hash: 9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96
[*] Inspecting Layer: f2d913644763b53196cfd2597f21b9739535ef9d5bf9250b9fa21ed223fc29e3
echo $?
1
Terrier는 "merged"에 있는 컨테이너의 병합된 내용을 분석하고 확인하도록 지시받습니다. 여기서 "merged"는 보통 /var/lib/docker/overlay2/..../merged에 위치합니다.
이 시나리오의 예시 YAML 파일은 다음과 같을 수 있습니다:
mode: container
verbose: true
# veryverbose: true
# image: latestgo13.tar
path: merged
files:
- name: '/usr/local/bin/analysis.sh'
hashes:
- hash: '9adc0bf7362bb66b98005aebec36691a62c80d54755e361788c776367d11b105'
- name: '/usr/local/go/bin/go'
hashes:
- hash: '23afbfab4f35ac90d9841a6e05f0d1487b6e0c3a914ea8dab3676c6dde612495'
- name: '/usr/local/bin/staticcheck'
hashes:
- hash: '73f89162bacda8dd2354021dc56dc2f3dba136e873e372312843cd895dde24a2'
- name: '/usr/local/bin/gosec'
hashes:
- hash: 'e7cb8304e032ccde8e342a7f85ba0ba5cb0b8383a09a77ca282793ad7e9f8c1f'
- name: '/usr/local/bin/errcheck'
hashes:
- hash: '41f725d7a872cad4ce1f403938937822572e0a38a51e8a1b29707f5884a2f0d7'
- name: '/var/lib/dpkg/info/apt.postrm'
hashes:
- hash: '6a8f9af3abcfb8c6e35887d11d41a83782b50f5766d42bd1e32a38781cba0b1c'
실행 중인 컨테이너를 분석하기 위해 Terrier를 실행합니다.
[+] Loading config: cfg.yml
[+] Analysing Container
[!] Found matching instance of '/usr/local/bin/analysis.sh' at: merged/usr/local/bin/analysis.sh with hash:9adc0bf7362bb66b98005aebec36691a62c80d54755e361788c776367d11b105
[!] Found matching instance of '/usr/local/bin/errcheck' at: merged/usr/local/bin/errcheck with hash:41f725d7a872cad4ce1f403938937822572e0a38a51e8a1b29707f5884a2f0d7
[!] Found matching instance of '/usr/local/bin/gosec' at: merged/usr/local/bin/gosec with hash:e7cb8304e032ccde8e342a7f85ba0ba5cb0b8383a09a77ca282793ad7e9f8c1f
[!] Found matching instance of '/usr/local/bin/staticcheck' at: merged/usr/local/bin/staticcheck with hash:73f89162bacda8dd2354021dc56dc2f3dba136e873e372312843cd895dde24a2
[!] Found matching instance of '/usr/local/go/bin/go' at: merged/usr/local/go/bin/go with hash:23afbfab4f35ac90d9841a6e05f0d1487b6e0c3a914ea8dab3676c6dde612495
[!] Found matching instance of '/var/lib/dpkg/info/apt.postrm' at: merged/var/lib/dpkg/info/apt.postrm with hash:6a8f9af3abcfb8c6e35887d11d41a83782b50f5766d42bd1e32a38781cba0b1c
[!] All components were identified and verified: (6/6)
Terrier는 공급망 공격 방지를 지원하기 위해 설계되었습니다. Github Actions 또는 CircleCI와 같은 CI와 Terrier를 함께 사용하려면 다음 예제 구성이 유용할 수 있습니다.
config.yml
version: 2
jobs:
build:
machine: true
steps:
- checkout
- run:
name: Build Docker Image
command: |
docker build -t builditall .
- run:
name: Save Docker Image Locally
command: |
docker save builditall -o builditall.tar
- run:
name: Verify Docker Image Binaries
command: |
./terrier_linux_amd64
Terrier cfg.yml
mode:image
image: builditall.tar
files:
- name: '/bin/wget'
hashes:
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521f'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2a'
- hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41a'
- name: '/sbin/sulogin'
hashes:
- hash: '9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96aaa'
go.yml
name: Go
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Get Code
uses: actions/checkout@master
- name: Build Docker Image
run: |
docker build -t builditall .
- name: Save Docker Image Locally
run: |
docker save builditall -o builditall.tar
- name: Verify Docker Image Binaries
run: |
./terrier_linux_amd64
Terrier cfg.yml
mode: image
image: builditall.tar
files:
- name: '/bin/wget'
hashes:
- hash: '8b7c559b8cccca0d30d01bc4b5dc944766208a53d18a03aa8afe97252207521f'
- hash: '22e88c7d6da9b73fbb515ed6a8f6d133c680527a799e3069ca7ce346d90649b2a'
- hash: '60a2c86db4523e5d3eb41a247b4e7042a21d5c9d483d59053159d9ed50c8aa41a'
- name: '/bin/sbin/sulogin'
hashes:
- hash: '9a43cb726fef31f272333b236ff1fde4beab363af54d0bc99c304450065d9c96aaa'
SHA256 해시의 출처가 다음과 같은 형식으로 다른 도구에서 생성되는 경우가 있습니다.
6a8f9af3abcfb8c6e35887d11d41a83782b50f5766d42bd1e32a38781cba0b1c ./var/lib/dpkg/info/apt.postrm
6374f7996297a6933c9ccae7eecc506a14c85112bf1984c12da1f975dab573b2 ./var/lib/dpkg/info/mawk.postinst
fd72e78277680d02dcdb5d898fc9e3fed00bf011ccf31deee0f9e5f4cf299055 ./var/lib/dpkg/info/lsb-base.preinst
fd72e78277680d02dcdb5d898fc9e3fed00bf011ccf31deee0f9e5f4cf299055 ./var/lib/dpkg/info/lsb-base.postrm
8a278d8f860ef64ae49a2d3099b698c79dd5184db154fdeaea1bc7544c2135df ./var/lib/dpkg/info/debconf.postrm
1e6edefb6be6eb6fe8dd60ece5544938197b2d1d38a2d4957c069661bc2591cd ./var/lib/dpkg/info/base-files.prerm
198c13dfc6e7ae170b48bb5b997793f5b25541f6e998edaec6e9812bc002915f ./var/lib/dpkg/info/passwd.postinst
위 형식에는 Terrier에 필요한 데이터가 포함되어 있지만 형식이 올바르지 않습니다. convertSHA.sh라는 스크립트가 포함되어 있으며, 이를 사용하여 위와 같은 파일 경로와 해시 값이 포함된 파일을 유효한 Terrier 설정 파일로 변환할 수 있습니다.
다음 예제에서 이를 확인할 수 있습니다.
# cat hashes-SHA256.txt
6a8f9af3abcfb8c6e35887d11d41a83782b50f5766d42bd1e32a38781cba0b1c ./var/lib/dpkg/info/apt.postrm
6374f7996297a6933c9ccae7eecc506a14c85112bf1984c12da1f975dab573b2 ./var/lib/dpkg/info/mawk.postinst
fd72e78277680d02dcdb5d898fc9e3fed00bf011ccf31deee0f9e5f4cf299055 ./var/lib/dpkg/info/lsb-base.preinst
fd72e78277680d02dcdb5d898fc9e3fed00bf011ccf31deee0f9e5f4cf299055 ./var/lib/dpkg/info/lsb-base.postrm
8a278d8f860ef64ae49a2d3099b698c79dd5184db154fdeaea1bc7544c2135df ./var/lib/dpkg/info/debconf.postrm
1e6edefb6be6eb6fe8dd60ece5544938197b2d1d38a2d4957c069661bc2591cd ./var/lib/dpkg/info/base-files.prerm
198c13dfc6e7ae170b48bb5b997793f5b25541f6e998edaec6e9812bc002915f ./var/lib/dpkg/info/passwd.postinst
# ./convertSHA.sh hashes-SHA256.txt output.yml
Converting hashes-SHA256.txt to Terrier YML: output.yml
# cat output.yml
mode: image
#mode: container
image: image.tar
#path: path/to/container/merged
#verbose: true
#veryverbose: true
files:
- name: '/var/lib/dpkg/info/apt.postrm'
hashes:
- hash: '6a8f9af3abcfb8c6e35887d11d41a83782b50f5766d42bd1e32a38781cba0b1c'
- name: '/var/lib/dpkg/info/mawk.postinst'
hashes:
- hash: '6374f7996297a6933c9ccae7eecc506a14c85112bf1984c12da1f975dab573b2'