How to give correct file ownerships and permissions to secure your app server
Linux is such a powerful Operating System and the permissions it provides are powerful and simple and yet most widely misunderstood.
I have gone through so many forums and one common observation was there is lack of understanding on how permissions work.
Most people give standard answers like put 644 or some ignorant ones even suggest 777, not knowing the underlying architecture of the system at all.
I thought it is time to put a blog that clearly outlines what are these permissions and how they really work behind the scenes.
There are many who know the underlying principles - i invite all of them to share their feedback to help expand this blog and serve newcomers even better.
This blog is not about how to set permissions or how to improve security. How part has been covered by many bloggers, hence we will not be discussing any commands. I am only going to focus on What permissions to give and Why.
Let's start
Most common scenario is there is a website or an application on a hosted linux server.
And most common question is, what file permissions to give.
Most of these systems will be served by a Web service like Apache. To keep discussion simple we will refer Apache quite often even though there are many web servers.
This is how permissions are decoded
0 - No permission
1 - Can Execute
2 - Can Write
4 - Can Read
If i want to give both read and write permission i will add 2 + 4 and 6 to that file.
7 means 1 + 2 + 4 and that translates to execute, write and read. 7 is the highest permission one can give.
Another aspect in connection with permissions is the file ownership without which our next discussion will be incomplete.
This is how file ownerships are decoded
There are total 3 levels of ownership
U - user - also known as the primary owner (the one who creates the file / dir automatically becomes the owner)
G - group - in linux system every user automatically has a group by the same username
O - other - any one who is not part of U or G, i simply describe this as rest of the world (they can be other users on the server too).
Each file or directory typically have all these 3 levels. Any permissions that we give is seen with respect to this ownership hierarchy.
I have gone through so many forums and one common observation was there is lack of understanding on how permissions work.
Most people give standard answers like put 644 or some ignorant ones even suggest 777, not knowing the underlying architecture of the system at all.
I thought it is time to put a blog that clearly outlines what are these permissions and how they really work behind the scenes.
There are many who know the underlying principles - i invite all of them to share their feedback to help expand this blog and serve newcomers even better.
This blog is not about how to set permissions or how to improve security. How part has been covered by many bloggers, hence we will not be discussing any commands. I am only going to focus on What permissions to give and Why.
Let's start
Most common scenario is there is a website or an application on a hosted linux server.
And most common question is, what file permissions to give.
Most of these systems will be served by a Web service like Apache. To keep discussion simple we will refer Apache quite often even though there are many web servers.
This is how permissions are decoded
0 - No permission
1 - Can Execute
2 - Can Write
4 - Can Read
If i want to give both read and write permission i will add 2 + 4 and 6 to that file.
7 means 1 + 2 + 4 and that translates to execute, write and read. 7 is the highest permission one can give.
Another aspect in connection with permissions is the file ownership without which our next discussion will be incomplete.
This is how file ownerships are decoded
There are total 3 levels of ownership
U - user - also known as the primary owner (the one who creates the file / dir automatically becomes the owner)
G - group - in linux system every user automatically has a group by the same username
O - other - any one who is not part of U or G, i simply describe this as rest of the world (they can be other users on the server too).
Each file or directory typically have all these 3 levels. Any permissions that we give is seen with respect to this ownership hierarchy.
The hierarchy is in this order UGO
In simple terms, if the file ownership is kalpesh:daemon, it means kalpesh is the primary user and daemon is the group user, and 3rd user - rest of them is automatically considered.
How does ownership and permissions link together
When we say 777 - it means 1st 7 is the permission granted for U (user), and 2nd 7 is granted to G (group) and 3rd 7 is granted to O (rest of the world).
A permission of 640 will mean - primary user has read and write permission, group user has read permission and world has no permission.
Is that all ? No : Deployment matters
Most times these permissions are taken literally and one of the most important aspect that is often ignored is how your application is deployed or in other words how is the server going to serve those files.
Permissions of the file on a server is seen in relation with the service that will serve those files. When we are connected to the server using terminal and are browsing a directory we are using file service. A user that has no access to your server but is browsing the website using a url via http or https protocol, it is typically using web-service, hence in the case of hosted applications you need to look at the permissions from the perspective of a webservice (eg apache)
Hence even if you assign 0 to the rest of world - it doesn't mean that file is safe
The above is valid depending on how the ownership have been been structured and what kind of deployment is used, and which service is serving those files.
In simple terms, if the file ownership is kalpesh:daemon, it means kalpesh is the primary user and daemon is the group user, and 3rd user - rest of them is automatically considered.
How does ownership and permissions link together
When we say 777 - it means 1st 7 is the permission granted for U (user), and 2nd 7 is granted to G (group) and 3rd 7 is granted to O (rest of the world).
A permission of 640 will mean - primary user has read and write permission, group user has read permission and world has no permission.
Is that all ? No : Deployment matters
Most times these permissions are taken literally and one of the most important aspect that is often ignored is how your application is deployed or in other words how is the server going to serve those files.
Permissions of the file on a server is seen in relation with the service that will serve those files. When we are connected to the server using terminal and are browsing a directory we are using file service. A user that has no access to your server but is browsing the website using a url via http or https protocol, it is typically using web-service, hence in the case of hosted applications you need to look at the permissions from the perspective of a webservice (eg apache)
Hence even if you assign 0 to the rest of world - it doesn't mean that file is safe
The above is valid depending on how the ownership have been been structured and what kind of deployment is used, and which service is serving those files.
More on this towards the end.
Before we get technical, let us define our needs
Before we get technical, let us define our needs
Scenario is hosted application that will be served via web service sitting behind http or https protocol
As the owner of the app i want ability to manage the files as and when needed, which means i can add, edit, delete files or directories of a particular parent directory.
A web service needs to read the files, and only some folders like tmp folder or a document folder where the web service need write permission (eg: during an upload activity or a report export activity)
World needs to be able to browse the site - they will be using some sort of http client to browse a particular page, this page will be served by apache over a http or https protocol
Note: It is worth remembering, that even if the world is browsing your site, it is apache that is serving and hence apache needs access - not the world!
This leads us to the following ownerships and permissions
1st part: Ownerships
Your primary user should be the one that is going to own the file
Your group user can belong to the web service user since it needs to serve the file
Which means file ownership will be kalpesh:daemon - where kalpesh is the primary user and owns the file and daemon (or any other user, eg: www-data) is the group user under which apache process is running.
2nd part: Permissions
In relation to ownership given above, following permissions will be most suitable
All directories that apache only needs to read will have following permission: 750
All directories that apache also need to write to (manage upload process) will have following permission: 770
All files that apache only needs to serve, will have following permission: 640
All files that apache also needs to write (eg: to save user configuration in a json file), will have following permission: 660
What we have done is given full permission to kalpesh, only read permission to apache group user for most files, and write permission to apache group user for some files / directory, and no access given to the world.
A web service needs to read the files, and only some folders like tmp folder or a document folder where the web service need write permission (eg: during an upload activity or a report export activity)
World needs to be able to browse the site - they will be using some sort of http client to browse a particular page, this page will be served by apache over a http or https protocol
Note: It is worth remembering, that even if the world is browsing your site, it is apache that is serving and hence apache needs access - not the world!
This leads us to the following ownerships and permissions
1st part: Ownerships
Your primary user should be the one that is going to own the file
Your group user can belong to the web service user since it needs to serve the file
Which means file ownership will be kalpesh:daemon - where kalpesh is the primary user and owns the file and daemon (or any other user, eg: www-data) is the group user under which apache process is running.
2nd part: Permissions
In relation to ownership given above, following permissions will be most suitable
All directories that apache only needs to read will have following permission: 750
All directories that apache also need to write to (manage upload process) will have following permission: 770
All files that apache only needs to serve, will have following permission: 640
All files that apache also needs to write (eg: to save user configuration in a json file), will have following permission: 660
What we have done is given full permission to kalpesh, only read permission to apache group user for most files, and write permission to apache group user for some files / directory, and no access given to the world.
Simply put, owners has full access, group has limited access and world has no access.
Since kalpesh has full permission it becomes easy for the file owner to manage the site.
Since apache group user (via daemon group) has read permission, it can read the file and serve it to the world via http or https protocol
No access to the world, doesn't mean the world cannot browse your site. Remember they need to browse the site via a browser via http(s) protocol, and not via file server.
So when the world is browsing the site, following sequence is happening:
1- Browser sends request via an http(s) protocol to a web service (eg apache)
2- Apache server locates the file based on configuration, and since it has read access, it will read the content of the file and pass it to the module that is responsible for serving / executing that particular extension.
3- Php module will execute all files with extension .php, or .Net module will execute .aspx (and many more) or any other module like perl, python, will execute the file from within apache process
4- The result of the execution will be written back as http(s) response.
5- Browser will interpret the response and present the content to the world.
And in this entire sequence, there was no need for the world to have any form of access to the end-file, it was the apache process that needed access and not the world.
How do i protect sensitive files that should never reach the world
I think so far so good, now only 1 thing left, if apache is serving the files it means it will serve all files and what it can execute via module will be returned back after execution, or it will be returned as it is if no modules were found.
Typical Eg of a file that is not executed by any module (php / .net / python etc) are the static files, these are delivered by apache to the requesting browser as it is.
What if some of the static file should never be served. eg: your configuration files that contains information about your database and connection strings with passwords or some other custom file that you have used as configuration but do not want world to see via browser.
As a thumb rule if i know the link to that file i can browse it via browser and if it contains important information it may be enough to hack into your system.
4- The result of the execution will be written back as http(s) response.
5- Browser will interpret the response and present the content to the world.
And in this entire sequence, there was no need for the world to have any form of access to the end-file, it was the apache process that needed access and not the world.
How do i protect sensitive files that should never reach the world
I think so far so good, now only 1 thing left, if apache is serving the files it means it will serve all files and what it can execute via module will be returned back after execution, or it will be returned as it is if no modules were found.
Typical Eg of a file that is not executed by any module (php / .net / python etc) are the static files, these are delivered by apache to the requesting browser as it is.
As a thumb rule if i know the link to that file i can browse it via browser and if it contains important information it may be enough to hack into your system.
If my config file is on the root and my app url is https://somedomain.com, and the hacker guesses it is a .net core app and runs this link in the browser: https://somedomain.com/appsettings.json
Apache will serve this file and many of the important settings related to the app will be revealed to the hacker.
This is where .htaccess file gets into the picture or in some case web.config (depending on your deployment) and these can be used for enhancing the security of the sensitive files.
Here you need to mention which file(s) shouldn't be served by the web service.
How to automate all this to ensure your app is not compromised because of silly mistakes
It is best to write a bash script that works for your application and add it to cron.
This is important since constantly your team will be updating some content on the site, either theme related changes or updating a module, or changing the configuration files.
So by their casual mistakes the sites security shouldn't get compromised. Hence it is best to automatically repair the sites permissions every 24 hours or so.
Re-visiting our example
I mentioned the following above: Even if you assign 0 to the world - it doesn't mean that file is safe
Good luck securing your systems !
So by their casual mistakes the sites security shouldn't get compromised. Hence it is best to automatically repair the sites permissions every 24 hours or so.
Re-visiting our example
I mentioned the following above: Even if you assign 0 to the world - it doesn't mean that file is safe
Under which scenario will that file be still unsafe?
It will be unsafe when your apache process user has been given incorrect write access by assigning it a 6 or 7, it means apache user can write into that file, and if your application is vulnerable to "Cross Site Scripting – XSS" attack, then the hacker can use this vulnerability to write content to that files. And once the file is written with malicious code, and when that same file gets executed in a normal browsing operation it will be used for injecting your site's directory with more malicious files and your entire server is then compromised.
Hence to provide maximum safety, be very careful while assigning write permission to your web service user. eg: it makes sense to write into a specific directory that your app can first clean before executing, however it doesn't make any sense to give write permission to any other executable files. Think about it, why should apache have any need to write into a .php file, .py file, a .ascx file, .dll file, these are typically compiled codes and giving them write permission will compromise your server.
App level security
The directories that are used for writing (the upload directory or user settings directory) should be cleaned by the app code to ensure that the files are safe from "injected code"
Hope this information helped.
Good luck securing your systems !
Thanks, excellent explanation.
ReplyDelete