Skip to content
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

Java: Add query to detect Apache Struts enabled Devmode #3945

Merged
merged 3 commits into from
Mar 2, 2021

Conversation

porcupineyhairs
Copy link
Contributor

This query detects cases where the development mode is enabled for a struts configuration. I can't find a CVE per se but, at present, Github's fuzzy search returns more than 44000 results. Some of them look like they are classroom projects, so they may be ineligible for a CVE. But we should be flagging them anyways as setting the development on in a production system is a very bad practice and can often lead to remote code execution. So these should be fixed anyways.

@porcupineyhairs porcupineyhairs requested a review from a team as a code owner July 12, 2020 18:39
Copy link
Contributor

@Marcono1234 Marcono1234 left a comment

Choose a reason for hiding this comment

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

Maybe it would be good to include "Apache Struts" in some way in the file name devMode.qhelp (and similar) since this query only applies to that?

@aibaars aibaars added the Java label Jul 13, 2020
@luchua-bc
Copy link
Contributor

This is an interesting area. As all development frameworks and application servers offer a dev or debug mode, is it possible for the query to detect production deployment only to reduce false positives? Thanks.

@porcupineyhairs
Copy link
Contributor Author

Hi @luchua-bc,

Yes, some of the frameworks offer a flag to turn developer/debug mode on. As you can see, I haven't adddressed @Marcono1234's comments on this PR. I am adding support for some other frameworks like Vaadin too here. Let me know if you have a particular framework in mind. I will include that one too.

is it possible for the query to detect production deployment only to reduce false positives

IMO, development mode should only be turned on when you are developing the code. No decent project actually allows you to knowingly push bad code into master. It is expected of the developer to clean the code for any debug symbols/bugs before pushing the changes. So, prod or no prod, if debug mode is turned on in a public repo, it's something which codeql should alert on.

As for cases where debug mode is enabled in test files, codeql, if I remember correctly, would by default ignore all test files while running the query. So, I don't have to skip any test files in my analysis as such.

@porcupineyhairs
Copy link
Contributor Author

Also, please do note that errors for this sorts have actually seeped into actual codebases multiple times. The most common one being the Flask Werkzeug debugger RCE.

A similar bug is possible for Apache Struts, you may see the exploitation steps here. Also, this presentation looks like it is about this very issue. However, the presentation is not in a language I understand so I can't say for sure.

@adityasharad adityasharad changed the base branch from master to main August 14, 2020 18:33
Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

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

I wouldn't necessarily worry about the initial PR covering many different frameworks. You might want to look at excluding common false-positives though -- for example, are there common signs that a web.xml file is an example that isn't enabled by default, such as its filename or directory?

Are you intending a bounty application for this? Either way, let me know when you consider it ready to evaluate.

@porcupineyhairs
Copy link
Contributor Author

@smowton @Marcono1234 I have included the changes you proposed and included a small heuristic to check for a bad path.

Also, @smowton I am opening the GHSL issue for htis one now.

Copy link
Contributor

@Marcono1234 Marcono1234 left a comment

Choose a reason for hiding this comment

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

Thanks! When there are already review comments, could you please refrain from force-pushing? It makes it difficult (in GitHub) to see the differences. If the commit history of the pull request becomes too long the commits can be squashed when merging, if necessary.

I have added some more review comments, hopefully they are helpful. Note that I am not a member of this project so these comments are not mandatory (unless the maintainers agree with the them).

Copy link
Contributor Author

@porcupineyhairs porcupineyhairs left a comment

Choose a reason for hiding this comment

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

include suggestions from review
--- EDIT ---
Please ignore this comment I posted it by mistake.

@porcupineyhairs
Copy link
Contributor Author

@smowton The tests for this one would fail as I mark all files with test in their file path as FP's. The output included here is for when you invert the isBadPath filter.

@smowton smowton changed the title JAVA : Add query to detect Apache Structs enabled Devmode Java: Add query to detect Apache Structs enabled Devmode Nov 10, 2020
@pwntester
Copy link
Contributor

Also, please do note that errors for this sorts have actually seeped into actual codebases multiple times. The most common one being the Flask Werkzeug debugger RCE.

A similar bug is possible for Apache Struts, you may see the exploitation steps here. Also, this presentation looks like it is about this very issue. However, the presentation is not in a language I understand so I can't say for sure.

or in my 6 years old post :)
https://www.pwntester.com/blog/2014/01/21/struts-2-devmode-an-ognl-backdoor/

@porcupineyhairs
Copy link
Contributor Author

While this is pending for review, I am merging the latest main here.

@smowton
Copy link
Contributor

smowton commented Dec 21, 2020

Apologies, I hadn't realised this one was back in my court. Marked to review after the Christmas break.

Also, please rebase rather than merge, it makes the resulting history simpler

@porcupineyhairs
Copy link
Contributor Author

@smowton No worries. Happy holidays'.

I plan on working on my PR's during this time though so you may have a lot of spam headed your way. Apologies in advance.

@smowton
Copy link
Contributor

smowton commented Dec 21, 2020

/me braces

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

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

Please also rebase this PR so we're not committing merges out of main.

import experimental.semmle.code.xml.StrutsXML

bindingset[path]
predicate isBadPath(string path) { path.regexpMatch("(?i).*(demo|test|example).*") }
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
predicate isBadPath(string path) { path.regexpMatch("(?i).*(demo|test|example).*") }
predicate isLikelyDemoProject(string path) { path.regexpMatch("(?i).*(demo|test|example).*") }

