Windows Authentication Headers without .NET. Possible? - linux

I was wondering if anyone knew of a way to use Windows Authentication without hosting on an ASP site. It's an intranet w/ access to LDAP, so I'm wondering if there's a way to force the client to provide me the data as if it was coming from an ASP site. I just need the login domain and username and I can run from there. Using Node.js on Ubuntu. Anyone have any experience with this?

Update: There's now a module that implements Windows-integrated authentication.
In your 401 response, you need to provide a WWW-Authenticate header with a value of NTLM, which informs browsers that they need to send Windows credentials.
response.writeHead(401, {
'WWW-Authenticate': 'NTLM',
});
You then have the fun of implementing NTLM authentication. Quoting from this document about the NTLM authentication protocol:
The client requests a protected resource from the server:
GET /index.html HTTP/1.1
The server responds with a 401 status, indicating that the client must authenticate. NTLM is presented as a supported authentication mechanism via the WWW-Authenticate header. Typically, the server closes the connection at this time:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: NTLM
Connection: close
Note that Internet Explorer will only select NTLM if it is the first mechanism offered; this is at odds with RFC 2616, which states that the client must select the strongest supported authentication scheme.
The client resubmits the request with an Authorization header containing a Type 1 message parameter. The Type 1 message is Base-64 encoded for transmission. From this point forward, the connection is kept open; closing the connection requires reauthentication of subsequent requests. This implies that the server and client must support persistent connections, via either the HTTP 1.0-style "Keep-Alive" header or HTTP 1.1 (in which persistent connections are employed by default). The relevant request headers appear as follows:
GET /index.html HTTP/1.1
Authorization: NTLM TlRMTVNTUAABAAAABzIAAAYABgArAAAACwALACAAAABXT1JLU1RBVElPTkRPTUFJTg==
The server replies with a 401 status containing a Type 2 message in the WWW-Authenticate header (again, Base-64 encoded). This is shown below.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: NTLM TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=
The client responds to the Type 2 message by resubmitting the request with an Authorization header containing a Base-64 encoded Type 3 message:
GET /index.html HTTP/1.1
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGoAAAAYABgAggAAAAwADABAAAAACAAIAEwAAAAWABYAVAAAAAAAAACaAAAAAQIAAEQATwBNAEEASQBOAHUAcwBlAHIAVwBPAFIASwBTAFQAQQBUAEkATwBOAMM3zVy9RPyXgqZnr21CfG3mfCDC0+d8ViWpjBwx6BhHRmspst9GgPOZWPuMITqcxg==
Finally, the server validates the responses in the client's Type 3 message and allows access to the resource.
HTTP/1.1 200 OK
It should be easy enough to get the user's username – it's sent as plain text in the Type 3 message. Actually validating that they've supplied the correct password is another matter entirely. Implementing all of this is left as an exercise for the reader.

Try Apache mod_ntlm or mod_auth_ntlm_winbind.
In Ubuntu:
root#eruditorum.org:~# apt-cache search ntlm apache
libapache2-authenntlm-perl - Perform Microsoft NTLM and Basic User Authentication
root#eruditorum.org:~# apt-cache show libapache2-authenntlm-perl
Package: libapache2-authenntlm-perl
Priority: optional
Section: universe/perl
Installed-Size: 192
Maintainer: Ubuntu MOTU Developers <ubuntu-motu#lists.ubuntu.com>
Original-Maintainer: Debian Perl Group <pkg-perl-maintainers#lists.alioth.debian.org>
Architecture: amd64
Version: 0.02-5
Depends: libapache2-mod-perl2, libc6 (>= 2.4), perl (>= 5.10.0-9), perlapi-5.10.0
Conflicts: libauthen-smb-perl (<= 0.96)
Filename: pool/universe/liba/libapache2-authenntlm-perl/libapache2-authenntlm-perl_0.02-5_amd64.deb
Size: 51418
MD5sum: 46f74ac156f7006d8d71ddbf00097e46
SHA1: 133aebf896156929d364950c2772c3e1344b9c9b
SHA256: 0688b38ab145f888a4d111aad12cb7f201dcd6e12ed969af697d3fec4a55c428
Description: Perform Microsoft NTLM and Basic User Authentication
The purpose of this module is to perform a user authentication via Microsoft's
NTLM protocol. This protocol is supported by all versions of the Internet
Explorer and is mainly useful for intranets. Depending on your preferences
setting IE will supply your windows logon credentials to the web server
when the server asks for NTLM authentication. This saves the user to type in
his/her password again.
.
The NTLM protocol performs a challenge/response to exchange a random number
(nonce) and get back a md4 hash, which is built from the user's password
and the nonce. This makes sure that no password goes over the wire in plain
text.
.
The main advantage of the Perl implementation is, that it can be easily
extended to verify the user/password against other sources than a windows
domain controller.
.
The default implementation is to go to the domain controller for the given
domain and verify the user. If you want to verify the user against another
source, you can inherit from Apache2::AuthenNTLM and override it's methods.
Homepage: http://search.cpan.org/dist/Apache2-AuthenNTLM
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu

