I'm using "RegularExpressionProtection" policy to prevent Script and SQL Injection. When implementing SQL protection, I was successful, but Script protection was not.
I'm using the following code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RegularExpressionProtection async="false" continueOnError="false" enabled="true" name="Regex-ScriptInjection">
<DisplayName>Regex-ScriptInjection</DisplayName>
<Properties/>
<Source>request</Source>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<URIPath>
<Pattern><\s*script\b[^>]*>[^<]+<\s*/\s*script\s*></Pattern>
</URIPath>
<QueryParam name="query">
<Pattern><\s*script\b[^>]*>[^<]+<\s*/\s*script\s*></Pattern>
</QueryParam>
<Variable name="request.uri">
<Pattern><\s*script\b[^>]*>[^<]+<\s*/\s*script\s*></Pattern>
</Variable>
</RegularExpressionProtection>
I'm simulating an injection:
https://host/path/path?page<script>alert(1)</script>&/
The request is accepted normally... (200 ok)
I also changed the default documentation regex, still to no avail:
<Pattern><[\s]*(?i)[a-zA-Z\s]+\b[^>]*>[^<]+<[\s]*/\s*[a-zA-Z\s]+[\s]*></Pattern>
the regex is correct (validated here: https://regex101.com/). But I'm not able to block the request.
What could I be doing wrong?
Solved! Go to Solution.
The RegularExpressionProtection policy checks URIPath, QueryParams and other variables.
The URIPath and the QueryParam elements in your policy will not scan the <script> text.
The request.uri variable is what you want to scan, for your particular case. BUT, it's encoded. So you'd need to decode it before scanning. I did this with a JS policy:
<Javascript name='JS-Decode-URI'>
<Properties>
<Property name='output-var'>decoded</Property>
<Property name='input-var'>request.uri</Property>
</Properties>
<Source>
var s = context.getVariable(properties['input-var']);
context.setVariable(properties['output-var'], decodeURIComponent(s));
</Source>
</Javascript>
And then used this RegularExpressionProtection policy
<RegularExpressionProtection name="REP-3">
<Source>request</Source>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<Variable name="decoded">
<Pattern><\s*script\b[^>]*>[^<]+<\s*/\s*script\s*></Pattern>
</Variable>
</RegularExpressionProtection>
And when I send in this request
curl -i 'https://MYORG-MYENV.apigee.net/regex-protect-uri/t3?page<script>alert(1)</script>&'
I get this fault:
{
"fault": {
"faultstring": "Regular Expression Threat Detected in REP-3: regex: <\s*script\b[^>]*>[^<]+<\s*/\s*script\s*> input: /regex-protect-uri/t3?page<script>alert(1)</script>",
"detail": {
"errorcode": "steps.regexprotection.ThreatDetected"
}
}
}
The RegularExpressionProtection policy checks URIPath, QueryParams and other variables.
The URIPath and the QueryParam elements in your policy will not scan the <script> text.
The request.uri variable is what you want to scan, for your particular case. BUT, it's encoded. So you'd need to decode it before scanning. I did this with a JS policy:
<Javascript name='JS-Decode-URI'>
<Properties>
<Property name='output-var'>decoded</Property>
<Property name='input-var'>request.uri</Property>
</Properties>
<Source>
var s = context.getVariable(properties['input-var']);
context.setVariable(properties['output-var'], decodeURIComponent(s));
</Source>
</Javascript>
And then used this RegularExpressionProtection policy
<RegularExpressionProtection name="REP-3">
<Source>request</Source>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<Variable name="decoded">
<Pattern><\s*script\b[^>]*>[^<]+<\s*/\s*script\s*></Pattern>
</Variable>
</RegularExpressionProtection>
And when I send in this request
curl -i 'https://MYORG-MYENV.apigee.net/regex-protect-uri/t3?page<script>alert(1)</script>&'
I get this fault:
{
"fault": {
"faultstring": "Regular Expression Threat Detected in REP-3: regex: <\s*script\b[^>]*>[^<]+<\s*/\s*script\s*> input: /regex-protect-uri/t3?page<script>alert(1)</script>",
"detail": {
"errorcode": "steps.regexprotection.ThreatDetected"
}
}
}