Host Header Injection - http-headers

I am a beginner in security and reading about the host header injection. I tested an application for this vulnerability and it is possible there for some request but developer implemented no-cache, no-store flags and this vulnerability is not in password reset request.
So first thing is there will not be cache poisoning. and the second is it is not happening in password reset request.
As I understand that for exploiting this vulnerability, I changed that host header. So I want to know why will It be a vulnerability, why a user will change Host of the application? and how an attacker can exploit it?

As in all of the cases the client input on the application should be never trusted (in security terms). The host header attribute is also something that can be changed by the client.
A typical attack scenario would be for example:
Lets suppose you have an application that you blindly trust the HOST header value and use it in the application without validating it.
So you may have the following code in your application, where you load a JS file dynamically (by host name):
<script src="http://<?php echo $_SERVER['HOST'] ?>/script.js">
In this scenario, whatever the attacker set as the HOST header would be reflected on this JS script load. So the attacker could tamper with this by manipulating the response to load a JS script from another host (potentially malicious). If the application is using any Caching mechanism or CDN and if this request is repeated multiple times, it can be cached by the Caching Proxy. Then, this can be served to other users as well (as it was saved to cache).
Another way of exploiting this is:
Let suppose that the application has a user password reset feature. And the application will send an email to whoever asks for a password reset with a unique token to reset it, like the email below:
Hi user,
Here is your reset link
http://<?php echo $_SERVER['HOST'] ?>/reset-password?token=<?php echo $token ?>
Now an attacker can trigger a password reset for a known victim email by tampering the HOST header value to the one of his desire. Then the victim would receive the legitimate email for password reset, yet the URL will be changed to the domain set by the attacker. If the victim would open that link, the password reset token could be leaked to the attacker so it would lead to account takeover.

Related

Basic Auth Authorization Header Conflicts with Backend

I have a backend service configured as a subdirectory behind a reverse proxy. The backend has its own auth scheme, and it relies on the authorization header being formatted as
Bearer <JWT Token>
in order to validate a session. Unfortunately, the backend reveals what it is to any curious eyes, and doesn't keep any record of auth attempts/failures to filter with, for example, fail2ban.
I would like to hide the backend behind basic auth, so the page details are only loaded for authorized users, and so that I can monitor auth attempts/failures across all my backends with a simplified fail2ban filter.
The problem I'm encountering, is that in order for the client's requests to reach the backend, once it's secured behind basic auth, the Authorization header needs to be formatted as
Basic <base64-encoded username:pass pair>
The moment the client sets this header, though, the backend is unreachable. The backend and the client also have quite a bit of back-and-forth communication, and from what I can tell <UserToken> is dynamically generated for each login session.
I've tried
proxy_set_header Authorization <A statically generated and set JWT Token for testing>
In the location block of the backend. However, at some point in the transactions that result between client and backend, the Authorization header goes from
Basic (with backend asking for credentials)-> Bearer (backend is authenticated and loads a few resources until...) -> Basic (backend is now logged out and reauthenticating causes an infinite loop)
Essentially, as soon as the Authentication header is reset by the client to authenticate with basic auth, presumably for the client's next request, the backend becomes inaccessible. I would like a way to dynamically maintain two Authorization headers with nginx, if such a configuration is possible, and set the header appropriately according to where in the chain between client, proxy, and backend the request occurs.
I've also tried to experiment a little bit with a mapping like:
map $http_authorization $origin_auth {
"Bearer" $http_authorization;
}
and then adding this directive inside the server block:
add_header my-header $origin_auth always;
Just to see if I could store the header for retrieval on one of the client's future requests, or something... scrolling through dev tools though, to examine the header fields, "my-header" never assumes the value of the backend's expected authorization header.
I don't have enough experience with either the http protocol, or nginx, to know if the thing I want to accomplish is even possible, and I haven't found much help in other posts. I have tried throwing about 3 dozen hours of my life at the problem though, without any luck. Any help would be very welcome and appreciated.

CSRF Double Submit Cookie is basically "not Secure"

