Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Bot Control Rules  选择 CAPTCHA


添加:Token Domain List 

Image Removed



webacl-alb-api-001默认规则:AWS-AWSManagedRulesBotControlRuleSet规则如下

Code Block
themeRDark
{
  "Name": "AWS-AWSManagedRulesBotControlRuleSet",
  "Priority": 0,
  "Statement": {
    "ManagedRuleGroupStatement": {
      "VendorName": "AWS",
      "Name": "AWSManagedRulesBotControlRuleSet",
      "ScopeDownStatement": {
        "AndStatement": {
          "Statements": [
            {
              "ByteMatchStatement": {
                "SearchString": "/waf/query",
                "FieldToMatch": {
                  "UriPath": {}
                },
                "TextTransformations": [
                  {
                    "Priority": 0,
                    "Type": "LOWERCASE"
                  }
                ],
                "PositionalConstraint": "EXACTLY"
              }
            },
            {
              "NotStatement": {
                "Statement": {
                  "ByteMatchStatement": {
                    "SearchString": "POST",
                    "FieldToMatch": {
                      "Method": {}
                    },
                    "TextTransformations": [
                      {
                        "Priority": 0,
                        "Type": "NONE"
                      }
                    ],
                    "PositionalConstraint": "EXACTLY"
                  }
                }
              }
            }
          ]
        }
      },
      "ManagedRuleGroupConfigs": [
        {
          "AWSManagedRulesBotControlRuleSet": {
            "InspectionLevel": "TARGETED",
            "EnableMachineLearning": true
          }
        }
      ],
      "RuleActionOverrides": [
        {
          "Name": "SignalNonBrowserUserAgent",
          "ActionToUse": {
            "Captcha": {}
          }
        },
        {
          "Name": "TGT_VolumetricIpTokenAbsent",
          "ActionToUse": {
            "Captcha": {}
          }
        }
      ]
    }
  },
  "OverrideAction": {
    "None": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "AWS-AWSManagedRulesBotControlRuleSet"
  }
}



Webacl-alb-api-001自定义规则:

Code Block
themeRDark
{
  "Name": "Block-Requests-With-Missing-Or-Rejected-Token-Label",
  "Priority": 1,
  "Statement": {
    "AndStatement": {
      "Statements": [
        {
          "OrStatement": {
            "Statements": [
              {
                "LabelMatchStatement": {
                  "Scope": "LABEL",
                  "Key": "awswaf:managed:token:absent"
                }
              },
              {
                "LabelMatchStatement": {
                  "Scope": "LABEL",
                  "Key": "awswaf:managed:token:rejected"
                }
              }
            ]
          }
        },
        {
          "NotStatement": {
            "Statement": {
              "ByteMatchStatement": {
                "SearchString": "POST",
                "FieldToMatch": {
                  "Method": {}
                },
                "TextTransformations": [
                  {
                    "Priority": 0,
                    "Type": "NONE"
                  }
                ],
                "PositionalConstraint": "EXACTLY"
              }
            }
          }
        }
      ]
    }
  },
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "Block-Requests-With-Missing-Or-Rejected-Token-Label"
  }
}

...

1、WEB前端代码样例

Code Block
themeRDark
<html>
<head>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Waf Captcha Test</title>
	<script type="text/javascript" src="https://xxxxxxxxxxxx73f53964xxxx.usap-westsoutheast-21.captcha-sdk.awswaf.com/xxxxxxxxxxxx/xxxxxxxxxxxx73f53964xxxx/jsapi.js" defer></script>
</head>

<body>
    
<h1>Login Page</h1>
    
<p>Click on the below button to login</p>

