Skip to content

feat: remediation for Python SSTI #4145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 5, 2025

Conversation

TheRubick
Copy link
Contributor

This commit include the following:

  • Add new rule to the generic attack category to block the Python SSTI payloads
  • Add Some test cases to check if the rule works fine or not

This commit include the following:

- Add new rule to the generic attack category to block the Python SSTI payloads
- Add Some test cases to check if the rule works fine or not
Copy link
Contributor

github-actions bot commented May 24, 2025

📊 Quantitative test results for language: eng, year: 2023, size: 10K, paranoia level: 1:
🚀 Quantitative testing did not detect new false positives

@dkegel-fastly
Copy link

Although the quantitative testing in CI didn't find any problems, I suspect that regexp is too loose, and may cause false positives in the real world. A bit of searching found this post:

Wow...\n\n{{{{{{{{{{{{Hugs}}}}}}}}}}}}} (if you want them)

which would trigger a false positive. There are surely other examples.

See for example commit 2ac26cc
which added support for a different flavor of SSTI; it went to the trouble of actually matching dangerous things between the brackets to avoid false positives.

You want tests for actual harmful requests, too, not just probes like {{ 7 * 7 }}.
And you probably want a test for the post I dredged up, demonstrating that a false positive is not triggered.

Note also that when one adds a regexp, one is expected to provide regex assembly source; the commit I linked to does this in file util/regexp-assemble/data/934100.data etc.

@dkegel-fastly
Copy link

#3780 is about bash; this is about SSTI. They may look similar because of the braces, but they're very different.

@Xhoenix Xhoenix added the release:new-detection In this PR we introduce a new detection label May 25, 2025
@franbuehler
Copy link
Contributor

franbuehler commented May 25, 2025

Thank you for providing this PR and also the associated issue. The PR already looks great, and there's even a test file.
The linting and the regression tests are failing. I think the payload in the test file {{ 7*7 }} should be url encoded. Then the regression tests are successful on my machine.

@dkegel-fastly
Copy link

dkegel-fastly commented May 25, 2025

It seems {{ }} is used by a large number of template languages, e.g.:

so you might want to either change the name of the rule to "Generic SSTI", or add keywords to make it specific to Flask and call it "Flask SSTI" (following the example set by a different SSTI rule in #2578 ).

Also, it's used in non-template language:

thus crs standard advice "disable any rule that causes false positives for your users" will apply to this rule.

@TheRubick
Copy link
Contributor Author

@franbuehler
Sure I will check your comments, very glad to have your reviews :)

@TheRubick
Copy link
Contributor Author

@dkegel-fastly
I will check your comments as well thanks :)

But regarding your claim that the double parentheses is used in a lot of things, what is the point that some users may pass such expression in a query parameter for example or for a cookie??

Even if there is a case and it is very rare, I think they can be bypassed by the folks whoever will face any issue for this rule, what do you think?

@dkegel-fastly
Copy link

dkegel-fastly commented May 25, 2025

I'm more worried about it happening in the body; that's where long user input goes.
And likely it'll go into a query parameter, since web apps don't tend to use bare bodies much these days.

@Xhoenix
Copy link
Member

Xhoenix commented May 26, 2025

This is already covered by rule 941380:

SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML:/* "@rx {{.*?}}" \

@Xhoenix
Copy link
Member

Xhoenix commented May 26, 2025

We need to update our documentation so that users stop reporting bypasses at PL1, when they're covered at higher PLs. Closing.

@Xhoenix Xhoenix closed this May 26, 2025
@franbuehler
Copy link
Contributor

franbuehler commented May 26, 2025

That's true. I didn't test for it.

curl -v -H "x-crs-paranoia-level: 2" -H "X-Format-Output: txt-matched-rules" 'sandbox.coreruleset.org/get?x=%7B%7B%207%2A7%20%7D%7D'
941380 PL2 AngularJS client side template injection detected
949110 PL1 Inbound Anomaly Score Exceeded (Total Score: 5)
980170 PL1 Anomaly Scores: (Inbound Scores: blocking=5, detection=5, per_pl=0-5-0-0, threshold=5) - (Outbound Scores: blocking=0, detection=0, per_pl=0-0-0-0, threshold=4) - (SQLI=0, XSS=5, RFI=0, LFI=0, RCE=0, PHPI=0, HTTP=0, SESS=0, COMBINED_SCORE=5)

However, case 2 is not covered yet:
/get?x={ { 7*7 } }"

curl -v -H "x-crs-paranoia-level: 2" -H "X-Format-Output: txt-matched-rules" 'sandbox.coreruleset.org/get?x=%7B%20%20%20%20%20%20%20%20%20%7B%207%2A7%20%7D%20%20%20%7D'

Do we want to extend the existing rule 941380 so that this case is covered as well?

@Xhoenix
Copy link
Member

Xhoenix commented May 26, 2025

Do we want to extend the existing rule 941380 so that this case is covered as well?

Yes, that'd make sense. Also, we need to update the comments to mention that the payload covers other template/non-template languages as mentioned by @dkegel-fastly.

UPDATE: I just tested with spaces, and the code is unable to evaluate due to incorrect syntax. The curly braces need to be close, atleast for Python, which I've tested.

@Xhoenix
Copy link
Member

Xhoenix commented May 26, 2025

I just checked, and we need to cover the the {% ... %} Python Jinja2 template statement syntax.

https://jinja.palletsprojects.com/en/stable/templates/#list-of-control-structures

 curl -H "x-format-output: txt-matched-rules" "https://sandbox.coreruleset.org/?test=%7B%25%20if%20True%20%25%7D%20yay%20%7B%25%20endif%20%25%7D" -H "x-crs-version: nightly" -H "x-crs-paranoia-level: 4"

@franbuehler
Copy link
Contributor

We could cover this with:
{[{%].*?[}%]}

So this would be enough when the curly braces need to be close.

@Xhoenix
Copy link
Member

Xhoenix commented May 26, 2025

Not sure how to implement this, rule 941380 is XSS related, although still a template injection vuln. What do you suggest, remove that rule, maintain this PR. and change the title to Template Injection, to make it generic.

@Xhoenix Xhoenix reopened this May 26, 2025
@TheRubick
Copy link
Contributor Author

TheRubick commented May 26, 2025

@Xhoenix Are you sure that the rule: 941380 could block the {{.*}} regex?? I have tested it multiple of times and I could still bypass the coreruleset.

@TheRubick
Copy link
Contributor Author

@franbuehler I see that this rule: 941380 doesn't make any kind of transformation, should we add the removeWhiteSpace for example? i.e. t:removeWhiteSpace instead of t:none

@franbuehler
Copy link
Contributor

Not sure how to implement this, rule 941380 is XSS related, although still a template injection vuln. What do you suggest, remove that rule, maintain this PR. and change the title to Template Injection, to make it generic.

@Xhoenix I'm not entirely sure, but I think we should move the rule to the right place. The downside is that some users may have written tuning rules to this rule 941180. Now the rule will be moved to a different ID, and the tuning rule will no longer apply. Maybe other opinions?

Are you sure that the rule: 941380 could block the {{.*}} regex?? I have tested it multiple of times and I could still bypass the coreruleset.

@TheRubick Yes, the regex of rule 941380 is almost the same: {{.*?}}. The only difference is the laziness.
You can test it with:
curl -v -H "x-crs-paranoia-level: 2" -H "X-Format-Output: txt-matched-rules" 'sandbox.coreruleset.org/get?x=%7B%7B%207%2A7%20%7D%7D'

I see that this rule: 941380 doesn't make any kind of transformation, should we add the removeWhiteSpace for example? i.e. t:removeWhiteSpace instead of t:none

@TheRubick Yes, this would also be the solution to match the second test case: { { 7*7 } }

@TheRubick
Copy link
Contributor Author

@franbuehler all options are available on the table :)
If you wanna schedule a meeting to put the boundaries and the main decisions for this PR, I am fine as well :)

- Add the {%%} and <%%> regex to the rule 934180
- Add more regression tests
- Removed some unnecessary comments
@TheRubick
Copy link
Contributor Author

TheRubick commented May 31, 2025

@franbuehler @Xhoenix
I have add multiple changes:

  • Add the {%%} and <%%> to our regex
  • Removed unnecessary comments
  • Added more regression tests.
    But my gut tells me that we no need the removeWhiteSpace filter as the payload will be useless. So should I remove this filter in addition to every associated regression tests related to the white space case?? i.e. remove the regressions test from id 5 to 8??

Also, can we be confirmed from removing the old rule from the XSS??

I have added the angle brackets plus percentage sign test case and regex as well as I have found this statement in the Jinja2 template official documents: An application developer can change the syntax configuration from {% foo %} to <% foo %>, or something similar, Reference: https://jinja.palletsprojects.com/en/stable/templates/

As well as I have found some SSTI payload can be exploited using this type of regex e.g. <%= File.open('/etc/passwd').read %>, Reference: https://github.com/payloadbox/ssti-payloads

@TheRubick
Copy link
Contributor Author

@franbuehler

@Xhoenix I'm not entirely sure, but I think we should move the rule to the right place. The downside is that some users may have written tuning rules to this rule 941180. Now the rule will be moved to a different ID, and the tuning rule will no longer apply. Maybe other opinions?

In my humble opinion, this fact should be concerned in every open source project :) I mean this may happen to someone who is using an open source library but didn't check the release notes. Does that make sense??

I see that we can remove the old rule and broadcast that we have changed to something else, folks/users should be synced to the latest change.

@TheRubick
Copy link
Contributor Author

@franbuehler I have added all the changes that we have agreed upon from the monthly meeting :)
If I have missed anything else or you have any other thoughts, just shout it out xD

@franbuehler
Copy link
Contributor

I will add a comment to the existing rule 941380 once this PR is ready.

@TheRubick
Copy link
Contributor Author

@franbuehler

I will add a comment to the existing rule 941380 once this PR is ready.

I have added a comment already, did you check it?
https://github.com/coreruleset/coreruleset/pull/4145/files#diff-b43639c57f48880d643410a3d423a4fa3daf0681be74978afc9b1e4214122c0bR361

@franbuehler
Copy link
Contributor

Linting fails because of trailing spaces in tests/regression/tests/REQUEST-934-APPLICATION-ATTACK-GENERIC/934180.yaml.

@fzipi
Copy link
Member

fzipi commented Jun 3, 2025

@TheRubick Can you fix the test's yaml?

@TheRubick
Copy link
Contributor Author

TheRubick commented Jun 3, 2025

@franbuehler @fzipi Done, waiting for your sweet lgtm :)
Sorry for late response as well but I was afk from my machine.

@franbuehler
Copy link
Contributor

Linting is still complaining about a trailing space.

@TheRubick
Copy link
Contributor Author

@franbuehler done
I have installed the yamllint in my ubuntu machine and I think it should be fine rn :)
Sorry for this confusion :)

Co-authored-by: Xhoenix <86168235+Xhoenix@users.noreply.github.com>
@franbuehler
Copy link
Contributor

@fzipi released 4.15.0 a few days ago. Now linting is complaining about a wrong ver tag.
Can you change the ver to the new version: ver:'OWASP_CRS/4.16.0-dev'.
Then it should be good.

I also commited @Xhoenix changes of the .* pattern.

@TheRubick
Copy link
Contributor Author

TheRubick commented Jun 4, 2025

Updated the action version, done :)

@fzipi fzipi changed the title feat: Remediation for Python SSTI feat: remediation for Python SSTI Jun 4, 2025
franbuehler and others added 3 commits June 4, 2025 11:40
Co-authored-by: Felipe Zipitría <3012076+fzipi@users.noreply.github.com>
Co-authored-by: Felipe Zipitría <3012076+fzipi@users.noreply.github.com>
@TheRubick
Copy link
Contributor Author

@fzipi I have added the new tag, hopefully so I have adjusted it appropriately :)

Copy link
Member

@fzipi fzipi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Xhoenix Xhoenix added this pull request to the merge queue Jun 5, 2025
Merged via the queue into coreruleset:main with commit d98c5dc Jun 5, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release:new-detection In this PR we introduce a new detection
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants