How to protect password sending through httpclient method in java - java

From SCAVA security scan tool it is reported that some of my code lines are subject to vulnerability.
The vulnerability classification is :
Insufficient_Sensitive_Transport_Layer
The vulnerable code contains
httpclient.addHeader() method sending password to login a server/api.
Application is in java langauge.
From google, I got to know that we can add some encryption method to avoid this vulnerability.
HttpGet getMethod = null;
getMethod = new HttpGet("http/https url to connect");
getMethod.addHeader(USERNAME,PASSWORD); // Vulnerability reported in
//this line as it is sending the password without any protection.
How can i prevent this vulnerability and pass the password in a secure way through some encryption method.
Thanks in advance.

Enable Transport Layer Security (TLS) each time you have to send credentials as plain text. If you have correctly configured https:// with latest secure version of TLS the communication will be secure.
Moreover, there are situations where sending plain text credentials can't be avoided e.g. user login process. Automatic scanning tools might not be smart enough to distinguish valid use cases and raise a false-positive.

Related

Java (JDK1.8) is not setting server_name extension in SSL handshake when hostname has '_'

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
System.out.println(httpclient.execute(httpget));
I am using this programming snippet and using this with couple of urls. "https://abc.def.com/file.txt" and "https://ab_c.def.com/file.txt" (actual names i used exist - this is just an example). When i run the code with -Djavax.net.debug=ssl:handshake:data options set, I see _server_name_ extension is added only in case of abc.def.com and not in case of ab_c.def.com.
I am aware that java.net.URL package doesn't allow '_' in hostname. Is this a similar issue? Is there any workaround to get the SSL handshake include the hostname with '_'?
The answer is no. This wont work in java using the standard JDK libraries with HTTPS.
There virtually no "normal" Java way to work around this problem.
Other ideas:
ask the service owner to provide a domain name without the _.
dont use SSL/HTTPS. Most Java HTTP clients that are not doing strict checks will work with a hostname with an underscore in it. This is not a great solution if you are on the open internet
do use HTTPS but go direct to the IP address and disable HTTPS hostname validation. This is also a bad idea if you are on the open internet
introduce a MITM or forward proxy that can provide a HTTP endpoint to your service, but will do HTTPS over the untrusted parts of the network, (SSL onloading?)
just shell out to curl and read the resulting string, as described here on Baeldung. Be very careful here, as it's very easy to unwittingly open yourself up security issues like remote code execution
use jni to get to a network library that will allow the underscore - libcurl is an obvious candidate, but this will be significantly more work than the System.execute method, also possibly unsafe for other reasons (memory management, instability of badly written jni interop, not great for maintainability)
You could possibly try to fork the related URI / URL parsing classes in java.net to remove the check for the underscore. The problem with this is it's a massive hack, possibly of unbounded difficulty, could easily break all manner of things unintentionally and you might need to build your own version of the JDK as I have some recollection of java.net code being special for some reason in that you couldn't just chuck a patched class in ext/lib dir of the JVM (but I could be mixing that up with something else).
I will provide a hotfix.
In your /etc/hosts file, include a new entry without the underscore to the IP.
For example,
abc.com xx.xx.xx.xx
Then, use abc.com in your program.

GitKit Java client library – emailVerify status of account with Facebook as provider

I was testing the following scenario. Sign in with GitKit and use Facebook as the provider.
All works well, but and the token cookie contains a.o.: "provider_id":"facebook.com","verified":false
Note that verified is false, albeit Facebook emails are verified by Facebook. I understand if GitKit might not want to hard code this assumption, but..
If we then send the user a verification email from our server using getEmailVerificationLink(gitkitUser.getEmail()) again all goes well.
(link is .../signin.html?mode=verifyEmail&oobCode=sFKXzFsKQ4ckr4A-HtofNPkRq_A&apb.cs=1)
The user sees "Success! Your email address has been verified."
But when then redirected to our server the token cookie still says "verified:false"!
My question is if this is the expected behavior?
Because if it is then I don't get it and I would very much appreciate some clarification.
Note, if I sign in with a simple password account, then the token cookie does give "verified:true" after the user followed the getEmailVerificationLink().
It sounds like a bug for social login account. The verified flag should be true after the verification. I will update here once we confirm the root cause.

Android 401 Error connecting to REST service using HttpURLConnection

