WPScanを使ってWordpressの脆弱性チェックと改善

#はじめに
WPScanを使用することで、プラグインやテーマの脆弱性チェックすることができます。

#流れ
①アカウント作成
②Dockerで脆弱性チェック
③エラー対処
④脆弱性への改善

#アカウント作成
[WPScan.com](https://wpscan.com/?__cf_chl_jschl_tk__=pmd_3.X8ZSEWCDj41sB0mRpsWfGYeyWMFhwMMjGwP0axcSo-1633955890-0-gqNtZGzNAjujcnBszQi9)でアカウントを作成すると、APIトークンを作成することができます。
APIトークンは、後ほど作成します。
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/7934caa8-c68e-48bd-cf96-8ce88b33d288.png">

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/f69086b4-c4f3-1be7-8a91-2caaedf4a773.png">

#Dockerで脆弱性チェック

まず、Dockerイメージをpullします。

```
$ docker pull wpscanteam/wpscan
```

WPScanのAPIトークンを使って、WordPressの脆弱性をチェックします。
urlは、チェックしたいurlを各自いれます。


```
$ docker run -it --rm wpscanteam/wpscan --url http://xxxxxxx.com  --api-token xxxxxxxxxxxxxxxxxxxxxxxx
````

これで脆弱性のチェックができます。

###オプション
・`-e vp`：脆弱なプラグインのみをチェック
・`-e vt`：脆弱なテーマのみをチェック
・`-e tt`： Timthumbファイル
・`-e cb`：wp-configのバックアップ
・`-e dbe `：DBバックアップ
・`-e u `：ユーザー名
・`-e m`：メディア
・`指定なし`：上記の項目全てチェックします。
複数指定する場合、・`-e vp,vt`のように`,`でつなぎます。


#エラー対処

```
$ docker run -it --rm wpscanteam/wpscan --url http://xxxxxxx.com  --api-token xxxxxxxxxxxxxxxxxxxxxxxx

_______________________________________________________________

         __          _______   _____

         \ \        / /  __ \ / ____|

          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®

           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \

            \  /\  /  | |     ____) | (__| (_| | | | |

             \/  \/   |_|    |_____/ \___|\__,_|_| |_|



         WordPress Security Scanner by the WPScan Team

                         Version 3.8.19

       Sponsored by Automattic - https://automattic.com/

       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart

_______________________________________________________________





Scan Aborted: The url supplied 'http://xxxxxxxxx' seems to be down (Server returned nothing (no headers, no data))

```
下記のようにスキャンできない場合があります。

```
Scan Aborted: The url supplied 'http://xxxxxxxxx' seems to be down (Server returned nothing (no headers, no data))
```

###対処法として、`オプション：--user-agent`を使用するとスキャンできます。

```
$ docker run -it --rm wpscanteam/wpscan --url http://xxxxxxx.com  --api-token xxxxxxxxxxxxxxxxxxxxxxxx --user-agent
```

#脆弱性への改善
今回は、DockerでWordpressを起動した際の脆弱性チェックになります。
パスは異なる可能性があります。

##ヘッダーの値削除

```terminal
[+] Headers
 | Interesting Entries:
 |  - server: Apache/2.4.51 (Debian)
 |  - x-powered-by: PHP/7.4.01
 | Found By: Headers (Passive Detection)
 | Confidence: 100%
```
ヘッダーに`Apache`と`PHP`の情報を確認できます。
実行アプリケーションが確認できれば攻撃方法も特定しやすくなるため非表示にしてみます。

###apacheのバージョン非表示対応
`security.conf`に以下の値を書き込みましょう。

```/etc/apache2/conf-available/security.conf
ServerSignature Off
ServerTokens Prod
```
こちらにある場合もあります。`/etc/apache2/conf-available/security.conf`
詳しい解説はこちら

https://qiita.com/bezeklik/items/1c4145652661cf5b2271

security.confの全体のコード内容は一番下のページに貼っておきます。

###nginxのバージョン非表示対応
nginx.confファイルのserver_tokens offのコメントアウトをとります。

```/etc/nginx/nginx.conf

http {
  ~
  # server_tokens off;
  ↓ コメントアウトをとる
  server_tokens off;
  ~
```
nginx.confファイルを保存して 、書き込みが問題ないことを確認し、nginx を再読み込みしましょう。

```
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

$ sudo nginx -s reload
```
![スクリーンショット 2021-11-26 18.48.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/5941fb87-72fb-78b9-a716-ef5542b493b7.png)
↓バージョンが見えなくなりました！
![スクリーンショット 2021-11-26 18.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/c433aec8-5858-334f-b720-1940c7f75865.png)

###PHPのバージョン非表示対応
php.iniファイルに書き込みます。
php.iniファイルを検索し、修正します。

```terminal
$ php -i | grep php.ini 
Configuration File (php.ini) Path => /usr/local/etc/php  #php.iniファイルのパス
```

```php:/usr/local/etc/php
expose_php = off
```

##readme.html削除


```terminal
[+] WordPress readme found: https://www.hoge.com/readme.html
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%
```
文字通り削除しましょう

##xmlrpcの無効化



```terminal
[+] XML-RPC seems to be enabled: https://www.hoge.com/xmlrpc.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%
 | References:
 |  - http://codex.wordpress.org/XML-RPC_Pingback_API
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
 |  - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
```

スマホアプリ経由などリモート投稿するために、xmlrpcを使用します。しかしDoS攻撃に悪用されてしまう可能性がある機能です。リモート投稿等することがなければ、無効にします。

###apacheの場合

`/var/www/html(ルートディレクトリ)`配下に、`.htaccess`がありますので追記します。

```terminal
# xmlrpc.phpへのアクセスを無効化する
<Files xmlrpc.php>
Order Allow,Deny
Deny from all
#allow from xxx.xxx.xxx.xxx # アクセスする必要が出たらIP指定
</Files>
```

###nginxの場合

```/etc/nginx/nginx.conf

location = /xmlrpc.php {
deny all;
return 404;
}
```
nginx.confファイルを保存して 、書き込みが問題ないことを確認し、nginx を再読み込みしましょう。

```
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

$ sudo nginx -s reload
```

https://oneuro.net/wp-how-to-deny-xmlrpc-php

https://kinsta.com/jp/blog/xmlrpc-php/#xmlrpcphp-1


##wp-cron.php 無効化

```
[+] The external WP-Cron seems to be enabled: https://www.hoge.com/wp-cron.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 60%
 | References:
 |  - https://www.iplocation.net/defend-wordpress-from-ddos
 |  - https://github.com/wpscanteam/wpscan/issues/1299
```

`wp-cron.php`は、WordPressで予約投稿する場合に使用されます。
これもDoSに悪用される危険があるため無効化、予約投稿やバックアップの処理、自動更新もwp-cronで実行されるのでサーバー内のcronで実行するように変更します。

https://s8a.jp/wordpress-cron#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E5%81%B4%E3%81%AEcron%E3%81%AE%E6%9C%89%E5%8A%B9%E5%8C%96

###③箇所変更します。

①wp-config.php

```php:wp-config.php
<?php
define('DISABLE_WP_CRON', 'true'); # 先頭に記載しないと無効にできない
```

②crontab
`wp-cron.php`が`/var/www/html配下`にある場合

```
$ crontab -e
```


```:crontab　-e
* * * * * /usr/bin/php7.4 /var/www/html/wp-cron.php > /dev/null 2>&1
```

もしくは

```:/etc/crontab
* * * * * apache /usr/bin/php -q /var/www/html/wp-cron.php >/dev/null 2>&1
```

③.htaccess

```.htaccess:.htaccess
<Files wp-cron.php>
order deny,allow
deny from all
#allow from xxx.xxx.xxx.xxx　# アクセスする必要が出たらIP指定
</Files>
```

##robots.txtが存在する

```terminal
[+] robots.txt found: https://www.hoge.com/robots.txt
 | Interesting Entries:
 |  - /wp-admin/
 |  - /wp-admin/admin-ajax.php
 | Found By: Robots Txt (Aggressive Detection)
 | Confidence: 100%
```
robots.txtに記載があるというこのメッセージ
おそらく対象パスにファイルがあることを記しているということになりますが、ajaxの機能を除外するのはコストが高すぎるため、特になにもしません。

##プラグインのバージョンアップ

```terminal
[+] contact-form-7
 | Location: https://www.hoge.com/wp-content/plugins/contact-form-7/
 | Last Updated: 2021-10-11T15:11:00.000Z
 | [!] The version is out of date, the latest version is 5.5.1
 |
 | Found By: Urls In Homepage (Passive Detection)
 | Confirmed By: Urls In 404 Page (Passive Detection)
 |
 | Version: 5.4.2 (100% confidence)
 | Found By: Query Parameter (Passive Detection)
 |  - https://www.hoge.com/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.4.2
 | Confirmed By:
 |  Readme - Stable Tag (Aggressive Detection)
 |   - https://www.hoge.com/wp-content/plugins/contact-form-7/readme.txt
 |  Readme - ChangeLog Section (Aggressive Detection)
 |   - https://www.hoge.com/wp-content/plugins/contact-form-7/readme.txt

```

この場合、`contact-form-7`を最新のバージョンにしましょう。

#参考

https://www.wivern.com/security20150526.html

https://qiita.com/koujimatsuda11/items/d49e8642dea1a1b0d067

https://qiita.com/bezeklik/items/1c4145652661cf5b2271

#security.confの全体

```security.conf:security.conf
#
# Disable access to the entire file system except for the directories that
# are explicitly allowed later.
#
# This currently breaks the configurations that come with some web application
# Debian packages.
#
#<Directory />
#   AllowOverride None
#   Require all denied
#</Directory>


# Changing the following options will not really affect the security of the
# server, but might make attacks slightly more difficult in some cases.

#
# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of:  Full | OS | Minimal | Minor | Major | Prod
# where Full conveys the most information, and Prod the least.
#ServerTokens Minimal
#ServerTokens OS
#ServerTokens Full
ServerTokens Prod

#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (internal error documents, FTP directory
# listings, mod_status and mod_info output etc., but not CGI generated
# documents or custom error documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of:  On | Off | EMail
ServerSignature Off
#ServerSignature On

#
# Allow TRACE method
#
# Set to "extended" to also reflect the request body (only for testing and
# diagnostic purposes).
#
# Set to one of:  On | Off | extended
TraceEnable Off
#TraceEnable On

#
# Forbid access to version control directories
#
# If you use version control systems in your document root, you should
# probably deny access to their directories. For example, for subversion:
#
#<DirectoryMatch "/\.svn">
#   Require all denied
#</DirectoryMatch>

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
#
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
#Header set X-Frame-Options: "sameorigin"


# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
```