構成
- WAFで攻撃を検知したらSlackへ飛ばす
WAF → KinesisFirehose → Lambda → Slack
↓
→ S3バケット
WAF
ルール設定
- ルールは汎用的なものを設定
- AWSManagedRulesCommonRuleSet
- AWS-AWSManagedRulesLinuxRuleSet
- DefaultActionはAllow
接続リソース設定
- 紐づけたいALBを指定
Logging and metrics設定
KinesisFirehose
Transform設定
- kinesisFirehoseのJson出力をLambdaへ渡す
- Lambda側でのトリガーでKinesisFirehoseを指定することはできない
Lambda設定
- トリガー、送信先は指定なし
ソースコード
- ランタイムはpython3.8
- AWSManagedRulesCommonRuleSetの中で
NoUserAgent_HEADER
とUserAgent_BadBots_HEADER
がやたらでるので、Slackへは飛ばしたくない - それ以外のルールはSlackへ飛ばす
import base64
import json
import os
import urllib.request
def lambda_handler(event, context):
output = []
for record in event['records']:
output_record = {
'recordId': record['recordId'],
'result': 'Ok',
'data': record['data']
}
output.append(output_record)
a = base64.b64decode(record['data'])
b = json.loads(a)
# if b['action'] != 'ALLOW':
# print("action not ALLOW")
if b["ruleGroupList"][0]["terminatingRule"]["ruleId"] != 'NoUserAgent_HEADER' and b["ruleGroupList"][0]["terminatingRule"]["ruleId"] != 'UserAgent_BadBots_HEADER':
print("terminatingRule is not NoUserAgent_HEADER")
response = post_slack(b)
print(output_record)
return {'records': output}
def post_slack(msg):
send_data = {
"username": "notify_slack",
"icon_emoji": ":vampire:",
"color":"#D00000",
"text": "WAF攻撃検知",
"attachments":[
{
"fallback":"fallback Test",
"color":"#D00000",
"fields":[
{
"title":"詳細内容",
"value":str(msg)
}
]
}
]
}
send_text = "payload=" + json.dumps(send_data)
# send_text = "payload=" + json.dumps(jsondata)
method = 'POST'
headers = {'Content-Type': 'application/json'}
WEB_HOOK_URL = os.environ['WEBHOOK_URL']
request = urllib.request.Request(
WEB_HOOK_URL,
data=send_text.encode('utf-8'),
method=method
)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode('utf-8')
print("send ok")
環境変数
- SlackのWebhookURLを指定する
動作確認用のテストデータ
- kinesisFirehoseから送られるであろうデータ形式
- dataはkinesisFirehoseからs3バケットに出力されているWAFのログをbase64エンコードしたもの
- lambda関数では、data部分をデコードし、terminatingRuleを判定するようにしている
{
"invocationId": "invocationIdExample",
"deliverySteamArn": "arn:aws:kinesis:EXAMPLE",
"region": "ap-northeast-1",
"records": [
{
"recordId": "49546986683135544286507457936321625675700192471156785154",
"approximateArrivalTimestamp": 1495072949453,
"kinesisRecordMetadata": {
"sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
"subsequenceNumber": "123456",
"partitionKey": "partitionKey-03",
"shardId": "shardId-000000000000",
"approximateArrivalTimestamp": 1495072949453
},
"data": "ew0KCSJ0aW1lc3RhbXAiOiAxNjA0Nzc0MzM1MTEyLA0KCSJmb3JtYXRWZXJzaW9uIjogMSwNCgkid2ViYWNsSWQiOiAiYXJuOmF3czp3YWZ2MjphcC1ub3J0aGVhc3QtMToxMTExMTExMTExMTpyZWdpb25hbC93ZWJhY2wvdmFtZGVtaWMtd2FmdjIveHh4eHh4eHgtY2UwYi00ZWYwLTkxZGUtYjQ0OTg1NmFmNDUxIiwNCgkidGVybWluYXRpbmdSdWxlSWQiOiAiQVdTTWFuYWdlZFJ1bGVzQ29tbW9uUnVsZVNldCIsDQoJInRlcm1pbmF0aW5nUnVsZVR5cGUiOiAiTUFOQUdFRF9SVUxFX0dST1VQIiwNCgkiYWN0aW9uIjogIkJMT0NLIiwNCgkidGVybWluYXRpbmdSdWxlTWF0Y2hEZXRhaWxzIjogW10sDQoJImh0dHBTb3VyY2VOYW1lIjogIkFMQiIsDQoJImh0dHBTb3VyY2VJZCI6ICIxMTExMTExMTExMS1hcHAvdmFtZGVtaWMtZGV2LWJ1c2luZXNzLWRldjItYWxiLzI4YWU3NjcyYzExMTExMWRjIiwNCgkicnVsZUdyb3VwTGlzdCI6IFsNCgkJew0KCQkJInJ1bGVHcm91cElkIjogIkFXUyNBV1NNYW5hZ2VkUnVsZXNDb21tb25SdWxlU2V0IiwNCgkJCSJ0ZXJtaW5hdGluZ1J1bGUiOiB7DQoJCQkJInJ1bGVJZCI6ICJOb1VzZXJBZ2VudF9IRUFERVIiLA0KCQkJCSJhY3Rpb24iOiAiQkxPQ0siLA0KCQkJCSJydWxlTWF0Y2hEZXRhaWxzIjogbnVsbA0KCQkJfSwNCgkJCSJub25UZXJtaW5hdGluZ01hdGNoaW5nUnVsZXMiOiBbXSwNCgkJCSJleGNsdWRlZFJ1bGVzIjogbnVsbA0KCQl9DQoJXSwNCgkicmF0ZUJhc2VkUnVsZUxpc3QiOiBbXSwNCgkibm9uVGVybWluYXRpbmdNYXRjaGluZ1J1bGVzIjogW10sDQoJImh0dHBSZXF1ZXN0Ijogew0KCQkiY2xpZW50SXAiOiAiMTI2LjIwOS4yMjEuNCIsDQoJCSJjb3VudHJ5IjogIkpQIiwNCgkJImhlYWRlcnMiOiBbDQoJCQl7DQoJCQkJIm5hbWUiOiAiSG9zdCIsDQoJCQkJInZhbHVlIjogImRldjIudmFtZGVtaWMuanAiDQoJCQl9LA0KCQkJew0KCQkJCSJuYW1lIjogIkFjY2VwdCIsDQoJCQkJInZhbHVlIjogIiovKiINCgkJCX0NCgkJXSwNCgkJInVyaSI6ICIvIiwNCgkJImFyZ3MiOiAiIiwNCgkJImh0dHBWZXJzaW9uIjogIkhUVFAvMS4xIiwNCgkJImh0dHBNZXRob2QiOiAiR0VUIiwNCgkJInJlcXVlc3RJZCI6ICIxLTVmYTZlOWJmLTIyMmU3NmNkNWJkNDQyYTEyYjg5YmM5YSINCgl9DQp9"
}
]
}
テスト
- こちらの2パターンのテストを行い、挙動を見る
参考