Linuxセキュリテイ対策　Snortによる侵入検知

# はじめに
本記事はLinuxのセキュリティ対策として、Snortの侵入検知について記載しています。

[Snort](https://www.snort.org/)はオープンソースのネットワーク型のIDSです。GPL (GNU General Public License) の元に無償で利用できます。

![スクリーンショット 2020-04-23 12.32.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/99a5ee57-0a99-ecaf-2238-c40475114286.png)

現在も開発が行われているので最新のルールセットを無料でダウンロードして使用することができます。

## Snortの構築
Snortはソースで提供されているため、ソースをダウンロードしてmakeする必要があります。

そのため、環境依存が大きく必要なライブラリがインストールされていない場合は、configureでエラーが発生し、依存関係を自分で調べてインストールする必要があります。

本記事ではCentOS7を例にSnortの構築方法について解説します。Snort等のバージョンは本記事執筆時点のバージョンを使用しています。

本記事の環境：CentOS Linux release 7.7.1908 (Core)

### Snort

- ディレクトリ移動   
`# cd /usr/local/src/`
- Snortのダウンロード   
`# wget https://www.snort.org/downloads/snort/snort-2.9.16.tar.gz`
- 解凍   
`# tar xzvf snort-2.9.16.tar.gz`
- ディレクトリ移動   
`# cd snort-2.9.16`
- configure   
`# ./configure`

**最少構成でインストールしたCentOS7で`configure`を実行するとエラーが発生します。
以降、Snortのディレクトリで`configure`実行後に発生したエラーに対して、必要なライブラリのインストール方法について記載しています。**

### Libpcap

```console
checking for pcap_datalink in -lpcap... no
checking pfring.h usability... no
checking pfring.h presence... no
checking for pfring.h... no
checking for pfring_open in -lpfring... no
checking for pfring_open in -lpcap... no

   ERROR!  Libpcap library/headers (libpcap.a (or .so)/pcap.h)
   not found, go get it from http://www.tcpdump.org
   or use the --with-libpcap-* options, if you have it installed
   in unusual place.  Also check if your libpcap depends on another
   shared library that may be installed in an unusual place
```

- libpcapのダウンロード   
`# wget http://www.tcpdump.org/release/libpcap-1.9.1.tar.gz`
- 解凍   
`# tar xzvf libpcap-1.9.1.tar.gz`
- ディレクトリ移動   
`#  cd libpcap-1.9.1`
- configure   
`# ./configure`
- make    
`# make`   
`# make install`

### Libpcre

```console
./configure: line 15614: pcre-config: command not found
./configure: line 15620: pcre-config: command not found
checking pcre.h usability... no
checking pcre.h presence... no
checking for pcre.h... no

   ERROR!  Libpcre header not found.
   Get it from http://www.pcre.org
```

- pcreのダウンロード   
`# wget ftp://ftp.pcre.org/pub/pcre/pcre2-10.34.tar.gz`
- 解凍   
`# tar xzvf pcre2-10.34.tar.gz`
- ディレクトリ移動   
`#  cd pcre2-10.34`
- configure   
`# ./configure`
- make    
`# make`   
`# make install`

### pcre-devel

```console
./configure: line 15614: pcre-config: command not found
./configure: line 15620: pcre-config: command not found
checking pcre.h usability... no
checking pcre.h presence... no
checking for pcre.h... no

   ERROR!  Libpcre header not found.
   Get it from http://www.pcre.org
```

-  pcre-develのインストール    
`# yum install -y pcre-devel`


### dnet header

```console
checking for SHA256_Init in -lcrypto... no
checking for MD5_Init in -lcrypto... no
checking dnet.h usability... no
checking dnet.h presence... no
checking for dnet.h... no
checking dumbnet.h usability... no
checking dumbnet.h presence... no
checking for dumbnet.h... no

   ERROR!  dnet header not found, go get it from
   http://code.google.com/p/libdnet/ or use the --with-dnet-*
   options, if you have it installed in an unusual place
```
- libdnetとlibdnet-develのインストール   
`# yum install -y libdnet libdnet-devel`

### daq

```console
./configure: line 16267: daq-modules-config: command not found
checking for daq_load_modules in -ldaq_static... no

   ERROR!  daq_static library not found, go get it from
   http://www.snort.org/.
```

- daqのダウンロード   
`# wget https://www.snort.org/downloads/snort/daq-2.0.7.tar.gz`
- 解凍   
`# tar xzvf daq-2.0.7.tar.gz `
- ディレクトリ移動   
`# cd daq-2.0.7`
- configure   
`# ./configure`
- make    
`# make`   

makeでエラー発生したので`autoreconf`を実行して、再度ビルド

```console
CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /usr/local/src/daq-2.0.7/missing aclocal-1.15 -I m4
/usr/local/src/daq-2.0.7/missing: 行 81: aclocal-1.15: コマンドが見つかりません
WARNING: 'aclocal-1.15' is missing on your system.
         You should only need it if you modified 'acinclude.m4' or
         'configure.ac' or m4 files included by 'configure.ac'.
         The 'aclocal' program is part of the GNU Automake package:
         <http://www.gnu.org/software/automake>
         It also requires GNU Autoconf, GNU m4 and Perl in order to run:
         <http://www.gnu.org/software/autoconf>
         <http://www.gnu.org/software/m4/>
         <http://www.perl.org/>
make: *** [aclocal.m4] エラー 127
```

- autoconf   
`# autoreconf`
- configure   
`# ./configure`
- make   
`# make`   
`# make install`

### zlib

```console
checking zlib.h usability... no
checking zlib.h presence... no
checking for zlib.h... no

   ERROR!  zlib header not found, go get it from
   http://www.zlib.net
```

- zlibのインストール   
`# yum install -y zlib zlib-devel`

### LuaJIT

```console
checking for luajit... no

   ERROR!  LuaJIT library not found. Go get it from http://www.luajit.org/ (or)
   Try compiling without openAppId using '--disable-open-appid'
configure: error: "Fatal!"
```

- LuaJIT-develのインストール   
`# yum install -y luajit-devel.x86_64`

### openssl-devel

```console
checking openssl/x509.h usability... no
checking openssl/x509.h presence... no
checking for openssl/x509.h... no

   ERROR!  openssl/x509.h or openssl library not found.
   Try compiling without openAppId using '--disable-open-appid'
configure: error: "Fatal!"
```
- openssl-develのインストール   
`# yum install openssl-devel.x86_64 `

本記事の環境ではopenssl-develのインストール終了後、ようやくSnortの`configure`が正常終了しました。以下はSnortのディレクトリで実行しています。

- configure   
`# ./configure`
- make   
`# make`   
`# make install`

## Snortの設定
Snortインストール後、Snortを使用するためにはいくつかの設定が必要になります。

以降、`cp`コマンドを使用しているときは`/usr/local/src/snort-2.9.16`のディレクトリで実行しています。

### ユーザ作成

- ユーザ作成   
`# useradd snort`

### /etc/sysconfig/snortの編集
`/etc/sysconfig/snort`ファイルはサービスの設定を行います。

- snort.sysconfigのコピー
`# cp rpm/snort.sysconfig /etc/sysconfig/snort`

- snort.sysconfigの編集
`# vi /etc/sysconfig/snort`

INTERFACEの値を使用しているインターフェースの値に変更します。

```console
< INTERFACE=eth0
---
> INTERFACE=enp0s8
```

### 起動スクリプトの作成
デフォルトの起動スクリプトの実行パスは`/usr/sbin/snort`となっています。インストールされたパスと違うため、シンボリックリンクを作成します。

- 起動スクリプトの作成   
`# cp rpm/snortd /etc/init.d/`   
`# chmod 755 /etc/init.d/snortd`
- シンボリックリンクの作成   
`# ln -s /usr/local/bin/snort /usr/sbin/snort`

### ルールセット
一般的にセキュリティソフトやIDSでは、攻撃者の特徴的なアクセスのパターンなどをシグネチャとよんでいます。Snortではルールセット（ルールファイル）に記述されているシグネチャを参照して不正なパケットを検出します。公式サイトのコミュニティ版のルールセットは無料で使用することができます。

- ルールセットのダウンロード   
`# cd /tmp`   
`# wget https://www.snort.org/downloads/community/community-rules.tar.gz`
- 解凍    
`# tar xzvf community-rules.tar.gz`
- ディレクトリ移動  
`# cd community-rules`
- ディレクトリの作成  
`# mkdir -p /etc/snort/rules`
- sid-msg.mapのコピー   
`# cp sid-msg.map /etc/snort/`
- community.rulesのコピー   
`# cp community.rules /etc/snort/rules/`
- 権限変更   
`# chown -R snort.snort /etc/snort`

### ログ設定

- ディレクトリの作成   
`# mkdir /var/log/snort`
- 権限変更   
`# chown -R snort.snort /var/log/snort`
- snort.logrotateのコピー   
`# cd /usr/local/src/snort-2.9.16`   
`# cp rpm/snort.logrotate /etc/logrotate.d/snort`

### /etc/snort/snort.confの編集
`/etc/snort/snort.conf`ファイルは動作設定ファイルになります。

- snort.confの編集   
`# vi /etc/snort/snort.conf`

**ipvar HOME_NET**の値を変更し、監視するネットワークを指定します。

```console
< ipvar HOME_NET any
---
> ipvar HOME_NET 192.168.1.0/24
```

外部ネットワークアドレスを設定します。 基本的にデフォルトの「any」を指定します。

```console
ipvar EXTERNAL_NET any
```

以下変数の相対パスをカレントパスに修正します。

```console
< var RULE_PATH ../rules
< var SO_RULE_PATH ../so_rules
< var PREPROC_RULE_PATH ../preproc_rules
---
> var RULE_PATH ./rules
> var SO_RULE_PATH ./so_rules
> var PREPROC_RULE_PATH ./preproc_rules
113,114c113,114
< var WHITE_LIST_PATH ../rules
< var BLACK_LIST_PATH ../rules
---
> var WHITE_LIST_PATH ./rules
> var BLACK_LIST_PATH ./rules
510,512c510,513
```

使用していない設定値のコメントアウト及びcommunity.rulesを追加します。

```console
<    nested_ip inner, \
<    whitelist $WHITE_LIST_PATH/white_list.rules, \
<    blacklist $BLACK_LIST_PATH/black_list.rules 
---
> #   nested_ip inner, \
>    nested_ip inner
> #   whitelist $WHITE_LIST_PATH/white_list.rules, \
> #   blacklist $BLACK_LIST_PATH/black_list.rules 

< include $RULE_PATH/app-detect.rules
< include $RULE_PATH/attack-responses.rules
< include $RULE_PATH/backdoor.rules
< include $RULE_PATH/bad-traffic.rules
< include $RULE_PATH/blacklist.rules
< include $RULE_PATH/botnet-cnc.rules
< include $RULE_PATH/browser-chrome.rules
< include $RULE_PATH/browser-firefox.rules
< include $RULE_PATH/browser-ie.rules
< include $RULE_PATH/browser-other.rules
< include $RULE_PATH/browser-plugins.rules
< include $RULE_PATH/browser-webkit.rules
< include $RULE_PATH/chat.rules
< include $RULE_PATH/content-replace.rules
< include $RULE_PATH/ddos.rules
< include $RULE_PATH/dns.rules
< include $RULE_PATH/dos.rules
< include $RULE_PATH/experimental.rules
< include $RULE_PATH/exploit-kit.rules
< include $RULE_PATH/exploit.rules
< include $RULE_PATH/file-executable.rules
< include $RULE_PATH/file-flash.rules
< include $RULE_PATH/file-identify.rules
< include $RULE_PATH/file-image.rules
< include $RULE_PATH/file-multimedia.rules
< include $RULE_PATH/file-office.rules
< include $RULE_PATH/file-other.rules
< include $RULE_PATH/file-pdf.rules
< include $RULE_PATH/finger.rules
< include $RULE_PATH/ftp.rules
< include $RULE_PATH/icmp-info.rules
< include $RULE_PATH/icmp.rules
< include $RULE_PATH/imap.rules
< include $RULE_PATH/indicator-compromise.rules
< include $RULE_PATH/indicator-obfuscation.rules
< include $RULE_PATH/indicator-shellcode.rules
< include $RULE_PATH/info.rules
< include $RULE_PATH/malware-backdoor.rules
< include $RULE_PATH/malware-cnc.rules
< include $RULE_PATH/malware-other.rules
< include $RULE_PATH/malware-tools.rules
< include $RULE_PATH/misc.rules
< include $RULE_PATH/multimedia.rules
< include $RULE_PATH/mysql.rules
< include $RULE_PATH/netbios.rules
< include $RULE_PATH/nntp.rules
< include $RULE_PATH/oracle.rules
< include $RULE_PATH/os-linux.rules
< include $RULE_PATH/os-other.rules
< include $RULE_PATH/os-solaris.rules
< include $RULE_PATH/os-windows.rules
< include $RULE_PATH/other-ids.rules
< include $RULE_PATH/p2p.rules
< include $RULE_PATH/phishing-spam.rules
< include $RULE_PATH/policy-multimedia.rules
< include $RULE_PATH/policy-other.rules
< include $RULE_PATH/policy.rules
< include $RULE_PATH/policy-social.rules
< include $RULE_PATH/policy-spam.rules
< include $RULE_PATH/pop2.rules
< include $RULE_PATH/pop3.rules
< include $RULE_PATH/protocol-finger.rules
< include $RULE_PATH/protocol-ftp.rules
< include $RULE_PATH/protocol-icmp.rules
< include $RULE_PATH/protocol-imap.rules
< include $RULE_PATH/protocol-pop.rules
< include $RULE_PATH/protocol-services.rules
< include $RULE_PATH/protocol-voip.rules
< include $RULE_PATH/pua-adware.rules
< include $RULE_PATH/pua-other.rules
< include $RULE_PATH/pua-p2p.rules
< include $RULE_PATH/pua-toolbars.rules
< include $RULE_PATH/rpc.rules
< include $RULE_PATH/rservices.rules
< include $RULE_PATH/scada.rules
< include $RULE_PATH/scan.rules
< include $RULE_PATH/server-apache.rules
< include $RULE_PATH/server-iis.rules
< include $RULE_PATH/server-mail.rules
< include $RULE_PATH/server-mssql.rules
< include $RULE_PATH/server-mysql.rules
< include $RULE_PATH/server-oracle.rules
< include $RULE_PATH/server-other.rules
< include $RULE_PATH/server-webapp.rules
< include $RULE_PATH/shellcode.rules
< include $RULE_PATH/smtp.rules
< include $RULE_PATH/snmp.rules
< include $RULE_PATH/specific-threats.rules
< include $RULE_PATH/spyware-put.rules
< include $RULE_PATH/sql.rules
< include $RULE_PATH/telnet.rules
< include $RULE_PATH/tftp.rules
< include $RULE_PATH/virus.rules
< include $RULE_PATH/voip.rules
< include $RULE_PATH/web-activex.rules
< include $RULE_PATH/web-attacks.rules
< include $RULE_PATH/web-cgi.rules
< include $RULE_PATH/web-client.rules
< include $RULE_PATH/web-coldfusion.rules
< include $RULE_PATH/web-frontpage.rules
< include $RULE_PATH/web-iis.rules
< include $RULE_PATH/web-misc.rules
< include $RULE_PATH/web-php.rules
< include $RULE_PATH/x11.rules
---
> include $RULE_PATH/community.rules
```

他ホスト宛のパケットを受け取るためにプロミスキャスモードの設定を行います。インターフェースのファイルに**PROMISC**の設定値を追記します。

- ネットワークの設定   
`# vi /etc/sysconfig/network-scripts/ifcfg-enp0s8`

```console
PROMISC=yes
```

## Snortの動作確認
検証用のルールを作成し、動作確認を行います。
本記事では例としてping検知を行います。

### ルールファイルの編集
ルールファイルは`/etc/snort/rules`配下に格納します。
ルールファイルについて説明します。

ルールファイルのシグネチャはルールヘッダと、ルールボディで構成されています。

```text
ルールヘッダ：ルールアクション/プロトコル/IPアドレス/ポート/方向演算子/IPアドレス/ポート/
ルールボディ：オプション
```

ルールアクションには以下の種類があります。

| 種別       |概要        |
|:-----------------|:------------------|
|alert             |ルールにマッチしたパケットをログに出力し、警告を出力 | 
|log             |ルールにマッチしたパケットをログに出力| 
|pass             |ルールにマッチしたパケットを無視 | 
|acitive             |ルールにマッチしたパケットについて警告を出力し、対応するdynamicルールのアクションを実行 | 
|dynamic             |該当するパケットをログに出力 | 

- local.rulesの編集   
`# vi /etc/snort/rules/local.rules`

```console
alert icmp any any -> any any (msg: "ICMP Packet detected"; sid:999999;)
```

ルール編集後はsnortの再起動が必要になります。

### Snort起動確認
デフォルトの起動スクリプトの中でオプション`-D`が指定されいているため、起動スクリプトを実行した場合はデーモンモードで起動します。

- 起動   
`#  /etc/init.d/snortd start`

**起動時にエラーが出ないことをシスログを見て確認します。**

正常に起動している場合は、以下の様なプロセスが確認できます。

```console
[root@localhost snort-2.9.16]# ps aux | grep snort | grep -v grep
snort    11481  0.0  6.3 164828 64456 ?        Ssl  03:03   0:07 /usr/sbin/snort -A fast -b -d -D -i enp0s8 -u snort -g snort -c /etc/snort/snort.conf -l /var/log/snort
```

また、以下の様にスニファとして起動することもできます。
スニファとして起動する場合は処理に時間がかかるため、基本的に動作確認以外では使用することはないと思います。

`# snort -v`

```console
Running in packet dump mode

        --== Initializing Snort ==--
Initializing Output Plugins!
pcap DAQ configured to passive.
Acquiring network traffic from "enp0s3".
Decoding Ethernet

        --== Initialization Complete ==--

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.9.16 GRE (Build 118) 
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/contact#team
           Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using libpcap version 1.9.1 (with TPACKET_V3)
           Using PCRE version: 8.32 2012-11-30
           Using ZLIB version: 1.2.7

Commencing packet processing (pid=17768)
```

### ルールファイル（local.rules）の検証

別の端末からpingを実行します。
以下のログを見るとICMPのパケットが検出されたことが確認できます。

- ログ確認   
`# tail -f /var/log/snort/alert `

```console
04/22-03:04:27.545270  [**] [1:999999:0] ICMP Packet detected [**] [Priority: 0] {ICMP} 192.168.1.10 -> 192.168.1.16
```

# おわりに
Snotはインストールも一苦労ですが、実際に運用する場合はルールセットのチューニングが発生したり、膨大のログから異常を確認するなどの作業が発生します。

ルールファイルの自動更新ができるOinkmasterや、Snortが出力したログファイルをHTMLファイルにしてWebブラウザ上で確認できるようにすることができるSnortSnarfというツールがあります。

余談ですが、Snortは鼻を鳴らすという意味があります。