You can use an NTLM module in Apache, or you can setup a script under IIS to capture the login information and POST it over to your node.js site.

If you are using Ubuntu, do a
sudo apt-get ntlmaps or download 'ntlmaps-xx-xx.deb'
and configure your proxy which would ask you for your domain, username and password.
Then run ntlmaps as your proxy. Ntlmaps will authenticate using your username and password. You write any program ntlmaps will authenticate your program automatically using your given configuration details. However there are few things you need to configure as well after installing ntlmaps. First let me know if is this something you are looking for?

Related

Understanding the purpose of "realm" in Basic WWW Authentication

I'm having difficulty understanding the purpose of the "realm" value in the WWW-Authenticate header used for basic HTTP authentication.
This question asks what the "realm" value is - and the answer seems pretty straightforward. The "realm" is sort of like a namespace, indicating a collection of protected resources.
Okay, so I get the abstract concept. But in practice, especially from the perspective of an HTTP client, how does "realm" actually help?
When authenticating over HTTP, the basic workflow seems to be:
(1) The server issues a challenge in the form of a WWW-Authenticate
header
(2) The client responds with an Authorization header, along with
a base64 encoded string containing the username and password.
(3) The Client is now granted access (or denied if credentials are wrong)
So where in any of this should the client have to care about the "realm" value sent by the server?
It's my understanding that if the client wants to access a protected resource again, the only thing necessary is to send the "Authorization" header again. So... again, how does the "realm" play into all of this?
Just to be clear... I understand what a "realm" is conceptually... I just don't see how it's used in practice by HTTP clients.
I just don't see how it's used in practice by HTTP clients.
The browser will not ask the user for credentials while the realm stays the same. So if you log on to http://example.com/ApplicationA which provides a certain realm value, then http://example.com/ApplicationB using the same realm can reuse the credentials the user entered for application A because their "canonical root URL" is the same (http://example.com), so the browser doesn't have to pop up the credentials form again.
Browsers seem to implement this differently though, depending on what part of the URI changes some will ask for credentials again even if realm and canonical root URL stay the same.

When trying to create a SSL connection with LWP::UserAgent, what do I use for realm?

I've started a project to scrape my work's employee website to scrape the user's (in this case, mine) schedule and munge the data onto a google calendar. I've decided to go with Perl with LWP.
The problem is this, when trying to set up SSL negotiations I don't know what do put for the 'realm'.
For example: (http://www.sciencemedianetwork.org/wiki/Form_submission_with_LWP,_https,_and_authentication)
# ...
my $ua = new LWP::UserAgent;
$ua->protocols_allowed( [ 'http','https'] );
$ua->credentials('some.server:443',**'realm'**,'username','password');
# ...
I've looked at everything my browser can tell me and at a wireshark packet capture trying to find anything but to no avail. I assume that second argument to credentials() isn't optional.
Where do I find the 'realm' I'm supposed to use?
The credentials are for the HTTP authentication protocol (RFC 2617) (Wikipedia).
The server can challenge the client to authenticate itself. This response contains a string called “realm” which tells the client for what authentication is required. This allows the same server under the same domain to request authentication for different things, e.g. in a content management system where there might be an “user password” and an “administrator password”, which would be two different realms.
In a browser, this realm would be displayed alongside the username and password box which allows the user to type in the correct password.
To discover the realm, navigate to a page which requires authentication and look for the WWW-Authenticate header.
Note that HTTP authentication has become quite uncommon, with session cookies being used more often. To deal with such an authentication scheme, make sure that your LWP::UserAgent has an attached cookie storage, and then navigate through the login form before visiting your actual target page. Using WWW::Mechanize tends to make this a lot easier.

understanding basic authentication with a 401

I'm a little confused about Basic authentication in regards to web browsers. I had thought that the web browser would only send an Authorization header after having received an HTTP 401 status in the previous response. However, it appears that Chrome sends the Authorization header with every request thereafter. It has the data that I entered once upon a time in response to a 401 from my website and sends it with every message (according to the developer tools that ship with Chrome and my webserver). Is that expected behavior? Is there some header I should use with my 401 to infer that the Authorization stuff should not be cached? I'm using WWW-Authenticate header currently.
This is the expected behavior of the browser as defined in RFC 2617 (Section 2):
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in
that space without receipt of another challenge from the server.
Similarly, when a client sends a request to a proxy, it may reuse a
userid and password in the Proxy-Authorization header field without
receiving another challenge from the proxy server. See section 4 for
security considerations associated with Basic authentication.
to my knowledge, Basic HTTP authentication has no ability to perform a logout / re-authentication. This along with the lack of security of HTTP Basic authentication is why most websites now use forms and cookies for auth solutions.
From RFC 2617:
If a prior request has been authorized, the
same credentials MAY be reused for all other requests within that
protection space for a period of time determined by the
authentication scheme, parameters, and/or user preference.
From my experience it is quite common to see browsers automatically sending the Basic credentials for subsequent requests. It prevents having to do an extra round trip for additional resources.

lwIP on Stellaris 32-bit microcontroller - Secure Login

I wish to use my Stellaris LM3S8962 microcontroller as a bridge between internet and a bunch of sensors. I will be using Zigbee nodes for communication from the sensors to the microcontroller. I have been able to use the lwIP TCP/IP stack (for LM3S8962) to access HTML pages stored in the controller's flash.
Now, I want to add a secure login system for the same. What I basically want is that - when I enter the IP of the controller in the browser, it should prompt me for a username and a password. I want to make this system as secure as possible using the lwIP TCP/IP stack.
FYI, the stack does not support PHP or any other scripts. CGI feature (in C) is supported but I don't know how to implement the security part. Please guide.
There are basically two ways you could implement user authentication over HTTP on your platform:
"classic" Basic HTTP authentication (see RFC2616 for exact specification),
a login form, creating a session ID, and returning that to the browser, to be stored either in a cookie, or in the URL.
Basic HTTP authentication works by you inserting a check into your web page serving routine, to see if there is an Authorization HTTP header. If there is, you should decode it (see the RFC), and check the specified username/password. If the credentials are ok, then proceed with the web page serving. If the credentials are incorrect, or in case there is no Authorization header, you should return a 401 error code. The browser will then prompt the user for the credentials. This solution is rather simple, and you'll get the browser login dialog, not a nice HTML page. Also, the microcontroller will have to check the credentials for every page request.
Authentication via a login form works by your server maintaining a list of properly authenticated user sessions (probably in memory), and checking the request against this list. Upon loggin in, a unique, random ID should be generated for that session, and the session data should be entered into your list. The new session ID should be returned to the browser to be included in upcoming HTTP requests. You may choose the session ID to be put into a browser cookie, or you can embed it into the URL, as a URL parameter (?id=xxxxx). The URL parameter is embedded by sending a 302 Redirection response to the browser with the new URL. If you want the cookie solution, you can send the response to the login request with a Set-Cookie HTTP response header. In the login form solution, the actual credentials (username/password) are only checked once, at login. After that, only the session ID is checked against the list of active sessions. The session ID has to be extracted from the requests for every web page serving (from the URL, or from the Cookie HTTP header). Also, you'll have to implement some kind of session timeout, both as a security measure, and to put bounds to the size of the list of active sessions.
Now comes the harder part: in both solutions, the username/password travels in some requests (in every request for the Basic HTTP authentication, and in the login page POST for the login form solution), and can be extracted from the network traffic. Also, information neccessary to hijack the session is present in every request in both solutions. If this is a problem (the system works on a freely accessible LAN segment, or over network links beyond your control), you'll probably need SSL to hide these sensitive data. How to get a reasonable SSL implementation for your platform, that's another question.

How secure is a HTTP POST?

Is a POST secure enough to send login credentials over?
Or is an SSL connection a must?
SSL is a must.
POST method is not more secure than GET as it also gets sent unencrypted over network.
SSL will cover the whole HTTP communication and encrypt the HTTP data being transmitted between the client and the server.
<shameless plug>I have a blog post that details what an HTTP request looks like and how a GET request compares to a POST request. For brevity's sake, GET:
GET /?page=123 HTTP/1.1 CRLF
Host: jasonmbaker.wordpress.com CRLF
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1 CRLF
Connection: close CRLF
and POST:
POST / HTTP/1.1 CRLF
Host: jasonmbaker.wordpress.com CRLF
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1 CRLF
Connection: close CRLF
CRLF
page=123
(The CRLF is just a newline)
As you can see, the only differences from the standpoint of how a request is formed* is that a POST request uses the word POST and the form data is sent in the body of the request vs the URI. Thus, using HTTP POST is security by obscurity. If you want to protect data, you should use SSL.
* Note that there are other differences.
That depends on your circumstances, how much would the interception of the credentials cost somebody?
If it's just a login to a software Q+A site then SSL might not be necessary, if it's an online banking site or you store credit card data then it is.
This is a business not a techncial decision.
HTTP POST is not encrypted, it can be intercepted by a network sniffer, by a proxy or leaked in the logs of the server with a customised logging level. Yes, POST is better than GET because POST data is not usualy logged by a proxy or server, but it is not secure.
To secure a password or other confidential data you must use SSL or encrypt the data before you POST. Another option would be to use Digest Authentication with the browser (see RFC 2617). Remember that (home grown) encryption is not enough to prevent replay attacks, you must concatenate a nonce and other data (eg. realm) before encrypting (see RFC 2617 for how it is done in Digest Auth).
SSL is a must :)
HTTP Post is transmitted in plain text. For an example, download and use Fiddler to watch HTTP traffic. You can easily see the entire post in there (or via a network traffic monitor like WireShark)
It is not secure. A POST can be sniffed just as easily as a GET.
No...POST is not secure enough at all. SSL is a MUST.
POST only effectively hides the parameters in the query string. Those parameters can still be picked up by anybody looking at the traffic in between the browser and the end point.
No, use SSL.
With POST the values are still submitted as plain text unless SSL is used.
The most secure way is to not send credentials at all.
If you use Digest Authentication, then SSL is NOT a must.
(NB: I am not implying that Digest Authentication over HTTP is always more secure than using POST over HTTPS).
POST is plaintext.
A secure connection is a must.
That's why it's called a secure connection.
A POST request alone is not secure because all the data is "traveling" in plain text.
You need SSL, to make it secure.
The only difference between HTTP GET and HTTP POST is the manner in which the data is encoded. In both cases it is sent as plain-text.
In order to provide any sort of security for login credentials, HTTPS is a must.
You do not need an expensive certificate to provide HTTPS either. There are many providers that will issue very basic certificates for about $20USD. The more expensive ones include identity verification which is more of a concern for e-commerce sites.
Please see this great article:
Protect Against Malicious POST Requests
https://perishablepress.com/protect-post-requests/
POST data is sent in plain text if you are using an unencrypted HTTP connection.
IF this is secure enough depends on your usage (hint: it's not).
If both the server, the client machine and ALL MACHINES BETWEEN THEM are part of a controlled, fully trusted network, this may be ok.
Outside of these very limited circumstances (and sometimes even within them) plain text authentication is asking for trouble.

Resources