Category Archives: Java Basics

Add a HTTPS certificate to your Java keychain

You have a tool like GIT or Maven that connects to a HTTPS website. Then your tool needs to know whether to trust that website’s certificate.

When that tool uses Java underneath, you can follow the following steps to add the website’s certificate to your keystore.

1) Visit the website [like for example https://maven.company.nl/nexus] using Firefox.

2) (optional) Confirm and add the exception if you get the notification “This Connection is Untrusted”

3) Export the certificate to a file with the name “CompanyCA.pem” ( click on lock left next to the domain name -> More information -> View certificate -> Details -> Export (choose format “X.509 Certificate with chain PEM”))

Click on the lock
Schermafbeelding 2014-11-27 om 20.51.54

View the details
Schermafbeelding 2014-11-27 om 20.52.36

View the certificate
Schermafbeelding 2014-11-27 om 20.52.49

Export the certificate with format “X.509 Certificate with chain PEM”
Schermafbeelding 2014-11-27 om 21.24.46

4) Add the certificate to you cacerts keychain to the java version that maven uses via the following steps

4.1) Determine which java version your maven uses via
mvn –version
https-keychain-security

4.2) On the command line, go to the java directory via
cd < java home directory >

Note: when you use Windows, then you need to start the command prompt as “Run as administrator”.

4.3) open the lib/security directory within this folder
4.4) Add the website’s CA certificate to the cacerts keychain via
keytool -keystore cacerts -importcert -alias companyca -file < file directory >/CompanyCA.pem

Note Replace the placeholder < file directory > with the file location where you stored the pem certificate. If you are on a unix like system, then you need to prefix this command with sudo.

Provide your password. By default this is changeit
Schermafbeelding 2014-11-27 om 21.07.31

When asked to trust it, type yes
Schermafbeelding 2014-11-27 om 21.08.22

When the notification “Certificate was added to keystore” is shown without errors, then you are done!

Additionally
Do ensure that in your settings.xml and your pom files, all links to you repository point to the https url, so for example https://maven.company.nl/nexus

How do know your certificate is not trusted properly?
When you get one of the below exceptions…

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project parent: Failed to retrieve remote metadata nl.company:parent:1.5-SNAPSHOT/maven-metadata.xml: Could not transfer metadata nl.company:parent:1.5-SNAPSHOT/maven-metadata.xml from/to corporateRepo (https://maven.company.nl/nexus/content/repositories/snapshots): peer not authenticated -> [Help 1]

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project parent: Failed to retrieve remote metadata nl.company:parent:1.5-SNAPSHOT/maven-metadata.xml: Could not transfer metadata nl.company:parent:1.5-SNAPSHOT/maven-metadata.xml from/to corporateRepo (https://maven.company.nl/nexus/content/repositories/snapshots): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target -> [Help 1]

Analyzing java.io.FileNotFoundException on HttpURLConnection

Just tried to open a HttpURLConnection, but that did not go well initially. A very unclear ” java.io.FileNotFoundException ” error was thrown.

So how to analyze why this happens? First check the response code [connection.getResponseCode()], otherwise open the connection.getErrorStream(); instead of the is = connection.getInputStream();

In my case it told me that authentication had to be done first

{"errorMessages":["The requested board cannot be viewed because it either does not exist or you do not have permission to view it."],"errors":{}}

So after adding basic authentication the error was fixed and I got the required response! Here the code:

    public static String readURLWithConnection(String urlString) throws Exception {
        HttpURLConnection connection;
        InputStream is;
        URL url = new URL(urlString);
        
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
        connection.setRequestProperty("Accept", "*/*");

        String userpass = "admin:admin";
        String basicAuth = "Basic " + new String(new Base64().encode(userpass.getBytes()));
        connection.setRequestProperty ("Authorization", basicAuth);

        connection.connect();
        try {
            is = connection.getInputStream();
        } catch(FileNotFoundException exception){
            log.error(exception.getMessage(), exception);
            is = connection.getErrorStream();
        }

        BufferedReader theReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        StringBuilder response = new StringBuilder();
        String reply;
        while ((reply = theReader.readLine()) != null) {
            response.append(reply);
        }

        return response.toString();
    }

Webkit’s XSS Auditor explained and current exploits

Webkit is a open source browser engine used by Safari and Chrome. To prevent cross site scripting attacks (number 3 in this years in the security vulnerabilities list of OWASP), Webkit filters all the web traffic with a auditor.

This auditor, called the XSS auditor, can be looked up online: https://github.com/WebKit/webkit/blob/master/Source/WebCore/html/parser/XSSAuditor.cpp

What does it do?
It prevents cross site scripting (XSS) by replacing malicious scripts with an empty script, so ” <script> </script> “.

As an example, we have our insecure web application.
Schermafbeelding 2013-06-16 om 19.29.15

Which has a simple input value:
Schermafbeelding 2013-06-16 om 19.29.23

When inserted a malicious XSS value into a input field, like ” /><script>pay /* test */ &;lt/script></br ”
Schermafbeelding 2013-06-16 om 19.29.40

Then we see that after submitting the page, the malicious script has been removed.
Schermafbeelding 2013-06-16 om 19.29.59

But wait! There are exploits.
It is good to know that the auditor doesn’t reflect all possible output contexts, like in JSP:

<script type="text/javascript">
    var a = "<%= request.getParameter("a") %>";
    document.write("<text>Welcome "+ a + "</text>");
</script>

When this code is called as follows in our insecure web application

http://localhost:8081/insecure-web/noHtmlEscaping?a=2%22;%20alert(document.cookie);%20var%20a=%221

Then we get to see our session cookie!
Schermafbeelding 2013-06-16 om 19.41.02

JPA 2 @ManyToMany java.sql.BatchUpdateException: Field ‘id’ doesn’t have a default value

Required: having a ManyToMany relation with JPA. Underlying ORM framework I use is Hibernate, but that is irrelevant here since JPA abstracts this.

The Entities
For a @ManyToMany we need two entities. Here we have a entity ‘Beurs’, which owns a collection of ‘Fonds’.

Beurs:

@Entity
@Table(name = “Beurs”)
public class Beurs implements Serializable {
private static final long serialVersionUID = -6250201709027758975L;

@Id
@Column(name = “beurscode”, unique = true, nullable = false)
private Long beurscode;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = “BeursFonds” , joinColumns = { @JoinColumn(name = “beurs_beurscode”, nullable = false, updatable = true) }
, inverseJoinColumns = { @JoinColumn(name = “fonds_fondscode”, nullable = false, updatable = true) })
private List fondsen;

Fonds:

@Entity
@Table(name = “Fonds”)
public class Fonds implements Serializable {
private static final long serialVersionUID = 4655056015858729584L;

@Id
@Column(name = “fondscode”)
private Long fondscode;

@ManyToMany(mappedBy = “fondsen”, fetch=FetchType.EAGER, cascade = CascadeType.ALL)
private List beurzen;

The Join Entity

@Entity
@Table(name = “BeursFonds”)
public class BeursFonds implements Serializable {

@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;

@Column(name = “beurs_beurscode”)
private Long beurscode;

@Column(name = “fonds_fondscode”)
private Long fondscode;

public BeursFonds() {
// default constructor for jpa
}

public BeursFonds(Long beurscode, Long fondscode) {
this.beurscode = beurscode;
this.fondscode = fondscode;
}

The entitymanager

public void store(Fonds fonds) {
List beurzen = fonds.getBeurzen();
for(Beurs beurs: beurzen) {
Beurs beursRepo = entityManager.find(Beurs.class, beurs.getBeurscode());

beursRepo.getFondsen().add(fonds);
entityManager.merge(beursRepo);
}
}

I have the ‘hibernate.hbm2ddl.auto’ set to value ‘update’, so when starting the webapplication with the new entities, these are auto generated. When you generated these tables by hand you might get the following exception. Solution: recreate the tables.

Caused by:
java.sql.BatchUpdateException: Field ‘id’ doesn’t have a default value
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2007)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1443)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.java:56)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1207)