Nginx basic auth and number of authenticated locations - authentication

Im using basic auth in nginx, no issue there, but i would like to limit the number of distinct locations a user is authenticated,
The end goal is to prevent user sharing access data to website, since the website does real time "monitoring" of some data, i wan't that if the same user/pass combination is used from another ip, that or either both users stop getting data,
or one of them stops getting data.

I don't think that is a good idea, because a user may log in via pc and mobile phone at the same time and has two different ip addresses that way. Also http-auth isn't designed to do what you want it to. It would have to remember the ip-address and make it expire somehow, when the user leaves without logging out. Altogether would it be difficult to guess for how long the session is valid. Another problem is, that most users don't have static IPs and get disconnected by their providers every 24 hours. What happens if that occurs after a valid login?
The most popular method to deal with this kind of problems are session-cookies. These can be described as a one time password and you can use that for as long as you want or until it expires. SessionIDs are usually saved in some kind of database and making those sessions unique would not be a big deal and may therefor be what you want. Luckily the
ngx_http_auth_request_module would allow you to only implement this missing part and would bring you as close as you can get without developing your own nginx-module (see https://www.nginx.com/resources/wiki/modules/ for available modules).
On the other hand: Don't do that. Seriously. If you care for security, do not try to reinvent the wheel and use something, that has already proven. E.g. ngx_http_auth_jwt_module allows you the use of OpenID, which also sets you free from saving sensible user data on your server (because nobody wants to save passwords unless it is absolutely necessary).
Both of these methods require nginx-modules, which may not be installed on your server. If you don't have the permissions to build them, I would suggest to add that to your question, so that others can suggest solutions for non root servers.
If you want to keep it simpler you should also consider to generate download links each and every time and save ip-address and download link address in a database. Delete entries when a user downloads that file and you are done. For that to work you can use the
Content-Disposition: attachment; filename=FILENAME-HTTP-Header, so that your download.php doesn't save a file that called alike.
May be you can also find some kind of javascript to replace ngx_http_auth_jwt_module and use OpenID with http-auth. That can work, because it is possible to do the authentication with ajax as well.
Last but not least: If you still want to do http-auth, also use HTTPS, because your passwords won't be encrypted by this auth-method by default.

What you want to do is unusual so you will need to write a lot of the logic to handle the process.
Your code will need to store a User ID and IP Address pair for each loged in user and validate each attempted log in against this. As the previous answer pointed out, you will need to expire logins etc. Basically, you need to roll a session handler.
This is not impossible or particularly difficult but you need to write it yourself in one of the scripting languages available to Nginx which are either Perl, which is not recommended due to limited ecosystem in Nginx, or Lua, which is highly recommended due to the massive Nginx lua ecosystem (used by Cloudflare for instance).
You will need to compile in the 3rd party Nginx Lua Module and associated modules or just uninstall Nginx and use the Openresty Bundle which already has everything you will need included instead ... including Redis for storage if you need to scale up.
Here are some tools you can use as your building blocks
Openresty Session Library
Openresty Redis Session Library
Openresty Encrypted Session Module
Note that you can implement Openresty stuff directly in Nginx if you wish without having to run Openresty as it is just a convenient bundle of Nginx and useful module.

Related

Secret file in Boomla open-source website

If I make a site open source, how can I save some data that should not be accessible by everyone? For example, I'd like to store some secret keys for APIs, while making the site available for others to fork and view.
One solution would be to maintain a copy of the website which is open source, and keep the live site closed source, but it is a bit cumbersome to always update the open-source one. And dangerous too, I might accidentally leak some sensitive keys.
Not sure how you could make use of the API keys as currently there is no way to make HTTP requests from the Boomla server to the outside world. You could only use it in the client - but then it's not secret any more.
There is an experimental solution for this. You can create a branch named db-fj9h9wdw. You will be able to access it like you would access a DB (from any of the website's branches).
EDIT: I have created a demo: secret-keys.boomla.net

Can cgi scripts be downloaded by an attacker?

I have a rather simple question but could not find an answer on the internet so far:
Is there any way an attacker can download a CGI Script (Perl, Python, whatever) from a webpage?
Or in other words: Is it a security risk to have sensible information (e.g. access keys to another service) within a cgi script?
Thanks!
Is there any way an attacker can download a CGI Script (Perl, Python, whatever) from a webpage?
The design of web servers tries to prevent this, but the design of web applications should assume this. - i.e. It's not how it's supposed to work, but it's not at all uncommon. Whether or not it's possible depends on why you're asking the question.
There may be a way for a particular hacker to download a script from your webpage, if he had an attack vector that was worth their time to do so.
This answer to another question (though relating to PHP, principles are the same), explains in a good amount of detail some of the factors that can lead to an exploit.
Is it a security risk to have sensible information (e.g. access keys to another service) within a cgi script?
Yes. While there's always risk, and the acceptability of that risk depends on your application and specific tradeoffs, this particular scenario has two major flaws (if not more):
If anything went wrong with your server, or CGI handler, you could have a public facing text file
It's just so, so easy, just to not put the private key there.
Even if the private key only accessed a VM on a free tier which did nothing but return the weather in your local city, you should at least employ a model where private keys are not accessible by the web server user (i.e. www-data, etc). i.e. You could have your CGI handler simply pass the paramaters/arguments to another local service to parse and invoke the actions required.

Is it possible to find anything out about the computer/user calling your api? If so, how?

I've created an api using .net core 2 and C#. I'm wondering if there's anyway to find out information about the computer or user that called the api. This is an internally used api so ideally I'd get the Windows user of where the api call came from, but if there's anything I can find out (like an IP address) I'd like to know how. If this isn't possible at all, I'd like to know so I can stop looking for a solution.
No, it's not possible. The server knows only what the client chooses to tell it, typically via request headers. However, the client can also lie, or "spoof" these headers. So, while something like User-Agent may look like it might give you some info about at least the OS/browser, all of that could be completely fabricated.
Matters are even worse with an API, as clients are typically thin, and the actual programmer or whatever connecting to your API must make a conscious decision to provide you with some particular bit of information, which most won't. A web browser typically sends certain standard things without user intervention, but even then users can change or alter what is sent.

How can I obfuscate a static password in objective c?

I need to hide a password to connect with a server. The problem is that the password is given by the service providers, so it is static.
I already thought of using the keychain, but the problem is that even if I use this I need to hard code the password to insert it in the keychain somewhere in the code.
So, is there a way to hide a static password to be available for my app, avoiding to write it in my code?
I would think about setting up a middle layer server - kind of a proxy - between users of your app and the service provider. It will allow you to:
set different password for each user
optionally give users a chance to change a password
have more control over who uses the service and what data is transmitted
be more independent of your service provider (e.g. change it anytime)
It will require more effort but may be it is more advantageous in long run.
This is not a solvable problem, and has been discussed at length around SO. For one "hub" question that includes links to several others, see Secure https encryption for iPhone app to webpage.
Using obscurity is not a horrible thing. But keep it simple. XOR the value with some random key. Done. Putting more and more layers buy you nothing, and cost you complexity (which means time and bugs, which are the enemies of both profit and security). If someone puts a debugger on your code, they're just going to log all the data you send to the server, so all the hoops you jump through to hide how you compute the password won't matter, because eventually you have to send it to the server. So keep it simple to stop people from just using "strings" to pull it out, and recognize that you cannot stop a debugger.
The only way to secure the service-provider's key is to put that key on your server, and then proxy for the service after authenticating the user. If you put it in the code, then it is discoverable, period. If this were a solvable problem, there would be no unlicensed copies of software, no unlicensed copies of music, no jailbreaks for iPhones, etc etc etc. If Apple can't stop reverse engineering when controlling every piece of the system from the hardware to the OS, you're not going to fix it inside of an app.
What you should be thinking about is how to recover if and when the key is lost. How do you discover that it's happened? How do you expire that key and create a new one? If you're shipping the key in the code, you must assume that it eventually will be discovered, and you should have a plan for dealing with it.
As a side note, one technique I've used in the past is to download the key from our server on-demand rather than encoding it anywhere in the app. We use authenticated HTTPS and check our certificates. Of course it is still possible to fool this system (it's always possible to fool a system that gives a client information they're only supposed to use a certain way), but the thinking is at least we can change the key more easily this way to stem the tide briefly if the key leaks.
This is the key and the box problem, you can keep putting your key in a new box every time and hide this key in a new box and you can keep on doing this.... but in the end you always have the last key... and nowhere to hide it.
Personally i would obfuscate the key to the keychain, and hide the real key in the keychain.
If it is a realy important secret you can use AES to encrypt your key, but then again your stuck with your encryption key, here you can use something that is device specific instead of a hardcoded value and generate your key out of that property.
For sure not perfect but will do the job in most cases.

Keep track of a user 100% sure

I am trying to ban users that spam my service by logging their IP and blocking it.
Of course this isn't safe at all, because of dynamic IP addresses.
Is there a way to identify a user that's 100% safe?
I've heard about something called evercookie, but I was easily able to delete that, and I guess that anyone capable of changing their IP can also keep their PC clean..
Are there any other options? Or is it just not possible?
A cookie will prevent the same browser from visiting your site as long as the user doesn't delete it, or turn off cookies, or use a different browser, or reinstall their browser, or use another machine, etc.
There is no such thing as 100% safe. Spam is an ongoing problem that most websites just have to learn to deal with.
There are numerous highly secure options, mostly relying on multi-factor authentication and physical key generators like the ones RSA markets. But the real question is an economic one. The more draconian the authentication mechanism, the more quickly you kill your website as you scare off all your visitors.
More practical solutions involve CAPTCHA, forum moderation, spam-reporting affordances, etc. One particularly effective technique is to block offending content from every IP address except the one that originated it. That way, the original spammer thinks their content is still there, oblivious to the fact that no one else can see it.
Alright I get that it's impossible to 100% identify a unique visitor.
What are the things that I could do to:
- find whether someone (anonymous) is using lots of different proxies to see my content (problem here is that cookies would land on the machine of the proxy? and not the actual visitors PC?)
- identify unique (anonymous) visitors with a dynamic IP