@smowton
Copy link
Contributor

smowton commented Jan 4, 2021

@porcupineyhairs this currently produces zero results. Could you re-check whether you're able to get any results against some of the projects you turned up using fuzzy search?

@porcupineyhairs
Copy link
Contributor Author

@smowton The query fails to detect any bugs as the XML extractor does not parse files located in theresources directory. As all struts.xml files are usually stored in that directory, none of them are actually included in the final CodeQL database rendering the run useless.

Is the Java-XML extractor source public? I can't seem to find it.

@smowton
Copy link
Contributor

smowton commented Jan 5, 2021

No, they're still in the private repo. I've asked around about this, will get back to you shortly.

@smowton
Copy link
Contributor

smowton commented Jan 5, 2021

Looks like you can add --xml-indexing-mode all to the command in $CODEQL_HOME/codeql/java/tools/autobuild.sh for a quick hack -- will let you know if I find a better way to do that!

@smowton
Copy link
Contributor

smowton commented Jan 5, 2021

Better alternative, set environment variable LGTM_INDEX_XML_MODE=smart, which as you can see in https://github.com/github/semmle-code/blob/main/language-packs/java/tools/pre-finalize.sh selects by the top-level tag name including struts. If for any reason that doesn't work you could also try the value LGTM_INDEX_XML_MODE=all.

@smowton smowton changed the title Java: Add query to detect Apache Structs enabled Devmode Java: Add query to detect Apache Struts enabled Devmode Jan 5, 2021
@intrigus-lgtm
Copy link
Contributor

Better alternative, set environment variable LGTM_INDEX_XML_MODE=smart, which as you can see in https://github.com/github/semmle-code/blob/main/language-packs/java/tools/pre-finalize.sh selects by the top-level tag name including struts. If for any reason that doesn't work you could also try the value LGTM_INDEX_XML_MODE=all.

https://github.com/github/semmle-code/blob/main/language-packs/java/tools/pre-finalize.sh is not public :)

@smowton
Copy link
Contributor

smowton commented Jan 5, 2021

Hah, whoops. In any case the environment variable settings can be tried from the command-line, and you should be able to see the script distributed as $CODEQL_HOME/codeql/java/tools/pre-finalize.sh.

@porcupineyhairs
Copy link
Contributor Author

@smowton exporting LGTM_INDEX_XML_MODE=all or LGTM_INDEX_XML_MODE=smart works well for me. I can confirm the fuzzy search results are now being detected.

@smowton
Copy link
Contributor

smowton commented Jan 12, 2021

We're going to add struts.xml to our routine XML import filter, so that we can test this against a broad swathe of projects. We should be in a position to do that in roughly 2 weeks. Prod me if you don't hear anything by then.

@smowton
Copy link
Contributor

smowton commented Jan 27, 2021

Looks like the change to routinely import struts files missed this merge window, so I'll try this again in 2 weeks.

@smowton
Copy link
Contributor

smowton commented Feb 16, 2021

This is now producing results on lgtm.com

This query detects cases where the development mode is enabled for a
struts configuration. I can't find a CVE per se but, at present, [Github's fuzzy search](https://github.com/search?q=%3Cconstant+name%3D%22struts.devMode%22+value%3D%22true%22+%2F%3E+language%3Axml&type=Code) returns more
than 44000 results. Some of them look like they are classroom projects,
so they may be ineligible for a CVE. But we should be flagging them
anyways as setting the development on in a production system is a very
bad practice and can often lead to remote code execution.
So these should be fixed anyways.
@porcupineyhairs
Copy link
Contributor Author

I have rebased it to the latest main while this is pending merge.

@aschackmull
Copy link
Contributor

StrutsXML.qll needs autoformatting

[ERROR] Input file ql/java/ql/src/experimental/semmle/code/xml/StrutsXML.qll is not correctly formatted

@porcupineyhairs
Copy link
Contributor Author

@aschackmull Changes done!

mt3ne
mt3ne previously approved these changes Mar 1, 2021
@aschackmull
Copy link
Contributor

Looks like the qltest is failing.

[3/8]  [18/42] ql/java/ql/test/experimental/query-tests/security/CWE-489/devMode.qlref: FAILED (compilation: 1.9s, execution: 42ms, total: 2s)
Expected results:
| StrutsBad.xml:8:5:8:52 | constant | Enabling development mode in production environments is dangerous |

Actual results:

Diff:
--- expected
+++ actual
@@ -1,1 +1,1 @@
-| StrutsBad.xml:8:5:8:52 | constant | Enabling development mode in production environments is dangerous |
+

@github github deleted a comment from mt3ne Mar 2, 2021
@porcupineyhairs
Copy link
Contributor Author

@aschackmull The tests were failing due to the isLikelyDemoProject check applied on all results. Since that check blocks all results which have *test* in their relative file paths, results in ql test directory are excluded as they contain query-tests in their relative path.

To fix this, I have removed the tests in question from this PR. I don't know if there is another way possible which does not involve duplicating the entire query.

@aschackmull aschackmull merged commit 0eb2c06 into github:main Mar 2, 2021
@porcupineyhairs porcupineyhairs deleted the structsDevMode branch March 2, 2021 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants