開啟AWS WAF並開啟日誌儲存至S3

Hachibye
12 min readAug 27, 2024

--

Enable AWS WAF and enable log storage to S3

  • 搜尋AWS WAF功能

https://us-east-1.console.aws.amazon.com/wafv2/homev2/start?region=ap-southeast-1

  • 建立web acl
  • 選取關聯項目(LB)
  • 加入受管的規則
  • 左側選單點擊Web ACLs
  • 主要面板

若有阻擋

  • 只看阻擋
  • 其他
  • 開啟log
  • Sampled Requests

AWS WAF 的 Sampled Requests 功能提供對進入的 Web 請求的詳細視圖。它隨機選擇一部分與 WAF 規則匹配的請求,幫助用戶分析和了解規則如何影響流量。通過 Sampled Requests,您可以檢視請求的原始數據,包括 IP 地址、HTTP 方法、URI 和標頭資訊,有助於調整規則以提高防護效果。這對於排除錯誤、優化 Web 安全策略和確保應用程式的正確防護非常有用。

  • 展開詳情(允許或阻擋)
  • 過濾請求(只顯示阻擋)
  • cloudwatch監控
  • 通過S3儲存桶查看LB日誌

2024–08–26 — — — — 1.1.1.1 37839 443 TLSv1.3 TLS_AES_128_GCM_SHA256 — “-” — — Failed:UnmappedConnectionError TID_ — — — —

Failed: UnmappedConnectionError: 請求結果,表示這個請求因 UnmappedConnectionError 錯誤而失敗。這可能意味著伺服器遇到了無法識別或映射的連接錯誤。

  • athena查詢
  • 確認資料格式
SELECT * FROM aaalb_access_logs LIMIT 10
  • 只查詢今天的403
  • 查看轉發行為

以上LB只能查看到失敗的時間、狀態、來源目的位置

具體命中什麼規則還是需要查詢WAF日誌

*需額外開啟WAF日誌功能

CREATE DATABASE IF NOT EXISTS waf_logs;

CREATE EXTERNAL TABLE IF NOT EXISTS waf_logs.waf_logs_table (
requestid string,
timestamp string,
clientip string,
action string,
rulegroupid string,
rulename string,
ratebasedrule string,
``rulegroupname`` string,
uri string,
method string,
headers string
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '1'
) LOCATION 's3://your-bucket-name/path/to/waf/logs/'
TBLPROPERTIES ('has_encrypted_data'='false');
SELECT *
FROM waf_logs.waf_logs_table
WHERE action = 'BLOCK';

官方文件

  • 開啟WAF日誌

建立S3儲存桶並符合命名規範

  • 配置S3儲存桶的許可權限
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSWAFLogsPolicy",
"Effect": "Allow",
"Principal": {
"Service": "waf.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::your-bucket-name/*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "your-aws-account-id"
},
"ArnLike": {
"aws:SourceArn": "arn:aws:wafv2:region:your-aws-account-id:*/webacl/*"
}
}
}
]
}
  • 查看日誌
  • 查看日誌的請求詳情,以及WAF行為
  • athena查詢
  • 建表
CREATE EXTERNAL TABLE `waf_logs`(
`timestamp` bigint,
`formatversion` int,
`webaclid` string,
`terminatingruleid` string,
`terminatingruletype` string,
`action` string,
`terminatingrulematchdetails` array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>,
`httpsourcename` string,
`httpsourceid` string,
`rulegrouplist` array <
struct <
rulegroupid: string,
terminatingrule: struct <
ruleid: string,
action: string,
rulematchdetails: array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>
>,
nonterminatingmatchingrules: array <
struct <
ruleid: string,
action: string,
overriddenaction: string,
rulematchdetails: array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>,
challengeresponse: struct <
responsecode: string,
solvetimestamp: string
>,
captcharesponse: struct <
responsecode: string,
solvetimestamp: string
>
>
>,
excludedrules: string
>
>,
`ratebasedrulelist` array <
struct <
ratebasedruleid: string,
limitkey: string,
maxrateallowed: int
>
>,
`nonterminatingmatchingrules` array <
struct <
ruleid: string,
action: string,
rulematchdetails: array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>,
challengeresponse: struct <
responsecode: string,
solvetimestamp: string
>,
captcharesponse: struct <
responsecode: string,
solvetimestamp: string
>
>
>,
`requestheadersinserted` array <
struct <
name: string,
value: string
>
>,
`responsecodesent` string,
`httprequest` struct <
clientip: string,
country: string,
headers: array <
struct <
name: string,
value: string
>
>,
uri: string,
args: string,
httpversion: string,
httpmethod: string,
requestid: string
>,
`labels` array <
struct <
name: string
>
>,
`captcharesponse` struct <
responsecode: string,
solvetimestamp: string,
failureReason: string
>,
`challengeresponse` struct <
responsecode: string,
solvetimestamp: string,
failureReason: string
>,
`ja3Fingerprint` string,
`oversizefields` string,
`requestbodysize` int,
`requestbodysizeinspectedbywaf` int
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://DOC-EXAMPLE-BUCKET/prefix/'
  • 查詢台灣(TW)遭封鎖的請求

這些在剛才官方文件上都有範例可以查詢使用喔

SELECT 
COUNT(httpRequest.country) as count,
httpRequest.country
FROM waf_logs
WHERE
terminatingruletype='RATE_BASED' AND
httpRequest.country='TW'
GROUP BY httpRequest.country
ORDER BY count
LIMIT 100;
  • 開啟WAF日誌(2)

也可以打到cloudwatch日誌群組,即時追蹤

再結合Kinesis,DynamoDB結合送給Graylog~

--

--

Hachibye
Hachibye

Written by Hachibye

字幕組退休勞工 ... DevOps/系統/雲端/資安

No responses yet