🔐

【ラズパイ】セキュリティテストを仕掛ける #STIGs #CISベンチマーク #serverspec #スキャン

2023/12/05に公開
セキュリティ対策系の記事は多く見かけますが、対策した後のセキュリティ”テスト”関連の記事がほとんどなかったので書きます。

やること

家のラズパイのセキュリティレベルがどの程度なのかを把握しておきたいので、セキュリティテストを仕掛けます。
誰でも簡単にできますので、是非お試しあれ。 (推定所用時間、1~2 分

以下のような、一般的なセキュリティ対策に問題がないことの確認に加えて、、、

https://qiita.com/nokonoko_1203/items/94a888444d5019f23a11

今回は、CISベンチマークに沿ったセキュリティスキャンをします。(CISベンチマークとは?
企業が商用環境でサーバーセキュリティに使う、ガチなヤツです。

通常CISベンチマークは、OSの種類によって中身が異なります。(Redhat用、とか、Ubuntu用など。。)しかし、使い分けが面倒な場合があります。

それで、すべてのLinuxOSに共通化されたベンチマーク↓↓↓が用意されています。今回はこちらを使っていきます。

https://www.cisecurity.org/benchmark/distribution_independent_linux

Distribution Independent Benchmark = ディストリビューション(Linuxの種類)に依存しないベンチマーク

では、やってきましょう!

TL;DR(1~2分)

1: InSpecインストール(InSpecとは

・Windows Powershell

. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -project inspec -version 4

・Macターミナル:

curl https://omnitruck.chef.io/install.sh | sudo bash -s -- -P inspec -v 4

2: テストコード取得(Githubリンク

git clone https://github.com/dev-sec/cis-dil-benchmark.git 

3: InSpec実行

inspec exec --chef-license=yes cis-dil-benchmark -t ssh://[ラズパイホスト名orIPアドレス]

実践チュートリアル

Step1: InSpecのインストール(InSpecとは

・Windows Powershell

. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -project inspec -version 4

※Windowsの場合、インストール後に、Powershellを閉じて、開き直す必要があります。

・Macターミナル:

curl https://omnitruck.chef.io/install.sh | sudo bash -s -- -P inspec -v 4

パッケージダウンロードしたい方は、こちら

Step2: テストコード取得(Githubリンク

git clone https://github.com/dev-sec/cis-dil-benchmark.git 

Gitインストール手順(公式ページ)

上記の通り、Github上に無料のテストコードが公開されています。

dev-secリポジトリ は、Progress社[1]が公式にメンテナンスしています。無償で利用できるテストコードは少ないです。

有償版であれば、ほぼすべてのOSに対応するテストコードが用意されています。すべての対応OSリストはこちらで確認することができます。

テストコードがどのようなものか簡単にご紹介します。
例えば、「SSHログイン失敗回数が設定されているか」を確認するコードは、

  describe sshd_config do
    its('MaxAuthTries') { should cmp <= 4 }
  end

可読性がとても高いですね。4回以上のログイン失敗を許可しないことを示しています。
他にも、「RootユーザーのSSHログインを許可していないか」を確認するコードは、

  describe sshd_config do
    its('PermitRootLogin') { should eq 'no' }
  end

Step3: テスト実行

Step2で取得したテストコードを実行する。
ラズパイへのSSH接続ができることが実行条件です。

inspec exec --chef-license=yes cis-dil-benchmark -t ssh://[ラズパイホスト名orIPアドレス]

--chef-license=yes:InSpecは、Chefと同様に商用利用する場合ライセンスを取得する必要があります。商用で利用する場合、事前にライセンス販売代理店にお問い合わせください。

-t:リモートターゲットモードです。リモートマシン(ラズパイ)に対してテストコードを実行する際に使用します。

Step4: テスト結果確認

・標準出力

さすがCISベンチマーク!テスト項目と結果が半端ない長さなので展開しない方が良いです😅

すべてのターミナル出力⚠️
$ inspec exec cis-dil-benchmark -t ssh://myCloud                12:28:53 

Profile: CIS Distribution Independent Linux Benchmark Profile (cis-dil-benchmark)
Version: 0.4.13
Target:  ssh://r-goto@myCloud:51042

  ×  cis-dil-benchmark-1.1.1.1: Ensure mounting of cramfs filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "cramfs" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "cramfs".configured?` to be truthy, got false
     ✔  Kernel Module cramfs is expected not to be loaded
     ×  Kernel Module cramfs is expected to be disabled
     expected `Kernel Module cramfs.disabled?` to be truthy, got false
  ×  cis-dil-benchmark-1.1.1.2: Ensure mounting of freevxfs filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "freevxfs" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "freevxfs".configured?` to be truthy, got false
     ✔  Kernel Module freevxfs is expected not to be loaded
     ×  Kernel Module freevxfs is expected to be disabled
     expected `Kernel Module freevxfs.disabled?` to be truthy, got false
  ×  cis-dil-benchmark-1.1.1.3: Ensure mounting of jffs2 filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "jffs2" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "jffs2".configured?` to be truthy, got false
     ✔  Kernel Module jffs2 is expected not to be loaded
     ×  Kernel Module jffs2 is expected to be disabled
     expected `Kernel Module jffs2.disabled?` to be truthy, got false
  ×  cis-dil-benchmark-1.1.1.4: Ensure mounting of hfs filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "hfs" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "hfs".configured?` to be truthy, got false
     ✔  Kernel Module hfs is expected not to be loaded
     ×  Kernel Module hfs is expected to be disabled
     expected `Kernel Module hfs.disabled?` to be truthy, got false
  ×  cis-dil-benchmark-1.1.1.5: Ensure mounting of hfsplus filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "hfsplus" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "hfsplus".configured?` to be truthy, got false
     ✔  Kernel Module hfsplus is expected not to be loaded
     ×  Kernel Module hfsplus is expected to be disabled
     expected `Kernel Module hfsplus.disabled?` to be truthy, got false
  ×  cis-dil-benchmark-1.1.1.6: Ensure mounting of squashfs filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "squashfs" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "squashfs".configured?` to be truthy, got false
     ✔  Kernel Module squashfs is expected not to be loaded
     ×  Kernel Module squashfs is expected to be disabled
     expected `Kernel Module squashfs.disabled?` to be truthy, got false
  ×  cis-dil-benchmark-1.1.1.7: Ensure mounting of udf filesystems is disabled (2 failed)
     ×  File System Table File (fstab) with file_system_type == "udf" is expected to be configured
     expected `File System Table File (fstab) with file_system_type == "udf".configured?` to be truthy, got false
     ✔  Kernel Module udf is expected not to be loaded
     ×  Kernel Module udf is expected to be disabled
     expected `Kernel Module udf.disabled?` to be truthy, got false
  ✔  cis-dil-benchmark-1.1.1.8: Ensure mounting of FAT filesystems is disabled
     ✔  File System Table File (fstab) with file_system_type == "vfat" is expected to be configured
  ×  cis-dil-benchmark-1.1.2: Ensure separate partition exists for /tmp
     ×  Mount /tmp is expected to be mounted
     
     Mount /tmp is not mounted

  ×  cis-dil-benchmark-1.1.3: Ensure nodev option set on /tmp partition
     ×  Mount /tmp options is expected to include "nodev"
     expected nil to include "nodev", but it does not respond to `include?`
  ×  cis-dil-benchmark-1.1.4: Ensure nosuid option set on /tmp partition
     ×  Mount /tmp options is expected to include "nosuid"
     expected nil to include "nosuid", but it does not respond to `include?`
  ×  cis-dil-benchmark-1.1.5: Ensure noexec option set on /tmp partition
     ×  Mount /tmp options is expected to include "noexec"
     expected nil to include "noexec", but it does not respond to `include?`
  ×  cis-dil-benchmark-1.1.6: Ensure separate partition exists for /var
     ×  Mount /var is expected to be mounted
     
     Mount /var is not mounted

  ×  cis-dil-benchmark-1.1.7: Ensure separate partition exists for /var/tmp
     ×  Mount /var/tmp is expected to be mounted
     
     Mount /var/tmp is not mounted

  ↺  cis-dil-benchmark-1.1.8: Ensure nodev option set on /var/tmp partition
     ↺  Skipped control due to only_if condition: /var/tmp is mounted
  ↺  cis-dil-benchmark-1.1.9: Ensure nosuid option set on /var/tmp partition
     ↺  Skipped control due to only_if condition: /var/tmp is mounted
  ↺  cis-dil-benchmark-1.1.10: Ensure noexec option set on /var/tmp partition
     ↺  Skipped control due to only_if condition: /var/tmp is mounted
  ×  cis-dil-benchmark-1.1.11: Ensure separate partition exists for /var/log
     ×  Mount /var/log is expected to be mounted
     
     Mount /var/log is not mounted

  ×  cis-dil-benchmark-1.1.12: Ensure separate partition exists for /var/log/audit
     ×  Mount /var/log/audit is expected to be mounted
     
     Mount /var/log/audit is not mounted

  ×  cis-dil-benchmark-1.1.13: Ensure separate partition exists for /home
     ×  Mount /home is expected to be mounted
     
     Mount /home is not mounted

  ↺  cis-dil-benchmark-1.1.14: Ensure nodev option set on /home partition
     ↺  Skipped control due to only_if condition: /home is mounted
  ✔  cis-dil-benchmark-1.1.15: Ensure nodev option set on /dev/shm partition
     ✔  Mount /dev/shm options is expected to include "nodev"
  ✔  cis-dil-benchmark-1.1.16: Ensure nosuid option set on /dev/shm partitionrun
     ✔  Mount /dev/shm options is expected to include "nosuid"
  ×  cis-dil-benchmark-1.1.17: Ensure noexec option set on /dev/shm partition
     ×  Mount /dev/shm options is expected to include "noexec"
     expected ["rw", "nosuid", "nodev"] to include "noexec"
  ↺  cis-dil-benchmark-1.1.18: Ensure nodev option set on removable media partitions
     ↺  Not implemented
  ↺  cis-dil-benchmark-1.1.19: Ensure nosuid option set on removable media partitions
     ↺  Not implemented
  ↺  cis-dil-benchmark-1.1.20: Ensure noexec option set on removable media partitions
     ↺  Not implemented
  ✔  cis-dil-benchmark-1.1.21: Ensure sticky bit is set on all world-writable 
     ✔  File /var/log/mail.log.1 is expected not to be writable by group
     ✔  File /var/log/mail.log.1 is expected not to be executable by group
     ✔  File /var/log/mail.log.1 is expected not to be readable by other
     ✔  File /var/log/mail.log.1 is expected not to be writable by other
     ✔  File /var/log/mail.log.1 is expected not to be executable by other
     ✔  File /var/log/mail.log.2.gz is expected not to be writable by group
     ✔  File /var/log/mail.log.2.gz is expected not to be executable by group
     ✔  File /var/log/mail.log.2.gz is expected not to be readable by other
     ✔  File /var/log/mail.log.2.gz is expected not to be writable by other
     ✔  File /var/log/mail.log.2.gz is expected not to be executable by other
     ✔  File /var/log/daemon.log.2.gz is expected not to be writable by group
     ✔  File /var/log/daemon.log.2.gz is expected not to be executable by group
     ✔  File /var/log/daemon.log.2.gz is expected not to be readable by other
     ✔  File /var/log/daemon.log.2.gz is expected not to be writable by other
     ✔  File /var/log/daemon.log.2.gz is expected not to be executable by urced in /etc/profile.
     +
     +# If not running interactively, don't do anything
     +[ -z "$PS1" ] && return
     +
     +# check the window size after each command and, if necessary,
     +# update the values of LINES and COLUMNS.
     +shopt -s checkwinsize
     +
     +# set variable identifying the chroot you work in (used in the prompt below)
     +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
     +    debian_chroot=$(cat /etc/debian_chroot)
     +fi
     +
     +# set a fancy prompt (non-color, overwrite the one in /etc/profile)
     +# but only if not SUDOing and have SUDO_PS1 set; then assume smart user.
     +if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
     +  PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
     +fi
     +
     +# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default.
     +# If this is an xterm set the title to user@host:dir
     +#case "$TERM" in
     +#xterm*|rxvt*)
     +#    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
     +#    ;;
     +#*)
     +#    ;;
     +#esac
     +
     +# enable bash completion in interactive shells
     +#if ! shopt -oq posix; then
     +#  if [ -f /usr/share/bash-completion/bash_completion ]; then
     +#    . /usr/share/bash-completion/bash_completion
     +#  elif [ -f /etc/bash_completion ]; then
     +#    . /etc/bash_completion
     +#  fi
     +#fi
     +
     +# if the command-not-found package is installed, use it
     +if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
     +	function command_not_found_handle {
     +	        # check because c-n-f could've been removed in the meantime
     +                if [ -x /usr/lib/command-not-found ]; then
     +		   /usr/lib/command-not-found -- "$1"
     +                   return $?
     +                elif [ -x /usr/share/command-not-found/command-not-found ]; then
     +		   /usr/share/command-not-found/command-not-found -- "$1"
     +                   return $?
     +		else
     +		   printf "%s: command not found\n" "$1" >&2
     +		   return 127
     +		fi
     +	}
     +fi

     ×  File /etc/profile content is expected to match /^\s*TMOUT=([0-8][0-9]{0,2}|900)\s*(?:#.*)?$/
     expected "# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))\n# and Bourne compatible shel...r i in /etc/profile.d/*.sh; do\n    if [ -r $i ]; then\n      . $i\n    fi\n  done\n  unset i\nfi\n" to match /^\s*TMOUT=([0-8][0-9]{0,2}|900)\s*(?:#.*)?$/
     Diff:
     @@ -1,34 +1,67 @@
     -/^\s*TMOUT=([0-8][0-9]{0,2}|900)\s*(?:#.*)?$/
     +# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
     +# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
     +
     +if [ "`id -u`" -eq 0 ]; then
     +  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
     +else
     +  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
     +fi
     +export PATH
     +
     +if [ "${PS1-}" ]; then
     +  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
     +    # The file bash.bashrc already sets the default PS1.
     +    # PS1='\h:\w\$ '
     +    if [ -f /etc/bash.bashrc ]; then
     +      . /etc/bash.bashrc
     +    fi
     +  else
     +    if [ "`id -u`" -eq 0 ]; then
     +      PS1='# '
     +    else
     +      PS1='$ '
     +    fi
     +  fi
     +fi
     +
     +if [ -d /etc/profile.d ]; then
     +  for i in /etc/profile.d/*.sh; do
     +    if [ -r $i ]; then
     +      . $i
     +    fi
     +  done
     +  unset i
     +fi

  ↺  cis-dil-benchmark-5.5: Ensure root login is restricted to system console
     ↺  Not implemented
  ×  cis-dil-benchmark-5.6: Ensure access to the su command is restricted
     ×  File /etc/pam.d/su content is expected to match /^auth\s+required\s+pam_wheel.so use_uid$/
     expected "#\n# The PAM configuration file for the Shadow `su' service\n#\n\n# This allows root to su without p... /etc/shadow entries.\n@include common-auth\n@include common-account\n@include common-session\n\n\n" to match /^auth\s+required\s+pam_wheel.so use_uid$/
     Diff:
     @@ -1,59 +1,117 @@
     -/^auth\s+required\s+pam_wheel.so use_uid$/
     +#
     +# The PAM configuration file for the Shadow `su' service
     +#
     +
     +# This allows root to su without passwords (normal operation)
     +auth       sufficient pam_rootok.so
     +
     +# Uncomment this to force users to be a member of group root
     +# before they can use `su'. You can also add "group=foo"
     +# to the end of this line if you want to use a group other
     +# than the default "root" (but this may have side effect of
     +# denying "root" user, unless she's a member of "foo" or explicitly
     +# permitted earlier by e.g. "sufficient pam_rootok.so").
     +# (Replaces the `SU_WHEEL_ONLY' option from login.defs)
     +# auth       required   pam_wheel.so
     +
     +# Uncomment this if you want wheel members to be able to
     +# su without a password.
     +# auth       sufficient pam_wheel.so trust
     +
     +# Uncomment this if you want members of a specific group to not
     +# be allowed to use su at all.
     +# auth       required   pam_wheel.so deny group=nosu
     +
     +# Uncomment and edit /etc/security/time.conf if you need to set
     +# time restrainst on su usage.
     +# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
     +# as well as /etc/porttime)
     +# account    requisite  pam_time.so
     +
     +# This module parses environment configuration file(s)
     +# and also allows you to use an extended config
     +# file /etc/security/pam_env.conf.
     +# 
     +# parsing /etc/environment needs "readenv=1"
     +session       required   pam_env.so readenv=1
     +# locale variables are also kept into /etc/default/locale in etch
     +# reading this file *in addition to /etc/environment* does not hurt
     +session       required   pam_env.so readenv=1 envfile=/etc/default/locale
     +
     +# Defines the MAIL environment variable
     +# However, userdel also needs MAIL_DIR and MAIL_FILE variables
     +# in /etc/login.defs to make sure that removing a user 
     +# also removes the user's mail spool file.
     +# See comments in /etc/login.defs
     +#
     +# "nopen" stands to avoid reporting new mail when su'ing to another user
     +session    optional   pam_mail.so nopen
     +
     +# Sets up user limits according to /etc/security/limits.conf
     +# (Replaces the use of /etc/limits in old login)
     +session    required   pam_limits.so
     +
     +# The standard Unix authentication modules, used with
     +# NIS (man nsswitch) as well as normal /etc/passwd and
     +# /etc/shadow entries.
     +@include common-auth
     +@include common-account
     +@include common-session

  ↺  cis-dil-benchmark-6.1.1: Audit system file permissions
     ↺  Not implemented
  ✔  cis-dil-benchmark-6.1.2: Ensure permissions on /etc/passwd are configured
     ✔  File /etc/passwd is expected to exist
     ✔  File /etc/passwd is expected to be owned by "root"
     ✔  File /etc/passwd is expected to be grouped into "root"
     ✔  File /etc/passwd mode is expected to cmp == "0644"
     ✔  File /etc/passwd sticky is expected to equal false
     ✔  File /etc/passwd suid is expected to equal false
     ✔  File /etc/passwd sgid is expected to equal false
  ✔  cis-dil-benchmark-6.1.3: Ensure permissions on /etc/shadow are configured
     ✔  File /etc/shadow is expected to exist
     ✔  File /etc/shadow is expected not to be more permissive than "0640"
     ✔  File /etc/shadow is expected to be owned by "root"
     ✔  File /etc/shadow gid is expected to cmp == 42
  ✔  cis-dil-benchmark-6.1.4: Ensure permissions on /etc/group are configured
     ✔  File /etc/group is expected to exist
     ✔  File /etc/group is expected to be owned by "root"
     ✔  File /etc/group is expected to be grouped into "root"
     ✔  File /etc/group mode is expected to cmp == "0644"
  ✔  cis-dil-benchmark-6.1.5: Ensure permissions on /etc/gshadow are configured
     ✔  File /etc/gshadow is expected to exist
     ✔  File /etc/gshadow is expected not to be more permissive than "0640"
     ✔  File /etc/gshadow is expected to be owned by "root"
     ✔  File /etc/gshadow gid is expected to cmp == 42
  ×  cis-dil-benchmark-6.1.6: Ensure permissions on /etc/passwd- are configured (1 failed)
     ✔  File /etc/passwd- is expected to exist
     ×  File /etc/passwd- is expected not to be more permissive than "0600"
     expected `File /etc/passwd-.more_permissive_than?("0600")` to be falsey, got true
     ✔  File /etc/passwd- is expected to be owned by "root"
     ✔  File /etc/passwd- is expected to be grouped into "root"
  ✔  cis-dil-benchmark-6.1.7: Ensure permissions on /etc/shadow- are configured
     ✔  File /etc/shadow- is expected to exist
     ✔  File /etc/shadow- is expected not to be more permissive than "0640"
     ✔  File /etc/shadow- is expected to be owned by "root"
     ✔  File /etc/shadow- gid is expected to cmp == 42
  ✔  cis-dil-benchmark-6.1.8: Ensure permissions on /etc/group- are configured
     ✔  File /etc/group- is expected to exist
     ✔  File /etc/group- is expected not to be more permissive than "0644"
     ✔  File /etc/group- is expected to be owned by "root"
     ✔  File /etc/group- is expected to be grouped into "root"
  ✔  cis-dil-benchmark-6.1.9: Ensure permissions on /etc/gshadow- are configured
     ✔  File /etc/gshadow- is expected to exist
     ✔  File /etc/gshadow- is expected not to be more permissive than "0640"
     ✔  File /etc/gshadow- is expected to be owned by "root"
     ✔  File /etc/gshadow- gid is expected to cmp == 42
  ✔  cis-dil-benchmark-6.1.10: Ensure no world writable files exist
     ✔  Command: `df --local -P | awk '{ if (NR!=1) print $6 }' | xargs -I '{}' find '{}' -xdev -type f -perm -0002` stdout is expected to cmp == ""
  ✔  cis-dil-benchmark-6.1.11: Ensure no unowned files or directories exist
     ✔  Command: `df --local -P | awk '{ if (NR!=1) print $6 }' | xargs -I '{}' find '{}' -xdev -nouser` stdout is expected to cmp == ""
  ✔  cis-dil-benchmark-6.1.12: Ensure no ungrouped files or directories exist
     ✔  Command: `df --local -P | awk '{ if (NR!=1) print $6 }' | xargs -I '{}' find '{}' -xdev -nogroup` stdout is expected to cmp == ""
  ↺  cis-dil-benchmark-6.1.13: Audit SUID executables
     ↺  Not implemented
  ↺  cis-dil-benchmark-6.1.14: Audit SGID executables
     ↺  Not implemented
  ×  cis-dil-benchmark-6.2.1: Ensure password fields are not empty
     ×  /etc/shadow passwords is expected not to include ""
     expected Inspec::Resources::Shadow (Can't read file: /etc/shadow) not to include ""
  ✔  cis-dil-benchmark-6.2.2: Ensure no legacy "+" entries exist in /etc/passwd
     ✔  /etc/passwd users is expected not to include "+"
  ×  cis-dil-benchmark-6.2.3: Ensure no legacy "+" entries exist in /etc/shadow
     ×  /etc/shadow users is expected not to include "+"
     expected Inspec::Resources::Shadow (Can't read file: /etc/shadow) not to include "+"
  ✔  cis-dil-benchmark-6.2.4: Ensure no legacy "+" entries exist in /etc/group
     ✔  /etc/group groups is expected not to include "+"
  ✔  cis-dil-benchmark-6.2.5: Ensure root is the only UID 0 account
     ✔  /etc/passwd with uid == 0 users is expected to cmp == ["root"]
  ✔  cis-dil-benchmark-6.2.6: Ensure root PATH Integrity
     ✔  ["/usr/local/bin", "/usr/bin", "/bin", "/usr/games"] is expected not to be empty
     ✔  ["/usr/local/bin", "/usr/bin", "/bin", "/usr/games"] is expected not to include ""
     ✔  ["/usr/local/bin", "/usr/bin", "/bin", "/usr/games"] is expected not to include "."
     ✔  File /usr/local/bin is expected to be directory
     ✔  File /usr/local/bin is expected not to be writable by group
     ✔  File /usr/local/bin is expected not to be writable by other
     ✔  File /usr/local/bin is expected to be owned by "root"
     ✔  File /usr/bin is expected to be directory
     ✔  File /usr/bin is expected not to be writable by group
     ✔  File /usr/bin is expected not to be writable by other
     ✔  File /usr/bin is expected to be owned by "root"
     ✔  File /bin is expected to be directory
     ✔  File /bin is expected not to be writable by group
     ✔  File /bin is expected not to be writable by other
     ✔  File /bin is expected to be owned by "root"
     ✔  File /usr/games is expected to be directory
     ✔  File /usr/games is expected not to be writable by group
     ✔  File /usr/games is expected not to be writable by other
     ✔  File /usr/games is expected to be owned by "root"
  ✔  cis-dil-benchmark-6.2.7: Ensure all users' home directories exist
     ✔  File /home/r-goto is expected to be directory
  ×  cis-dil-benchmark-6.2.8: Ensure users' home directories permissions are 750 or more restrictive (2 failed)
     ✔  File /home/r-goto is expected to exist
     ✔  File /home/r-goto is expected not to be writable by group
     ×  File /home/r-goto is expected not to be readable by other
     expected File /home/r-goto not to be readable by other
     ✔  File /home/r-goto is expected not to be writable by other
     ×  File /home/r-goto is expected not to be executable by other
     expected File /home/r-goto not to be executable by other
  ✔  cis-dil-benchmark-6.2.9: Ensure users own their home directories
     ✔  File /home/r-goto is expected to be owned by "r-goto"
  ✔  cis-dil-benchmark-6.2.10: Ensure users' dot files are not group or world writable
     ✔  File /home/r-goto/.bash_logout is expected not to be writable by group
     ✔  File /home/r-goto/.bash_logout is expected not to be writable by other
     ✔  File /home/r-goto/.lesshst is expected not to be writable by group
     ✔  File /home/r-goto/.lesshst is expected not to be writable by other
     ✔  File /home/r-goto/.viminfo is expected not to be writable by group
     ✔  File /home/r-goto/.viminfo is expected not to be writable by other
     ✔  File /home/r-goto/.wget-hsts is expected not to be writable by group
     ✔  File /home/r-goto/.wget-hsts is expected not to be writable by other
     ✔  File /home/r-goto/.selected_editor is expected not to be writable by group
     ✔  File /home/r-goto/.selected_editor is expected not to be writable by other
     ✔  File /home/r-goto/.zcompdump is expected not to be writable by group
     ✔  File /home/r-goto/.zcompdump is expected not to be writable by other
     ✔  File /home/r-goto/.zshrc is expected not to be writable by group
     ✔  File /home/r-goto/.zshrc is expected not to be writable by other
     ✔  File /home/r-goto/.profile is expected not to be writable by group
     ✔  File /home/r-goto/.profile is expected not to be writable by other
     ✔  File /home/r-goto/.bash_history is expected not to be writable by group
     ✔  File /home/r-goto/.bash_history is expected not to be writable by other
     ✔  File /home/r-goto/.bashrc is expected not to be writable by group
     ✔  File /home/r-goto/.bashrc is expected not to be writable by other
  ✔  cis-dil-benchmark-6.2.11: Ensure no users have .forward files
     ✔  File /root/.forward is expected not to exist
     ✔  File /usr/sbin/.forward is expected not to exist
     ✔  File /bin/.forward is expected not to exist
     ✔  File /dev/.forward is expected not to exist
     ✔  File /bin/.forward is expected not to exist
     ✔  File /usr/games/.forward is expected not to exist
     ✔  File /var/cache/man/.forward is expected not to exist
     ✔  File /var/spool/lpd/.forward is expected not to exist
     ✔  File /var/mail/.forward is expected not to exist
     ✔  File /var/spool/news/.forward is expected not to exist
     ✔  File /var/spool/uucp/.forward is expected not to exist
     ✔  File /bin/.forward is expected not to exist
     ✔  File /var/www/.forward is expected not to exist
     ✔  File /var/backups/.forward is expected not to exist
     ✔  File /var/list/.forward is expected not to exist
     ✔  File /var/run/ircd/.forward is expected not to exist
     ✔  File /var/lib/gnats/.forward is expected not to exist
     ✔  File /nonexistent/.forward is expected not to exist
     ✔  File /run/systemd/.forward is expected not to exist
     ✔  File /run/systemd/.forward is expected not to exist
     ✔  File /run/systemd/.forward is expected not to exist
     ✔  File /nonexistent/.forward is expected not to exist
     ✔  File /nonexistent/.forward is expected not to exist
     ✔  File /run/rpcbind/.forward is expected not to exist
     ✔  File /var/lib/nfs/.forward is expected not to exist
     ✔  File /run/sshd/.forward is expected not to exist
     ✔  File /var/run/avahi-daemon/.forward is expected not to exist
     ✔  File //.forward is expected not to exist
     ✔  File /home/r-goto/.forward is expected not to exist
     ✔  File /var/lib/chrony/.forward is expected not to exist
     ✔  File /var/lib/usbmux/.forward is expected not to exist
  ✔  cis-dil-benchmark-6.2.12: Ensure no users have .netrc files
     ✔  File /root/.netrc is expected not to exist
     ✔  File /usr/sbin/.netrc is expected not to exist
     ✔  File /bin/.netrc is expected not to exist
     ✔  File /dev/.netrc is expected not to exist
     ✔  File /bin/.netrc is expected not to exist
     ✔  File /usr/games/.netrc is expected not to exist
     ✔  File /var/cache/man/.netrc is expected not to exist
     ✔  File /var/spool/lpd/.netrc is expected not to exist
     ✔  File /var/mail/.netrc is expected not to exist
     ✔  File /var/spool/news/.netrc is expected not to exist
     ✔  File /var/spool/uucp/.netrc is expected not to exist
     ✔  File /bin/.netrc is expected not to exist
     ✔  File /var/www/.netrc is expected not to exist
     ✔  File /var/backups/.netrc is expected not to exist
     ✔  File /var/list/.netrc is expected not to exist
     ✔  File /var/run/ircd/.netrc is expected not to exist
     ✔  File /var/lib/gnats/.netrc is expected not to exist
     ✔  File /nonexistent/.netrc is expected not to exist
     ✔  File /run/systemd/.netrc is expected not to exist
     ✔  File /run/systemd/.netrc is expected not to exist
     ✔  File /run/systemd/.netrc is expected not to exist
     ✔  File /nonexistent/.netrc is expected not to exist
     ✔  File /nonexistent/.netrc is expected not to exist
     ✔  File /run/rpcbind/.netrc is expected not to exist
     ✔  File /var/lib/nfs/.netrc is expected not to exist
     ✔  File /run/sshd/.netrc is expected not to exist
     ✔  File /var/run/avahi-daemon/.netrc is expected not to exist
     ✔  File //.netrc is expected not to exist
     ✔  File /home/r-goto/.netrc is expected not to exist
     ✔  File /var/lib/chrony/.netrc is expected not to exist
     ✔  File /var/lib/usbmux/.netrc is expected not to exist
  ✔  cis-dil-benchmark-6.2.14: Ensure no users have .rhosts files
     ✔  File /root/.rhosts is expected not to exist
     ✔  File /usr/sbin/.rhosts is expected not to exist
     ✔  File /bin/.rhosts is expected not to exist
     ✔  File /dev/.rhosts is expected not to exist
     ✔  File /bin/.rhosts is expected not to exist
     ✔  File /usr/games/.rhosts is expected not to exist
     ✔  File /var/cache/man/.rhosts is expected not to exist
     ✔  File /var/spool/lpd/.rhosts is expected not to exist
     ✔  File /var/mail/.rhosts is expected not to exist
     ✔  File /var/spool/news/.rhosts is expected not to exist
     ✔  File /var/spool/uucp/.rhosts is expected not to exist
     ✔  File /bin/.rhosts is expected not to exist
     ✔  File /var/www/.rhosts is expected not to exist
     ✔  File /var/backups/.rhosts is expected not to exist
     ✔  File /var/list/.rhosts is expected not to exist
     ✔  File /var/run/ircd/.rhosts is expected not to exist
     ✔  File /var/lib/gnats/.rhosts is expected not to exist
     ✔  File /nonexistent/.rhosts is expected not to exist
     ✔  File /run/systemd/.rhosts is expected not to exist
     ✔  File /run/systemd/.rhosts is expected not to exist
     ✔  File /run/systemd/.rhosts is expected not to exist
     ✔  File /nonexistent/.rhosts is expected not to exist
     ✔  File /nonexistent/.rhosts is expected not to exist
     ✔  File /run/rpcbind/.rhosts is expected not to exist
     ✔  File /var/lib/nfs/.rhosts is expected not to exist
     ✔  File /run/sshd/.rhosts is expected not to exist
     ✔  File /var/run/avahi-daemon/.rhosts is expected not to exist
     ✔  File //.rhosts is expected not to exist
     ✔  File /home/r-goto/.rhosts is expected not to exist
     ✔  File /var/lib/chrony/.rhosts is expected not to exist
     ✔  File /var/lib/usbmux/.rhosts is expected not to exist
  ✔  cis-dil-benchmark-6.2.15: Ensure all groups in /etc/passwd exist in /etc/group
     ✔  /etc/group gids is expected to include 0
     ✔  /etc/group gids is expected to include 1
     ✔  /etc/group gids is expected to include 2
     ✔  /etc/group gids is expected to include 3
     ✔  /etc/group gids is expected to include 65534
     ✔  /etc/group gids is expected to include 60
     ✔  /etc/group gids is expected to include 12
     ✔  /etc/group gids is expected to include 7
     ✔  /etc/group gids is expected to include 8
     ✔  /etc/group gids is expected to include 9
     ✔  /etc/group gids is expected to include 10
     ✔  /etc/group gids is expected to include 13
     ✔  /etc/group gids is expected to include 33
     ✔  /etc/group gids is expected to include 34
     ✔  /etc/group gids is expected to include 38
     ✔  /etc/group gids is expected to include 39
     ✔  /etc/group gids is expected to include 41
     ✔  /etc/group gids is expected to include 65534
     ✔  /etc/group gids is expected to include 102
     ✔  /etc/group gids is expected to include 103
     ✔  /etc/group gids is expected to include 104
     ✔  /etc/group gids is expected to include 65534
     ✔  /etc/group gids is expected to include 110
     ✔  /etc/group gids is expected to include 65534
     ✔  /etc/group gids is expected to include 65534
     ✔  /etc/group gids is expected to include 65534
     ✔  /etc/group gids is expected to include 113
     ✔  /etc/group gids is expected to include 996
     ✔  /etc/group gids is expected to include 1001
     ✔  /etc/group gids is expected to include 114
     ✔  /etc/group gids is expected to include 46
  ✔  cis-dil-benchmark-6.2.16: Ensure no duplicate UIDs exist
     ✔  is expected to be nil
  ✔  cis-dil-benchmark-6.2.17: Ensure no duplicate GIDs exist
     ✔  is expected to be nil
  ✔  cis-dil-benchmark-6.2.18: Ensure no duplicate user names exist
     ✔  is expected to be nil
  ✔  cis-dil-benchmark-6.2.19: Ensure no duplicate group names exist
     ✔  is expected to be nil
  ✔  cis-dil-benchmark-6.2.20: Ensure shadow group is empty
     ✔  #<Inspec::Resources::EtcGroupView:0x000000010b9be658> users is expected to be empty


Profile Summary: 74 successful controls, 105 control failures, 51 controls skipped
Test Summary: 1103 successful, 347 failures, 94 skipped


最初と最後だけスクショを貼ります。

capture 2023-12-08 15.27.33.png
〜中割愛〜
capture 2023-12-08 15.27.55.png

問題なくPassしているテスト項目もありますが、105の大項目でセキュリティに問題が検知されていることがわかります。

テスト結果の一部を詳しく見てみましょう。

・SSH設定関連

capture 2023-12-08 15.24.20.png

expected: は、あるべき設定の状態です。
got: は、実際の設定値です。

HostbasedAuthentication設定については、”no"(無効化)ではなく、”nil”となっていて明示的に無効化されていないために問題検知を示す X となっています。

但し、「Rootログイン」や「空パスワード」については、正常に無効化できていることがわかります。

・ユーザー設定関連

capture 2023-12-08 15.34.38.png

こちらは、各ユーザーのホームディレクトリの有無や権限を確認しています。
全てのユーザーのホームディレクトリの権限は、750以上である必要がありますが、満たせていないようです。
/home/r-gotoディレクトリの権限には第三者によるRead権限が付されていまっていることがわかります。

・Web UI画面

capture 2023-12-05 12.47.44.png

Chef Automate のセットアップが必要になりますが、より高精度なテスト結果の分析を行うことができます。Slack、メール、ServiceNowと連携させることで高度な通知機能も扱うことができるようになります。

・HTMLファイル出力

inspec exec cis-dil-benchmark -t ssh://myCloud --reporter=html2 > inspect_test_results.html

上記コマンドオプションで実行し、inspect_test_results.html のように結果をHTML形式で出力することができます。

HTML以外にも、JSONやYAML出力も可能です。

Step5: まとめ&【お問い合わせ】

InSpecでラズパイのセキュリティレベルを把握することができました。
継続的かつ定期的にInSpecテストを実行することで、常にセキュアな状態を保つことができます。

すべてのテスト項目をパスできるなら、それ以上のセキュリティ対策がないくらいにガチガチ堅牢ラズパイになりますね。

検知された設定項目を手動で直すことも可能ですが、IaC(Infrastructure as Code)で自動修正することで設定ミスを減らし、よりセキュアにすることができます。次の記事でやり方をご紹介します。


InSpecに関する技術サポートや商用ライセンスの取得は、国内販売代理店に問い合わせることができます。

https://www.chef-sec.com/


おまけ(テストコードのカスタマイズ)

今回のCISベンチマークは、企業のセキュリティ部門が使用する程のガチ堅牢基準です。自宅サーバーをここまで堅牢にする必要はないように思います。

そこで、テスト項目をカスタマイズする方法を最後にご紹介します。

https://docs.chef.io/inspec/waivers/

上記で説明されているWaiver機能を使うことで不要なテストをスキップさせることができます。

YAMLもしくはJASONのファイル(waivers.yaml)を作成します。

waivers.yamlにスキップさせたいテスト項目名を以下のように追記。

cis-dil-benchmark-1.1.1.1:
  expiration_date: 2050-10-15
  justification: Not needed 

cis-dil-benchmark-1.1.1.2:
  expiration_date: 2050-10-15
  justification: Not needed 

Waiverファイルを指定してInSpec実行

inspec exec --chef-license=yes cis-dil-benchmark --waiver-file waivers.yaml -t ssh://[ラズパイホスト名orIPアドレス]
脚注
  1. Progress社は、ITインフラストラクチャの自動化およびセキュリティの向上を支援する企業です。ChefとInSpecといった強力なオートメーションツールを提供し、クラウドおよびオンプレミスの環境での効率的な運用とセキュリティの確保をサポートしています。 ↩︎

Discussion