From OWASP page : A CSRF attack works because browser requests automatically include all cookies including session cookies.
To prevent it, we can use double-submit cookie hash.
In some sample codes I found, basically this algorithm is found.
Victim access app:
Backend : generate login cookie AND hash string related to login
cookie
Frontend : store the hash string into second cookie (say :
CSRF-token cookie)
Frontend (secured) : send request with login
cookie and CSRF HTTP header, where the header value is extracted
from CSRF-token cookie.
Attacker :
Use some kind of social media engineering to make users click malicious link, where this malicious link use session cookie.
The attacker then steal this session cookie to logged in as victim
Double submit cookie should prevent this attack since attacker also need to provide valid CSRF token in the HTTP header.
I still don't get this: If browser requests automatically include all cookies, that means on clicking malicious link, both login cookie AND CSRF-token cookie will also included, and attacker steal both of them.
So the attacker is just need to extract value from CSRF-token cookie, and create his own API access, using login cookie that he steal, and CSRF HTTP header with extracted value?
Am I missing something?
Thanks
A few things appear to be mixed up here.
So in the original synchronizer token pattern, you would generate a random token, store it server-side for the user session, and also send that to the client. The client would then send the token back as a form value or request header, but not as a cookie, so it doesn't get sent automatically - that's the whole point. (And the server would of course compare the token from the request to the one in the session.)
In double posting, the token doesn't even need to be generated server-side, the client can also do it (or the server can send it, doesn't matter that much if we accept that crypto is good enough in Javascript).
The token will be sent as a cookie, and also as something else (form value, request header, anything not sent automatically). If the server sent it as a cookie (obviously without httpOnly), the client can read it from that and include as a non-cookie too in a request. The server will again just compare the two.
The point is that an attacker on attacker.com will not be able to access the cookie (neither read nor write) for the application domain. So if the client can read the cookie and include it as something else in the request, that client must be running on the application origin (if we are talking about unmodified browsers only), so no CSRF is being performed. The client can also create the whole token itself, because attacker.com will still not be able to create a cookie for the application domain.
So based on the above, if everything is just in cookies, the implementation is wrong, and does not protect against CSRF.
While Gabor has basically answered the question, I just wanted to add some emphasis on some of the important parts, since I was once also confused with this double submit cookie technique.
The main misconception here is to assume that CSRF attack happened because the attacker is able to steal the cookie from the "targetweb.com", while in fact the attacker doesn't need to know the value of the cookie at all!
For the CSRF attack to happen, the attacker only need 4 conditions:
The session on the target site has already been established (user has logged in to the "targetweb.com")
The attacker knows the request format of some operation (e.g transfer fund)
The session token is stored in cookie.
The user trigger something (e.g a button/link), that unbeknownst to him, send a request to the "targetweb.com".
All the attacker need to do is to make the user trigger the request that had been forged by the attacker without the user knowing (and the important part is, the forged request doesn't need to contains the session cookie, since it will be added automatically by the browser later when it is sent -- thus the attacker doesn't need its value).
Now, with the double submit cookie technique, the server send additional value in the cookie. The attacker doesn't know its value. And when a request is made, this value need to be also appended to, say, a request header (which not automatically added). The server is then compare this header value with the cookie value and only proceed when the value match.
What's different from the attacker point of view is now he need to append the value to the header also to make the request valid. And he doesn't know the value, thus CSRF is prevented.
CSRF protection with double submit cookie is not secure.
Therefore, in the OWASP documentation, the double submit cookie is classified as one of defense in depth.
The reason is that cookies can be set by a third party with MITM attack.
HTTPS requests and responses cannot be eavesdropped or modified. However, MITM attack can modify the HTTP response(plain text).
An attacker could direct the victim to http://example.com/ (Target site) to send a plaintext http request.
Then, in response, the attacker can use MITM to return a Set-Cookie header.
HTTP / 1.1 200 OK
Set-Cookie: CSRFTOKEN=XXXXXXXXXXXXXXXXXXXXXXX;
This CSRFTOKEN is set in the victim's browser.
Next, the attacker sets up a CSRF trap page below.
<form action="https://example.com/target" method="POST">
<input type="hidden" name="mail" value="evil#example.net">
<input type="hidden" name="token" value="XXXXXXXXXXXXXXXXXXXXXXX">
<input type="submit">
</form>
The destination of the above form is a https page, but the cookie set by http response is also valid on https requests.
So the cookie and hidden parameter will be sent the same value, bypassing CSRF protection.

Getting a 401 response on couchdb authentication