<button    <button onclick="loginuserAction()">Login</button>

	
<script type="text/javascript">
	const apiURL  <script>
   = 'http://api001.bosicloud.one/waf/query';

     async function loginshowMyCaptcha() {
        const container  let user = {
= document.getElementById('container');
        AwsWafCaptcha.renderCaptcha(container, {
         name apiKey: 'usernamexxxxUYC7iqJbIcvhB5W21s/w9s3oAGcPai9tKFpadOUctVCXTZ0KndUbGATzSVqLx7s5dzl4MKwudqYWIEeyv0gnYZuSPchyf1mgZAXjRveATBmosCj2h3LEC2jAsagSWpzQGofjBvhFlC8CMnSmapPY8kekeIABcCyycj4rGUPVIX/iRAlGyZEFat68AfMJmsvoxRYiSIQQt1cJZnTNFlg/Uam3fQW9hFy/n6HJnO3nxs+kFwjotKnzMbHGOJXpbZlakYivF6t6mFoEea5PftXxszvDEdjJ6sUZI4aQbrJTfIcRF/9cM2L2WjNs0sVCj9fqu1lI75k2txelIrwoHOBxgJlSo8P23e5CShd1fBkYJgGdj8BobiIoMEqWgtIUN8s54EcaRzGUAZqinqsEONpBn8SBViBpl5I+RuiiEYsRBXpfHUzb5mbo/lzgO5YRCezY+B2LFAHmLzy6xeq390ig6xKmPRNXItxTDIudPELhIVO8rJ5vrYm+yf8wV1ppyJXuNP9pq9ifS2+jFfCt5kCNrjunTF0Hzbt08qHgPE1OZb9c2dSyXK8pvDGyaIbjROLgcCcJ7mRKqk2BvzSTCkY34SC98upXGUkMn1o36aOrbZoM15GcBGKPnQ0E0PmQrnfGGaIDJFZJRH8Hv/Q2s/o1GrluRmGEN39eeGuyYEs=_0_1xxxx',
            onSuccess: successFunction,
         surname   onError: 'surname'errorFunction,
        });
    };

    function successFunction() {
      const responsecontainer = await AwsWafIntegrationdocument.fetchgetElementById('https://yourdomain.com/waf/query',{container');
      container.innerHTML = '';
       method: 'POST',
   AwsWafIntegration.fetch(apiURL, {}).then(response => {
        response.json().then(myJson => {  headers: {renderResponse(myJson) });
      });
    }

    function     'Content-Type': 'application/json'errorFunction(error) {
           console.log(error);
    },

    function renderResponse(json) {
        if body: JSON.stringify(user)(json) {
           });
           const responseText = await response.text()
     container.innerHTML = "Result: The request resulted is Success.";
        } else {
       document.getElementById("display").innerText = responseText
   container.innerHTML = "Result: The request resulted is  console.log(responseText)Error.";
        }
   </script>
<p>Hello WAF!</p>
<div id='display'></div>
</body>
</html>

WAF Client JavaScript API 提供了 AwsWafIntegration.fetch()方法,是原生 JS fetch()方法的 Wrapper。与原生 fetch()方法相比,内部逻辑封装了 token 的请求和计算,并在业务 http 请求中自动加上了 token, 调用方法的参数与原生 JS fetch()相同。

样例代码使用 WAF client API 向后端发起了一个 Post 请求。后端使用 AWS EC2 部署 Echo-Server 做为测试用的 Web 服务器,实现返回 http response,并通过 ALB 提供对外访问。ALB 被刚才配置的 WEB ACL 所保护。

2、WEB前端代码部署

上传样例代码到EC2的NGINX里面,呈现为客户端可访问的网页如下:

4.4、步骤四:配置AWF

1、在WAF ACL关联ALB

Image Removed

2、配置Token Domain列表

当 WAF 从 web 请求中侦测 token 时,默认只会接受与 ACL 所关联资源的 host domain。当请求是通过ALB 时,需要把custom host domain 配置到 Token domain 列表中。配置参考文档

Image Removed

4.5、步骤五:场景测试

1、访问集成 SDK 的前端网页,观察WEB-API的响应

访问 Web 前端,打开浏览器开发者模式。可以看到,页面在初始化后自动与 WAF 后台进行交互,获取了jsapi.js 并进行静默计算得到 token。在发起 query 请求后,会自动在 cookie header 中带上 aws-waf-token。WAF 后台的 Bot control Rule 进行 token 校验成功后,流量被发送到 ALB。Echo-Server 会把发送的请求原样返回,可以看到请求中包含了 token 信息。

Image Removed

2、增加根据 Token 判断阻断的 WAF Rule

对于 Request 中不带有 token,或者 token 无效,我们希望 WAF 进行阻止的操作。需要做如下配置。

从流程上看,token 无效的请求,AWSManagedRuleBotControlRuleSet 会给这条 Request 加上 Label,用于表示 token 不存在或 token 无效。我们可以继续配置自定义规则,如果 request 包含特定 label,则说明请求来自非法客户端,进行阻断。

Awswaf:managed:token:absent,包含这个 label 说明 token 不存在

Awswaf:managed:token:rejected,包含这个 label 说明 token 无效

增加 Custom Rule,如果请求中包含上述 Label,则 Block

Image Removed

Image Removed

增加 Custom Rule,如果请求的 token 无效,则 Block。以下是等效配置的 JSON 描述:

Image Removed

现在有三条 Rule 作用在 WAF ACL 上:

Image Removed

3、观察不带 Token 的请求访问业务后端的情况

修改 Web 前端,使用 JS 原生 fetch(),不带 token 发送请求给业务后端。

Code Block
themeRDark
<html>
<head>
</head>
<body>
    <h1>Login Page</h1>
    <p>Click on the below button to login</p>
    <button onclick="login()">Login</button>

    <script>
        async function login(){
 }

    function userAction() {
		const container = document.getElementById('container');
		container.innerHTML = '';
           
		AwsWafIntegration.fetch(apiURL,{method: 'POST'}).then(response => {
			if ( response.status == 405) {
				showMyCaptcha();
			} else {
				response.json().then(myJson => { renderResponse(myJson) });
			}
		});
    }
</script>

<p>Hello WAF!</p>
<div id='container'></div>

</body>
</html>


WAF Client JavaScript API 提供了 AwsWafIntegration.fetch()方法,是原生 JS fetch()方法的 Wrapper。与原生 fetch()方法相比,内部逻辑封装了 token 的请求和计算,并在业务 http 请求中自动加上了 token, 调用方法的参数与原生 JS fetch()相同。

样例代码使用 WAF client API 向后端发起了一个 Post 请求。后端使用 AWS EC2 部署 Echo-Server 做为测试用的 Web 服务器,实现返回 http response,并通过 ALB 提供对外访问。ALB 被刚才配置的 WEB ACL 所保护。


2、WEB前端代码部署

上传样例代码到EC2的NGINX(  /usr/share/nginx/html )里面,呈现为客户端可访问的网页如下:

Code Block
themeRDark
    server {
        listen       80;
        #listen       [::]:80;
        #server_name  _;
        root         /usr/share/nginx/html;
        index index.html index.htm

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }


效果如下:

Image Added


4.4、步骤四:配置AWF

1、在WAF ACL关联ALB

Image Added


2、配置Token Domain列表

当 WAF 从 web 请求中侦测 token 时,默认只会接受与 ACL 所关联资源的 host domain。当请求是通过ALB 时,需要把custom host domain 配置到 Token domain 列表中。配置参考文档

Image Added


4.5、步骤五:场景测试

1、访问集成 SDK 的前端网页,观察WEB-API的响应

访问 Web 前端,打开浏览器开发者模式。可以看到,页面在初始化后自动与 WAF 后台进行交互,获取了jsapi.js 并进行静默计算得到 token。在发起 query 请求后,会自动在 cookie header 中带上 aws-waf-token。WAF 后台的 Bot control Rule 进行 token 校验成功后,流量被发送到 ALB。Echo-Server 会把发送的请求原样返回,可以看到请求中包含了 token 信息。

Image Added


请求头和报文

Code Block
themeRDark
POST
	http://api001.bosicloud.one/waf/query
状态
200
版本HTTP/1.1
传输485 字节(大小 98 字节)
Referrer 策略strict-origin-when-cross-origin
DNS 解析系统


POST /waf/query HTTP/1.1
Host: api001.bosicloud.one
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://web001.bosicloud.one/
Origin: http://web001.bosicloud.one
Connection: keep-alive
Priority: u=4
Content-Length: 0



响应头和报文

Code Block
HTTP/1.1 200 
Date: Thu, 13 Jun 2024 04:38:54 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://web001.bosicloud.one
Access-Control-Expose-Headers: X-Sms-Portal-Identity-Token
Access-Control-Allow-Credentials: true



{"msg":"success","code":0,"data":{"waf-query":"ok.","database":"ok.","redis":"ok.","status":"ok"}}




2、增加根据 Token 判断阻断的 WAF Rule

对于 Request 中不带有 token,或者 token 无效,我们希望 WAF 进行阻止的操作。需要做如下配置。

从流程上看,token 无效的请求,AWSManagedRuleBotControlRuleSet 会给这条 Request 加上 Label,用于表示 token 不存在或 token 无效。我们可以继续配置自定义规则,如果 request 包含特定 label,则说明请求来自非法客户端,进行阻断。

Awswaf:managed:token:absent,包含这个 label 说明 token 不存在

Awswaf:managed:token:rejected,包含这个 label 说明 token 无效

增加 Custom Rule,如果请求中包含上述 Label,则 Block


Image Added



Image Added


增加 Custom Rule,如果请求的 token 无效,则 Block。以下是等效配置的 JSON 描述:

Image Added


现在有三条 Rule 作用在 WAF ACL 上:

Image Added



3、观察不带 Token 的请求访问业务后端的情况


修改 Web 前端,使用 JS 原生 fetch(),不带 token 发送请求给业务后端。

Code Block
themeRDark
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Waf Captcha Test</title>
	<script type="text/javascript" src="https://73f53964XXX.ap-southeast-1.captcha-sdk.awswaf.com/73f53964XXXX/jsapi.js" defer></script>
</head>

<body>

<h1>Login Page</h1>

<p>Click on the below button to login</p>

<button onclick="userAction()">Login</button>

	
<script type="text/javascript">
	const apiURL = 'http://api001.bosicloud.one/waf/query';

    function showMyCaptcha() {
        const container = document.getElementById('container');
        AwsWafCaptcha.renderCaptcha(container, {
          apiKey: 'XXXXIIjdUYC7iqJbIcvhB5W21s/w9s3oAGcPai9tKFpadOUctVCXTZ0KndUbGATzSVqLx7s5dzl4MKwudqYWIEeyv0gnYZuSPchyf1mgZAXjRveATBmosCj2h3LEC2jAsagSWpzQGofjBvhFlC8CMnSmapPY8kekeIABcCyycj4rGUPVIX/iRAlGyZEFat68AfMJmsvoxRYiSIQQt1cJZnTNFlg/Uam3fQW9hFy/n6HJnO3nxs+kFwjotKnzMbHGOJXpbZlakYivF6t6mFoEea5PftXxszvDEdjJ6sUZI4aQbrJTfIcRF/9cM2L2WjNs0sVCj9fqu1lI75k2txelIrwoHOBxgJlSo8P23e5CShd1fBkYJgGdj8BobiIoMEqWgtIUN8s54EcaRzGUAZqinqsEONpBn8SBViBpl5I+RuiiEYsRBXpfHUzb5mbo/lzgO5YRCezY+B2LFAHmLzy6xeq390ig6xKmPRNXItxTDIudPELhIVO8rJ5vrYm+yf8wV1ppyJXuNP9pq9ifS2+jFfCt5kCNrjunTF0Hzbt08qHgPE1OZb9c2dSyXK8pvDGyaIbjROLgcCcJ7mRKqk2BvzSTCkY34SC98upXGUkMn1o36aOrbZoM15GcBGKPnQ0E0PmQrnfGGaIDJFZJRH8Hv/Q2s/o1GrluRmGEN39eeGXXXXuyYEs=_0_1',
            onSuccess: successFunction,
            let user = {
onError: errorFunction,
        });
    }

    function name: 'username',successFunction() {
      const container = document.getElementById('container');
      container.innerHTML surname:= 'surname';
           };
   AwsWafIntegration.fetch(apiURL, {}).then(response => {
        const responseresponse.json().then(myJson => await{ fetch('https://yourdomain.com/waf/query',{renderResponse(myJson) });
      });
    }

     method: 'POST',
function errorFunction(error) {
       console.log(error);
    }

     headers:function renderResponse(json) {
        if (json) {
           'Content-Type': 'application/json'
        container.innerHTML = "Result: The request resulted is Success.";
        }, else {
            container.innerHTML = "Result: body: JSON.stringify(user)
   The request resulted is Error.";
        });
    }

    function   userAction() {
		const responseTextcontainer = await responsedocument.textgetElementById('container');
		container.innerHTML = '';
           document.getElementById("display").innerText = responseText
           console.log(responseText)
    
		AwsWafIntegration.fetch(apiURL,{method: 'POST'}).then(response => {
			if ( response.status == 405) {
				showMyCaptcha();
			} else {
				response.json().then(myJson => { renderResponse(myJson) });
			}
		});
    }
   </script>

<p>Hello WAF!</p>
<div id='displaycontainer'></div>

</body>
</html>


通过 Chrome 浏览器开发者模式可以看到,由于请求不带 token,请求被 WAF 所拒绝。

Image RemovedImage Added