-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add Security Checks Log #6973
Add Security Checks Log #6973
Conversation
Codecov Report
@@ Coverage Diff @@
## master #6973 +/- ##
==========================================
- Coverage 94.00% 93.85% -0.16%
==========================================
Files 172 174 +2
Lines 12835 12992 +157
==========================================
+ Hits 12066 12194 +128
- Misses 769 798 +29
Continue to review full report at Codecov.
|
I think this is a great idea. If we end up adding code snippets for some of the security features in the docs, then it could be helpful to provide links to them. For checking the database port, are you pulling these from the URI or using the default Mongo (should probably check Postgres also)? Update: I’m looking from my phone, but I skimmed the code and it looks like you may have covered much of what I mentioned. My original comments was based on the output above, but it looks like the code may output more details? |
@cbaker6 I've added a few options that I could think of that would need to be checked for - and yeah this is functional. Just the advice on what it outputs will need to be adjusted, and I'm hoping that it'll evolve over time, and the function can be implemented into Parse Dashboard, with hopefully some click-through links to the relevant sections (e.g the schema warnings take you to the schema for that class). As you mentioned, the code currently is intended to get the current databaseURI, and then removes any username:password combo, and attempts to connect. Maybe we could also do some validation around password strength for DB strings and masterKeys. I'm honestly not sure of the security issues with postgres as I've always used Mongo. If you have the capacity, would you be willing to add it to the security checks? |
It looks like the checks would be on by default and be switched off using the optional parameter. This sounds like a good idea in the sense that Parse Server gives proactive security guidance. However, we want to make sure that we don't make deployments actually more vulnerable by disclosing vulnerabilities in the logs without some developers being aware of it. We also want to make sure these vulnerabilities cannot be easily revealed through the PR, which requires some feature maturity. So I am not sure we should introduce that immediately. I suggest to start by introducing the checks as disabled by default with a warning in the logs, if checks are not enabled. Later on, after we got some real-world feedback and potentially fixed some flaws, we could enable the check by default, with a highlighted warning in the change log. Therefore I would rename the option to This is a great PR, one of many in the past days by @dblythy. If we had an award "PR machine of the month", it would surely be yours 😉 |
I agree with all the points made @mtrezza. Maybe for an introduction, disabled by default, and then the function I am honored Manuel, as I've said before, Parse really helped me when I was getting started and all my production servers are better off thanks to the great work of this community. I am in debt to you all, and it's good to be able to give back a little bit! |
Yes, sounds like a good strategy. Disable Log output of security warnings sounds like bad practice to me, so I think we should never enable log output by default. However, there may be users who do not use parse dashboard, so they could temporarily enable the output in the logs. So we'd have at least 2 security parameters and the option could look like this:
As a side note, to clearly separate the terminology from issues that need to be fixed in source code rather than an unsafe configuration, we probably should not use the terms "vulnerability" or "issue" in relation to the security checks in the docs or source code. |
I've been attempting to get any JS PR's I'm tied to merged in hopes to not have to look at JS for awhile and focus on the Parse-Swift SDK. With that being said, I've made it a point to not let anything parse/postgres related slip behind mongo any further (and have attempted to catch it up) as I use Postgres instead of mongo. If no one else can add the Postgres parts, I can look. The makeup of the URI is similar to mongo (except for The usage of the parser occurs here: parse-server/src/Adapters/Storage/Postgres/PostgresClient.js Lines 7 to 26 in 7f3ea3f
|
I like the suggestions. I've updated the PR, and I'll try work on postgres shortly. As a side note, it feels bit clunky in my view to recommend a fileTrigger for users that never intend to have any files uploaded to their servers. Could we have a How do we feel about maybe having a |
I think it would be good but I'd do that on a separate PR. |
If I understand the suggestion correctly, it is related to this. My impression from the discussion there is that Parse Server should apply the secure ACL by default for these classes, which can be changed manually by the dev, but depending on the security impact of that change, Parse Server would then log an "unsafe configuration warning", thanks to this PR. |
I have pushed a new commit with the following changes: /GET endpoint for /advisoryChecks. This will return all the required data for (someone who is good with react, not me 😔) the creation of an Advisory panel in the dashboard. Otherwise, you can run the server with |
|
I was conscious of adding the word "security" to the code, hence why I used advisory. I misunderstood what you were saying about being sensitive regarding using the word "vulnerability". I'll change it back. |
Apologies for my previous comment being unclear, what I meant was that the terms |
No stress @mtrezza it was my misunderstanding. |
I only just realised you edited this comment Test case added. Regarding your second point - should we perhaps disable the security checks by default? I'm concerned that configurations with an exposed masterKey will potentially become more exposed (or, is this the least of their problems if their masterKey is exposed). |
Yes, as discussed
I don't think Parse Server can become more exposed than with the master key, aside from a (undiscovered) security vulnerability that exposes Parse Server internals or the underlying infrastructure. Do you have an example? |
Done!
No, I don't think so either. |
Related aspects to test for security: https://github.com/netreconlab/parse-hipaa |
@dblythy I may just pick up this PR and finish it if there's not too much left, if that's ok with you. Let me know if you have any thoughts to incorporate, or any obstacles you think should be addressed, that are not already mentioned here. |
@mtrezza you're welcome to crack in. I've been a bit busy on my end so I haven't been able to finish it off. I was looking at evolving it so that new features can be tested with something like your example.
|
@mtrezza did you manage to pick this up? If not, all good. I'm looking to keep working on it this week. |
As discussed @mtrezza I have introduced a helper class 'SecurityCheck'. The idea is that adding a new security check can happen anywhere, without needing to import any files. Here's how to use it: new Parse.SecurityCheck({
group: Parse.SecurityCheck.Category.ServerConfiguration,
title: 'Client class creation allowed',
warning: 'Clients are currently allowed to create new classes. This allows an attacker to create new classes without restriction and potentially flood the database. Change the Parse Server configuration to allowClientClassCreation: false.',
success: `Client class creation is turned off`,
check() {
return !options.allowClientClassCreation;
},
}); Returning Alternatively: const check = new Parse.SecurityCheck({
group: Parse.SecurityCheck.Category.ServerConfiguration,
title: 'Client class creation allowed',
warning: 'Clients are currently allowed to create new classes. This allows an attacker to create new classes without restriction and potentially flood the database. Change the Parse Server configuration to allowClientClassCreation: false.',
success: `Client class creation is turned off`
});
if (condition) {
check.setFailed();
} Also sets the check to failed. Let me know your thoughts on the way I've coded it thus far. Still need to work on DB error stuff, and increase coverage. |
Well, done! I think you got all the components there, I only suggest to change the structure, rearrange the parts if you will.
I see that such checks have been added to the MongoDB adapter. I would opine against that because:
So ideally, we want to keep the security checks centralized in a single file. Other thoughts:
To simplify the structure, I suggest to create a directory
|
Thank you for the feedback. Most of your questions can be answered by the fact that I'm pretty new to Javascript class syntax / OOP and not overly sure what i'm doing 🤨 .
Thanks for your suggestions. The reason why I had them stored was thinking that for the dashboard; where the security checks will be visible after the cloud route is called. Do you have any suggestions as to how I can do this without storing them? |
I imagine the dashboard having a page that executes SecurityChecks on demand and displays the results. Then there is an update button that executes the checks again and displays the updated results. The checks are executed in REST fashion. There is no need to cache them in Parse Server. The only purpose I can think of to store them would be a historic log, but that also would not happen in memory but in the database. I don't think such a historic view should be in scope here. In memory storing in Parse Server is also useless when you think of an environment with multiple instances, where only one instance has these in memory. |
I don't really understand the difference between what I have now, and your example, e.g:
The securityCheckStore adds the securityChecks to an array, where they are then run using How else should I do this? Isn't this the same as securityChecks.js push to an array, and then on the REST call run the checks? |
return Promise.resolve(); | ||
}) | ||
.then(() => { | ||
if ((options.securityChecks || {}).enableLogOutput) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should never be undefined, instead set a default value in option definitions.
Your |
So it would be better to have:
|
return Promise.resolve(); | ||
}) | ||
.then(() => { | ||
if ((options.securityChecks || {}).enableLogOutput) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
for (const check of data) { | ||
const { title, warning, error, result, success } = check; | ||
if (result === 'success') { | ||
logger.warn(`✅ ${success}\n`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this logic should go into the security checks files, not into the server file.
I finally found some time to look into this branch in detail:
I think this needs a major rewrite. Coordinating the necessary changes takes probably more time than just writing it from scratch. I hope to find the time soon to write this from scratch in a new branch. I'll post an update here when the basic structure is done and then maybe we can discuss together which tests to add. |
Ok, I think that’s the best way to go, if you have the willingness and capacity to implement this feature - rather than going back and forth attempting to reach your vision. I look forward to seeing your version. Thanks |
Thanks @dblythy, you did a good job already in bringing this ahead. If it's ok with you and if it turns out to be faster, I may just do the changes directly in your branch, so maybe keep it for a while. |
Thanks Manuel, it was fun to try to learn OOP and I look forward to seeing your implementation, so I can learn how it should look like. You’re welcome to use any code / branch of mine for the benefit of the community, please don’t hesitate if it saves you time :) |
@dblythy I just wanted to give you a 👍 for your work and graciousness on this. It is a great concept and will definitely be a solid contribution. I am really pleased that you clearly haven't taken offense, but instead recognized that this will be a great learning opportunity. In the end, the community will have a useful new feature and you will have seen an alternative approach that is beneficial for a project of this size and scope. |
@MobileVet thanks for the lovely thoughts - it’s no big deal though. At the end of the day we all want Parse Server to evolve, and whether that’s my code in the final version or not, it ultimately doesn’t really matter. :) |
It was clearly just meant to be a pragmatic suggestion. @dblythy made a great contribution with this PR and has put a lot of effort into this. Without his initiative we would probably still be talking about the idea. This feature has been a community effort all along, from the first idea by $davimacedo to the initiative to create this PR by $dblythy and all the feedback from others that went into it. I will pick this up for refactoring now and we can go from there to decide which tests to add. |
Hello all,
I've worked on implementing a log that picks up schema, allowClientClassCreation, beforeFileSave, beforeConnect, mongoDB auth issues, and anything else I could think of. This isn't intended to pen-test a Parse Server, but just give developers some easy to follow pointers to make their backends safer.
It currently runs on creation of ParseServer, and returns a nice little payload that can hopefully easily be rendered on the dashboard. Can be turned off with
disableSecurityChecks:true
.This PR is not ready for merge just yet - I was interested in your thoughts and suggestions, also suggestions around suggested CLPs for internal classes. I also need to write test cases.
This code also makes a few tests break with "open connections" - I was also wondering if there were any suggestions around that.
Here's what the current version outputs:
Reference to discussion in community forum.