I've spent the last day or two pulling my hair out over this, so I thought I'd share the answer.
Problem: When trying to get an authentication cookie from the client side (using some http library or another), you get a 401 Unauthorised response. Even though you know the username and password are correct and you're doing it exactly how it's done in all the examples. Well my friend, your issue is that you expect things to make sense.
Turns out that if you have the require_valid_user set to true in the couch db config, and then don't include those credentials with an authentication request (even if the credentials you're authenticating are valid!) couch will reject it out of hand. So you've two options really,
Keep require_valid_user true and do your authentication on your own server where you can wack in the admin username and password as a part of the url (like so url = http://admin:password#url:5984). And then authenticate your credentials and pass back the ensuing cookie you get from that. (Make sure in subsequent requests straight from the client to the db you include withCredentials:true, so the browser sends the cookie with the request).
Say screw it and don't require a valid user with each request, and instead authenticate on the design doc and database security level only. I can't vouch for how secure this is, as I haven't done it.

LDAP "force-change-on-add" can't be handled properly

I'm using openDJ LDAP server for authentication process of a Java based project using JNDI.
Most of the other things like password expired, invalid credentials can be handled using exceptions. (using the understandable message in exception, or using the error codes in some occasions)
ds-cfg-force-change-on-add and ds-cfg-force-change-on-reset attributes are set to true in the password policy.
But when a newly created user logs in or, when a user logs in after a password reset by admin no exceptions occur.
Can somebody tell me how to handle this.
One alternative in this case is the password policy request and response controls (example) defined in draft-behera-ldap-password-policy, supported by OpenDJ LDAP SDK and other SDKs. You pass the request control to the directory server, and you get back a response control.
The response control indicates whether the password needs to be changed, why a requested password modification could not complete, how much time remains before expiration, etc.

What 'exactly' happens when I type a password in a web-browser before the password is sent out of the machine onto the network?

What happens exactly when I type a password into a password input field in a form in a web-page (e.g the password field of Gmail) and then hit enter. I want to understand the procedure before the browser sends it out of the local machine onto the network. For example: on the local machine, the web-browser first makes a system call, then the local machine does some processing on the password, and then sends it over the network. I searched on Google a lot, but could not find anything useful.
Nothing special happens, in general.
A password is just an HTML <input> element. It's just a text box.
In most instances, web sites requiring form submitted passwords use HTTPS to encrypt the posted data (including the username and password) back up to the server (if the site doesn't use SSL, then the password would be sent up in cleartext).
Edit:
According to wiki, SSL / TLS works at the presentation layer of the OSI, although this SSL article indicates that SSL is in the TCP application layer. AFAIK https is just http working on top of an SSL connection.
As per #John's post, the traditional way of submitting passwords is by providing the user with a form with a username and password .
(Full reference here)
<form name="input" action="https://somesite/login.asp" method="post">
Username: <input type="text" name="user" />
Password: <input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
This form data would be posted back to the server, which should then validate the input before checking authentication of username and password (usually by passing one or both fields through a one way hash to ensure that passwords aren't stored cleartext in the database).
From a security point of view
Although the browser will 'show' asterisks on the password control, the browser still has knowledge of the cleartext password.
Secure forms method should be POST (method = GET would appear on the querystring)
The form page itself should have been served via https (since in addition to encryption, the browser verifies the server's certificate against the domain, for expiry, for the certification chain itself)
and the form action itself should use an https:// url, to ensure that the username and password are encrypted in transit on the way back to the server.
One concept that needs to be made is the reason why the browser doesn't 'hash' or otherwise do some of the authentication checking on the 'client side' of the connection is because the server mustn't ever trust the browser / remote computer - the original full password must be sent by the remote client computer.
Re : Can I hack the password?
Common attacks are
Keylogging - software which logs user's keystrokes, including usernames and passwords
Phishing - the attacker presents the user with a site login page which looks like the target login page, the user can be fooled into typing username and password. If the user's configured DNS or LMHosts file is compromised, then the login URL can be made to appear bonafide, even though it is served by the attacker's phishing server.
XSS attack (e.g. if the login page displays unvalidated user comment posts on the same page) would allow an attacker to inject javascript to hook into any number of events on the page to obtain usernames and passwords
With weak client validation and some information about the design of server, SQL Injection attacks can be used to either bypass the login entirely, read data from the server database (e.g. obtain all users and passwords if they are stored cleartext), or corrupt or delete data on the server (but this attacks the server, not the browser)