I am developing an android application and want to connect to a REST service using URLConnection. The resource is protected using Digest Authentication. I can successfully access the REST service via the browser. I do not want to use HttpClient because URLConnection is the more current way to connect for the future.
But when I try to access the resource via the code below, I get a 401 Error with an java.io.FileNotFoundException. I have researched this thoroughly but no success, solutions appreciated.
Note: My REST service has been developed using Grails, I am running this code in the android emulator with code developed in Eclipse on the windows 64 bit OS.
CODE
URL myurl = new URL("http://10.0.2.2:8080/MyREST/customers");
HttpURLConnection myurlConnection = (HttpURLConnection) myurl.openConnection();
String basicAuth = "Basic " + (Base64.encode(userpass.getBytes(),android.util.Base64.DEFAULT)).toString();
myurlConnection.setRequestProperty ("Authorization", basicAuth);
try {
int responseCode1 = ((HttpURLConnection) myurlConnection).getResponseCode();
Log.i("MyLongOperation", "Check connection" +Integer.toString(responseCode1) );
InputStream in = new BufferedInputStream(myurlConnection.getInputStream());
readStream(in);
}
finally {
myurlConnection.disconnect();
}
I have also tried setting authentication at a global level with no effect
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
);
I have referred to this article - with no success. Connecting to remote URL which requires authentication using Java
If the resource is protected by "Digest" then sending a "Basic" authorization scheme in your code will not work because the server would not recognize it.
Secondly, by using a "preemptive" authentication, setting the Authorization header w/o it being requested is kind of a security hole. You will be sending information to the server that it has not requested.
Thirdly, the "Authenticator.setDefault" most likely will not be requested as there was some significant back-and-forth caused by MicroSoft's implementation of HTTP digest authentication (YMMV may vary on my recollection of this). As such, Sun/Oracle decided to leave this behavior disabled by default as per this document.
That said, you may be better off looking into utilizing the Apache HTTP client bundled with Android to do this. There is a bundled implementation Digest Authentication included. There is an example of "preemptive" digest authentication located here.
Couple of caveats to be aware of:
Pay CLOSE attention to the "HttpHost" stored in "target" - this MUST MATCH EXACTLY the host name, protocol port, and protocol scheme used in the URL being retrieved.
The example provided is for HTTP Client 4.2.x. I am not 100% sure of the version included in Android but you should be able to locate working examples.
Update Submitter has provided additional comments with regard to the statement that it is recommended by Google to use the HttpURLConnection with articles here and here.
While I trust the statements made by Tim Bray with regard to the reasoning as to why you should be using the provided HttpURLConnection object for performing these calls, I do not agree that they should be immediately accepted on face value.
There is no indication as to the level of support of digest authentication provided by the implementation in Android. As I mentioned earlier, the HttpURLConnection does not support immediately as it has been known to be buggy.
If you are decided that you are going to use HTTP Digest Authentication, regardless of the fact that it has been deemed unstable by the majority of the community, I would attempt to set the following system properties in your application as EARLY as possible during the Android lifecycle:
http.auth.digest.validateServer="true"
http.auth.digest.validateProxy="true"
By doing so, this should enable the digest authentication scheme.
I am, again, going to re-iterate that the Apache HTTP Client bundled with Android was developed and designed specifically to address short-comings of the basic Java HttpURLConnection, providing much a much broader and robust client for dealing with HTTP(s) based data streams.
I would recommend trying a couple of things as well, see if you can configure your container to provide "Basic" authentication protection. The other, more complex option, would be to possibly provide X.509 Certificate Based authentication.
I hope that this clarification helps you get to your goal.
change
'Base64.encode ...'
to
'Base64.encodeToString ...'

UnboundID SASL cannot acquire password

Relating to my other question: UnboundID LDAP DIGEST-MD5 binding cause NPE
I'm using ApacheDS as the server and UnboundID as the API.
I followed the suggested answer and the NPE is gone. However, now I'm getting this error.
LDAPException(resultCode=49 (invalid credentials), errorMessage='INVALID_CREDENTIALS: DIGEST-MD5: cannot acquire password for 'dn:uid=blah,ou=dev,dc=blah,dc=com in realm : mizar.com', diagnosticMessage='INVALID_CREDENTIALS: DIGEST-MD5: cannot acquire password for dn:uid=blah,ou=dev,dc=blah,dc=com in realm : blah.com')
at com.unboundid.ldap.sdk.LDAPConnection.bind(LDAPConnection.java:1881)
at UnboundDemo.main(UnboundDemo.java:40)
Code as follows:
conn = new LDAPConnection("1.1.1.1",389);
mdBind = new DIGESTMD5BindRequest("dn:uid=blah,ou=dev,dc=blah,dc=com", null, "test", "blah.com",null);
bindResult = conn.bind(mdBind);
System.out.println("MD5 bind success!");
Here's the ApacheDS SASL configuration from the Directory Studio config page:
SASL Host: 1.1.1.1
SASL Principal: ldap/ldap.example.com#EXAMPLE.COM
Search Base Dn: ou=dev,dc=blah,dc=com
The ApacheDS doc didn't explain what the SASL Principal is so I'm starting to think that it may be a mis-config on my part. The main idea here is to test UnboundID against a number of SASL mechanism.
It is likely the case that the ApacheDS server isn't configured to store passwords in a format that allows it to determine the clear-text value for the password.
The primary attractive property of the DIGEST-MD5 and CRAM-MD5 SASL mechanisms is that the password is combined with other information and encoded with a one-way digest before being sent to the server. This ensures that the password is not transmitted in the clear, so that it is protected against anyone who can observe the communication without the need to secure the rest of the communication. However, the ability to authenticate with one of these mechanisms requires that the server be able to determine the clear-text version of the password so that it can perform the same cryptographic processing as the client.
If you're just looking to test the UnboundID LDAP SDK's ability to perform SASL authentication, then I'd recommend using the PLAIN mechanism, since it shouldn't impose any special requirements on the user entry. If you really want to use DIGEST-MD5, then you'll need to ensure that the server has access to the clear-text representations of the passwords for the users that need to authenticate with that mechanism.
Neil

How to get Kerberos TGS and use it in a GUI application in Java?

i'm trying to make an application with the Keberos protocol and the GSS-API in Java, and i've already made the authentication and the context establishement before calling the doAsPrivileged method.
In this method I get the mutual authentication sending a simple token from the client to the server, but after that i want to make some other things.
I want to open a new window with a table of products to let the client select them and buy something and that was connected to a database in the server.
my question is about how can a i use this context in other frames that are diferent from the original doAsPrivileged action class.
i get an error GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt) and i don't know how can i find this TGT to send it more than one time to the server.
thank you.
I ran into a similar issue as well.
Your code fails because Java tries to use GSSAPI with the default login config name. Which is com.sun.security.jgss.initiate. To perform a GSS call for someone else or with another login conf name you have to use the LoginContext, obtain the subject and then do a doAs. As far as I can see, every action involving ticket exchange has to be done in a PrivilegedAction if you don't stick to the defaults. That's why our stuff's failing :-(

Categories

Resources