The OWASP Top Ten and ESAPI – Part 5 – Insecure Direct Object Reference

No Gravatar

This article will describe how to protect your J2EE application from direct object reference (DOR) attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

What is direct object reference (DOR)? Other than being a somewhat quirky, generic name … here’s what OWASP says it is:

“A direct object reference occurs when a developer exposes a reference to an internal implementation object, such as a file, directory, database record, or key, as a URL or form parameter. An attacker can manipulate direct object references to access other objects without authorization, unless an access control check is in place. ” [from here]

So, what does that mean? Well for most (not all) J2EE developers, it will mean database key references, so that’s what we’ll deal with here. However, the discussion is applicable no matter what your reference.

Consider the following database table called USERS.

ID FNAME LNAME
1 John Melton
2 Bill Smith
3 Susan Thomas
4 David Carter

Now, let’s say that this database table were queried in a normal application. Then, the results are presented on the page, and each record in the result list would probably have a link to more detail about each user, having their pictures, their list of friends, etc. This is the typical master-detail interaction and is prevalent in pretty much any web app, not just J2EE. But how do we get to the detail page? How do we pass along which user we want to see in detail from the “master” table to “detail” page? Well, we could start by using the first name, but that’s not unique, or we could use the last name, but same issue. We could include both, which is less likely to produce duplicates but it’s still possible. In most situations, what happens is each table in the database has a column setup as a unique identifier. Each record in the table will have a different ID. So, that’s what we use. Now, here’s what the url might look like to go view greater detail about Bill:

/users/viewDetail?id=2

Ok, great, so what we have is the identifier being passed in the url to represent Bill. That way when we get to the view detail code, we simply check the id that was passed in and pull up that record in detail and display the information.

So where’s the issue? Well, everything works fine in this instance b/c every user is able to see the detail, but let’s look at what this might look like for a bank, which is the classic DOR example. In a bank, all records for all users are stored in the same table (at least in our example), however each user can only view his or her account. They should not be able to simply pick a random account to view or manipulate. But what if the URL to my account looks like:

/accounts/viewDetail?id=3540

What would happen if I changed this to

/accounts/viewDetail?id=3541

If there’s no protection in place, I can see someone else’s account!

Well, this is the crux of the DOR problem. Any attacker can manipulate url or form parameters at will when they submit a request, which means this issue obviously applies to both GET and POST requests, as well as exposed parameters, hidden fields, etc. If it’s being sent from the client to the server, the client can alter it. That means when you use the ID as the reference, and that ID can be manipulated, the attacker can gain access to data that they should not have access to. The ID in this case is the direct reference (id) to the object (record in the table) that you are trying to access.

Where do we go from here? ….

Well, ok, that’s not super encouraging. We have an issue (that most people have never heard of) that is affecting most applications . Banking is the obvious example, but this could be a problem for many different types of applications. Take heart, there is a solution (actually there are two)! You have 2 options for how to properly deal with this issue when it exists in your application.

1. Use ESAPI’s AccessReferenceMap (or something similar)
2. Perform authorization on the view detail page
Bonus. Use both! (the only way to go for paranoid people like me)

Let’s discuss the basic concepts of each of the options.

AccessReferenceMap

The AccessReferenceMap is an interface for a map which has methods that allow you to add a “direct” reference (which generates an “indirect” reference), then retrieve an indirect reference using a direct reference, or retrieve a direct reference using an indirect reference.

Confused yet? Me too. Actually it’s quite simple. Let’s use a contrived (and insecure) example just to illustrate the concept (again, this simplified version is NOT secure).

Let’s say you have a table in the database with 4 records, and their id’s are 1,2,3,4. Now let’s say you have the situation above where you display all these records in a master table, and each row is a link to more detail about the individual record. Let’s say you want to hide these numbers and reference them on the UI as letters instead. The simple mapping would be 1=A, 2=B, etc… In this case, when you retrieve the data from the database, your ids are 1,2,3,4. However, when you show them on the screen, their ids are A,B,C,D. Finally from the detail page (after the user clicks the link), you would just lookup what C matches, find that it is 3, then retrieve that record from the DB and display it. It’s that simple.

Now, in practice, obviously a letter -> number matrix is too simple to be effective. What works better, as usual in computer science, is randomness. That’s why ESAPI already contains a class called RandomAccessReferenceMap. Here’s an example of how you might use it.


MyObject obj;	 	// generate your object
Collection coll; 	// holds objects for display in UI

//create ESAPI random access reference map
AccessReferenceMap map = new RandomAccessReferenceMap();

//get indirect reference using direct reference as seed input
String indirectReference = map.addDirectReference(obj.getId());

//set indirect reference for each object - requires your app object to have this method
obj.setIndirectReference(indirectReference);

//add object to display collection
coll.add(obj);

//store collection in request/session and forward to UI
...

As you can see the code is fairly simple. Beyond this, the only other code is when it is displayed on screen, you use the indirect reference to be the id that gets you to the view detail page. From the view detail page, you retrieve the id that was passed in, then iterate over the collection in memory until you find the object from the map matching the indirect reference and then retrieve the full data from the DB by mapping back to the original ID.

A couple notes here:
- If you get an id passed in that doesn’t match any in your collection, it means either the code is wrong, or the user has tampered with it, so it should be a security issue
- You’ll note my object has a method called setIndirectReference. All my value objects in my applications extend a base class with some helper methods, and this is one of them. This is obviously not required and there are many ways to accomplish the usage of the RandomAccessReferenceMap, but I build my apps knowing I’m going to use this technique, so it’s not a problem for me.

Per-Page Authorization

Per page authorization is another technique that has a similar goal to the AccessReferenceMap. The idea here is that you’ve already done the appropriate authorization on the master page. Again, for simplicity, let’s use the bank account example. Let’s say you have a checking and savings account with a particular bank, and both of those accounts show up on your “master” accounts page. The code has to check what you have access to (authorization) in order to only display the appropriate 2 accounts to you on that page.

Unfortunately, that’s where many applications stop. They assume since they’ve only given you 2 accounts to choose from, you’ll have to choose 1 of the 2. This doesn’t take tampering into account, however, and tampering can allow the attacker to input any account they choose.

What the per-page authorization says is that if and when the attacker tampers with the data sent to the detail page, it still shouldn’t be possible for him to see data that is not his. The code that brings up detail about a specific account should first include a check that you have access to that account (authorization). Again, if he doesn’t have access to that account, either the code is broken, or he is tampering and that is a security incident.

So, which option should I choose

Well, either or both. They are both viable options to solve the DOR problem, but I’ll try to give a couple of points about both that may sway you one direction or the other.

AccessReferenceMap
1. *May* not require an extra DB hit to do detail page authorization – depends on how you’ve coded it.
2. Shields actual IDs from end user. In case you ever have a vulnerability on another page, and haven’t protected for it properly, the attacker won’t know your IDs.
3. Requires a bit of extra coding and some extra information to pass around the application in order to maintain access to the reference maps.
4. Currently not very popular, so not very well understood yet.

Per-Page Authorization
1. *May* require an extra DB hit to do detail page authorization – depends on how you’ve coded it.
2. Exposes actual IDs from end user. In case you ever have a vulnerability on another page, and haven’t protected for it properly, the attacker could know your IDs.
3. Doesn’t requires extra coding or the passing of information around the application in order to maintain access to the reference maps.
4. Very well understood paradigm.

Well, there you have it. There’s really not that much to it. While direct object access is a significant issue in many of today’s applications, it can be fairly simply corrected. I’ve presented a couple of options that can be done separately or combined together as a solution. I like to use them both, but separately, they still do their job properly.

Just one final safety note. While I’ve only discussed these techniques in the context of database queries, whichever one or both that you choose should additionally be applied when referencing any sensitive internal resources, including files, internal objects, classes, etc.

Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions to improve any of my ideas.

Other articles in this series:
Part 1: The OWASP Top Ten and ESAPI
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Cross Site Scripting (XSS)
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Injection Flaws
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Malicious File Execution

Technorati Tags: , , , , ,

The OWASP Top Ten and ESAPI – Part 4 – Malicious File Execution

No Gravatar

This article will describe how to protect your J2EE application from malicious file execution attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem?

So what exactly is malicious file execution? It could mean different things to different people. Here, I want to limit the discussion to the execution, either immediate or delayed, of files or file handles that can be manipulated in some way by user input. This is a fairly broad definition that can cover a few different situations. Let’s first discuss a few of the different types of issues that can come up. This collection is by no means exhaustive, but should give us decent coverage of the types of issues that arise when dealing with file input.

1. Included file name is partially or wholly determined by dynamic input (think dynamic include files)
2. File is uploaded and written to disk with “as is” (no validation of uploaded file – just write to disk)
3. File name to display or retrieve is partially or wholly determined by dynamic input
4. Command / data file is uploaded (think a batch process being kicked off with data from an uploaded spreadsheet)

So, what types of issues do these particular situations present us with. In general, an attacker can manipulate this process to gain increased privileges, access data for which they are not authorized and even execute code. Since these aren’t the only 4 examples of issues that exist, we won’t specifically delve into each issue in detail, but we’ll try to extract some common problems that are present in one or more of the scenarios listed above. This set of problems is related to common file upload / processing situations.

1. Missing or insufficient input validation – This is almost always true with file processing. This also is a broad topic, since it deals both with the file name and path, as well as the file contents. Many times, this could express itself as uploading a file as is and simply writing it out with a filename that is either the name of the file as uploaded, or a name specified by the user. This could cause issues like directory traversal (“../../etc/passwd” – overwriting the passwd file – sorry for the old cliche example), or overwriting other files in the filesystem (“../../jsps/login.jsp” – overwriting the login page). Something like this could allow the attacker to break the site significantly up to and including owning the site, and even the server it’s hosted on. While most file processing code I’ve seen is not bad enough to allow something like this, some of it is just that bad .. scary.

2. No virus scanning – This goes along with input validation to some extent, but if you are uploading a file that is going to be executed in any way at any time, it should be virus scanned. There are engines out there, even free ones, that you can call out to in order to scan the file. If the scan fails, the file should be deleted, and the incident should be logged as a security incident. At that point, the normal security incident response process in your organization can be executed.

3. No size checks – One of the simplest tasks you can perform that is often overlooked is to check the file size of the uploaded file. There is most likely a reasonable limit to the size of your accepted files. For instance, a spreadsheet would have to have quite a bit of data to be any more than a few MB, but an attacker could upload files of many times more than that to try and fill up the file system, or just hang processing on the server to block out other valid users.

4. Invalid file type processing – This task is a bit more difficult, but makes sense in many cases. If you are an image hosting site, there’s no reason to accept Word files. This should involve creating a whitelist of the types of files you will accept and then verifying that only those are uploaded. This does NOT mean file extension checks. Although these can be used as a superficial first test, they are trivial to change and provide no security assurance. Often times, this check will involve output encoding (see #7).

5. Giving too much control over file name input – This occurs when users are allowed to influence the final filename that is output to the filesystem. This could happen by allowing a user to type in the desired filename or by just accepting their filename and using that on the server side. However, it is much safer to generate the filename that is used to save the file to the filesystem. Generally, this would have some securely random string of characters, as well as the author, date, time, etc. If there is a specific requirement to accept input from the user as to what the filename should be, just ensure that the name given is validated against an acceptable whitelist before writing the file out.

6. Direct object reference (DOR) problems – While the DOR issue affects more than just filenames, it is relevant here so we’ll quickly discuss it. DOR is simply an issue where the actual filename is pointed to directly. This filename could be in a hidden field, stored in a cookie, or some other place that is not directly seen by the user on the screen. Typically the filename is taken directly and used to retrieve or execute the file. This could cause issues of broken authorization (attacker changes filename to access another user’s file), elevation of privileges (touching a file belonging to a user with higher privileges or the system user), or many other problems. This topic is covered in greater detail in the next article in the series.

7. No output encoding – This issue doesn’t always exist since not every filetype can be thought of in this way. The basic issue is when a file is not validated properly before being written out. There are several filetypes that are valid, that could have extra information in them. However, of those, there are some file types which can be read in, and then written out again to ensure the “bad stuff” is not still there. This does not apply to all “bad stuff” that can be contained in those files, nor does it apply to every file type, but it can be useful when the option is available, though it rarely if ever is used in many applications.

8. Not authorizing access – This issue exists because many applications contain reasonably appropriate authentication, but horrible if any authorization. Once a user is authenticated, many times they can perform any function in the application. The classic example of this is not restricting access to a certain page, let’s say the admin screen. The home page might not show the link, but if they type the link into the url bar, there’s nothing stopping them from getting there. Depending on the type of site, this could be especially harmful with file upload. Often times, only “trusted” people are expected to be able to upload files, but if the authorization is broken, it could allow anyone to upload files at will. Again, this depends on the type of site you have – it may be perfectly fine for everyone to upload files (like flickr or youtube).

Where do we go from here? ….

So, we’ve discussed lots of issues that can crop up when dealing with uploading files, so how does ESAPI and general best practices say we should deal with these issues? Let’s take them one by one.

1. Missing or insufficient input validation – As discussed in part 2 of this series, ESAPI makes it fairly simple to do proper input validation through the framework. The code is very simple, and extensible through the addition of new regular expressions. Here is an example of how ESAPI checks the filename of the uploaded file to verify that it is valid.


if (!ESAPI.validator().isValidFileName("upload", filename, allowedExtensions, false)) {
	throw new ValidationUploadException("Upload only simple filenames with the following extensions " + allowedExtensions, "Upload failed isValidFileName check");

}

2. No virus scanning – ESAPI does not directly support virus scanning through the base APIs, but several of the antivirus vendors support API access for Java. I’ve heard that there are also free AV tools that offer this feature as well.

3. No size checks – There is no built in support for this in ESAPI. However, several of the web frameworks do provide support for this. Additionally, most if not all file upload libraries also provide support for this. Lastly, it’s trivial to perform your own check even if your specific library does not support it directly. Just load the uploaded file into a file object and call the length() method on it to determine the size of the file in bytes. Here is what ESAPI uses to prevent large files. The following is a snippet:


ServletFileUpload upload = new ServletFileUpload(factory);

upload.setSizeMax(maxBytes);

4. Invalid file type processing – This task is supported by the input validation portion of ESAPI again. First, the filename could be validated by the application. Then, each input from the file that is processed could again be validated by the application. Think of processing a spreadsheet. The filename should first be tested, then not only each line, but each cell should be checked for validity before being used by the application.

5. Giving too much control over file name input – In order to at least partially solve this issue, ESAPI has the SafeFile object. This is a trivial extension to the java.io.File object that additionally performs checks of the file and directory names to check for unsafe characters. However, this is a blacklist check. It is likely that you could do a better job if you know what characters are allowed in your filenames and only allow those (whitelist), though the characters in the ESAPI blacklist should minimally be disallowed.

6. Direct object reference (DOR) problems – Again, this will be covered in greater detail in the next article, but here I will just mention that ESAPI does have a mechanism to hide DORs. This involves essentially creating a map of direct -> indirect references and then using the indirect references for display, then mapping back during the processing. Come back for the next article for more details on how this is actually done in code.

7. No output encoding – There is no built in support for this in ESAPI. However, there are ways of doing this that *may* work for different filetypes. The most obvious one is images. If an image is uploaded, you can open the file, load the contents into an image object, then save that object. This guarantees that the image is a valid object. Otherwise, loading the image will fail. (Note: this is the expected behavior, though there have been some defects that may cause this not to work – ensure your library version functions correctly here). It may also be possible to do this with the help of some 3rd party libraries depending on the file type you are processing.

8. Not authorizing access – ESAPI does have authorization coverage in the framework, but it deserves its’ own discussion. Actually, the last article in this series will cover restricting URL access which will discuss the authorization capabilities of ESAPI. Additionally, CSRF (Cross Site Request Forgery) protections can help deal with this issue as well, and this is also going to be covered in a later article in the series.

I’d like to mention a couple of other helpful things that are more systems management related when dealing with uploaded files.

- Use a safe base directory when saving your uploaded files that is outside the standard web directory that your site is served from. This will force your application to be the only thing that can access these files. That way, an attacker can’t drop a file in an accessible directory.

- Use the file-system access controls that are offered in your operating system and possibly your web/application server. Ensure that only the appropriate users have privileges and that they have the least privilege necessary to do their jobs. This is a necessary stopgap in case your other protections fail.

- Audit properly. This can’t be stressed enough. If you audit and log properly, and then *READ* those logs, then you can notice when strange behavior occurs. This can help you locate things that need to be resolved.

Hopefully this article has been useful in helping you recognize the types of issues related to file upload and some best practices for dealing with those. As in all the other articles, I recommend trying to be as safe as possible, and only having your app do what is necessary. If you don’t need to upload files, don’t do it. If you have to do it, spend time making sure it’s as safe as you can make it. Let me know if you have other suggestions or best practices you use with file upload.

Editorial Note: I realize it’s been quite a while since I posted any articles in this series. However, I plan to finish up the series in the next few months by posting an article every week or two now that I can spend a bit more time on it. I also realize that in the gap of time I had off, the new OWASP Top Ten (2010) has been released and it supercedes the 2007 list. However, all the issues in the 2007 list either still exist in the 2010 list, are covered by it, or are still issues that may not make that high of a ranking anymore, but are still important. For these reasons, and the fact that I’d already started using the 2007 list, I’ll finish up with the 2007 list. I may go back at the end and catch any new ones from the 2010 list if relevant.

Other articles in this series:
Part 1: The OWASP Top Ten and ESAPI
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Cross Site Scripting (XSS)
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Injection Flaws

Technorati Tags: , , , , , ,

The OWASP Top Ten and ESAPI – Part 3 – Injection Flaws

No Gravatar

This article will describe how to protect your J2EE application from injection (SQL and others) attacks using ESAPI. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.

What’s the problem

Now to discuss injection. Again, let’s begin the the definition of injection from OWASP:
“Injection flaws, particularly SQL injection, are common in web applications. Injection occurs when user-supplied data is sent to an interpreter as part of a command or query. The attacker’s hostile data tricks the interpreter into executing unintended commands or changing data.”

Here I should make a quick note about “input”. While the vast majority of attacks are usually due to malicious user-supplied input, often directly through the browser, this is not necessary for the attack to work. Dangerous (whether malicious or not) could come from a variety of sources, like the filesystem, or the database, or even other applications. The rule is, if you take in input, always understand it could be dangerous. OK, back to injection …

If you look at injection alongside XSS, you’ll notice that they are very similar types of vulnerabilities in spirit. Consider this working definition: “The application takes in input and without proper data validation or encoding, outputs that data to a destination where certain values or entities have special meaning”. This could be describing XSS or Injection. In the case of XSS, our output destination (we’ll use OWASP’s “interpreter” term from here on out) happens to be a browser. For injection, it could be a database, LDAP server, operating system or any other number of interpreters. Each of the interpreters has its’ own semantics and processing rules for what it understands and what symbols and characters have semantic meaning as input.

For the browser, for instance, the bold tag has semantic meaning, which results in making certain text bold-faced.

<b>bold-faced</b>

As for a SQL compliant database, the keyword SELECT has semantic meaning in that it performs a read of some portion of the database.


SELECT first_name, last_name FROM employees;

As we saw previously in the XSS article, it is possible for a user to insert (inject) data that will cause issues if the input is not properly validated and/or encoded (my strong suggestion is to do both). The same thing is true with injection attacks. If the input is not valid for the interpreter, or more specifically contains some commands that will be processed by the given interpreter, then the user can cause the interpreter to perform functions on the user’s behalf that were not intended to be allowed by the application.

Let’s take a classic SQL injection attack as an example to clarify the issue. Here’s some simple Java code creating a SQL string to perform an authentication check so that a user can login. Let’s assume the Java code gets the results back and tests to see if there are any results, and if so, allows the user to be authenticated.


String sqlString = "SELECT * FROM users WHERE fullname = '"
    + form.getFullName() + "' AND password = '" + form.getPassword() + "'";

So, let’s assume the user is presented with a simple login screen, and let’s also assume the user is benevolent. The user might enter something like John Melton for the username and 123pass for the password. That would create the following SQL string to be executed against the database after it is processed by Java (ie. this is what you would see as the SQL string if you watched it through the debugger, or printed it out after the values have been populated at runtime).


SELECT * FROM users WHERE username = 'John Melton' AND password = '123pass'

OK, so far, everything is great right? Sure, for those specific inputs no problem. Now, to pay homage to a good friend of mine, I’ll include his oft-quoted refrain – “The web wasn’t made for Irishmen”.

Let me explain that. For those who are unaware, many Irishmen have names like O’Brien or O’Connor. Note the apostrophe in the last name. Now, let’s show what the SQL string looks like after being processed now.


SELECT * FROM users WHERE username = 'Paul O'Malley' AND password = '789pass'

Are we still good? Nope, this time, we’re not so lucky. What will happen here is a SQLException will be thrown because the SQL cannot be processed by the database interpreter. The issue is in the extra apostrophe in the name. The apostrophe is used in SQL, among other reasons, to open and close a string representation. So, what the SQL interpreter sees in this case is that the username string is populated with Paul O and then closed, and the actual SQL string starts again, only <b> is not valid SQL syntax, so processing stops and an exception is thrown.

(Note: I’m using interpreter generically. In the cases I’m describing, it actually would get booted by the parser, but that’s quibbling :>. )

All right, now that we’ve covered the basic “it works” case and also seen there is a way to break it, how can we break it to our advantage if we wanted to attack the site? Let’s say an attacker sends these two crafted inputs.


Full Name: blah blah
Password: ' OR '1' = '1

Update: modified code above according to Ben’s comment below.

Now that’s a funny looking string to be entered in the password field – let’s see what the SQL string produced looks like.


SELECT * FROM users WHERE username = 'blah blah' AND password = ' ' OR '1' = '1'

What the above SQL actually does is returns all records from the users table that use the given username and password OR where 1 = 1, which is … EVERY RECORD!!!. This grants the attacker access to the application as an authenticated user. This was an actual issue in a real (fairly well-known at the time) web application many years ago. It would check the results that were returned and take the first one as the user to log in. In the case where they were being attacked and all records were returned, it took the first result, which like most other systems first user, was the admin account! Most decent sites have closed this issue on the login screen thankfully, but it is a very prevalent issue in systems across the world.

The above is a simple example of what can happen with SQL injection. The vast majority of reported issues with injection have to do with SQL injection. The others are not as popular, probably because they’re less common types of systems (b/c almost every app uses a DB) and SQL injection is so easy and prevalent, there’s no real driver for attackers to do anything else. Additionally, most of the sensitive data is likely stored in the DB anyhow, so we might as well attack it directly if possible.

Where do we go from here? ….

So, now that we see the problem, how do we fix it? Well there are essentially 2 reasonably reliable techniques as I see it. The first option has to do with using PreparedStatements with bound parameters, and the second option uses the ESAPI framework.

Update: From Jeff’s (the chair of OWASP) comment below, it should be clear that PreparedStatements and the ESAPI output encoding mechanisms are not mutually exclusive. They can be complementary and used together for increased assurance. It is a task left up to the development organization securing their app to make a decision over which option (or both) to choose. As with most choices, each option (PS, ESAPI, or both) has its’ advantages and disadvantages.

Note: with either technique, white-list input validation should be used since it’s relatively easy to do, and helps avoid so many types of problems. Additionally, standard security measures like least privilege for the user account connecting to the DB for your application should also be utilized.

Before getting into the detail of the 2 options, I want to point out that the ESAPI folks have put together another article called the SQL Injection Prevention Cheat Sheet and it is a great resource about this topic, specifically SQL injection.

PreparedStatements (with bound parameters)
——————
Those familiar with DB programming in java will recognize the 3 statement types in Java: Statement, PreparedStatement and CallableStatement. These 3 types represent varying levels of security. The standard Statement class is not a good idea – there are no security measures built-in and you are on your own if you try and use this class. As for the CallableStatement, it is used with stored procedures and functions. *Typically* stored procs are secure. However, it is very possible to make them insecure by not validating the input properly or even constructing dynamic sql within the procedure for execution. Finally, there is the PreparedStatement. When used properly (with a safe driver and bound variables), these are typically viewed as the most secure option.

There are 2 important things to remember about PreparedStatements when it comes to security.
1. SQL executed with PreparedStatements is only as safe as the drivers that implement the classes. The actual runtime class that implements the PreparedStatement interface is part of a 3rd party package. There are some out there that are generally thought to be safe, and some that aren’t. The most popular ones expectedly tend to be more respected (not necessarily earned, but true nonetheless). The only suggestion I can give here is that you can look at the code of popular open source drivers yourself and make up your mind about their safety. If you use a commercial driver, understand the support structure in case there is a security issue that must be resolved.
2. The code leveraging the PreparedStatements must use them properly. This involves the use of strongly typed bound parameters. This means that if you concatenate your SQL string together using dynamic input, the PreparedStatement does you no good. The safety comes into play when using the setXXX methods on the PreparedStatement class. The snippet below shows how to properly use dynamic input (which should already be validated) as input to the SQL string by doing parameter substitution. The setInt method below (if the driver is coded properly) should be DB specific and will escape any necessary characters for that DB to prevent breaking out of the interpreter and allowing the user to specify code that will be run by the DB.


myPrepStmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?");
myPrepStmt.setInt(1, validatedUserId);
...
//execute statement and get results

and a query with multiple input parameters looks very similar …


myPrepStmt = conn.prepareStatement
    ("SELECT name FROM users WHERE id = ? AND date_created >= ?");
myPrepStmt.setInt(1, validatedUserId);		//first param
myPrepStmt.setDate(2, validatedStartDate);	//second param
...
//execute statement and get results

As you can see, using the PreparedStatement can solve this issue, but only when used properly. One very important thing to note here is about ORM frameworks. Most of these frameworks *can* be used securely, but you have to know what you’re doing. Hibernate, for instance, can be used securely or insecurely depending on which classes you choose. Be sure to do your homework, read solid tutorials, pick good frameworks, and above all understand what you’re using when you let a framework do some of the work for you. OK, now on to our other option …

ESAPI
——————
ESAPI takes a similar approach to solving this issue, but the code will look slightly different. The approach is very simple, and boils down to escaping/encoding all dynamic input to the SQL statement using an appropriate encoder. For this section of the article, I relied heavily on the ESAPI section of the SQL Injection Prevention Cheat Sheet at OWASP, so it’s a worthwhile time to go read it if you haven’t already. Let’s look at one quick example to show how it works. We’ll modify the second query above to use ESAPI instead of PreparedStatements.


//ESAPI version of query
Codec ORACLE_CODEC = new OracleCodec();		//we're using oracle
String query = "SELECT name FROM users WHERE id = " +
   ESAPI.encoder().encodeForSQL( ORACLE_CODEC, validatedUserId)
   + " AND date_created >= '"
   + ESAPI.encoder().encodeForSQL( ORACLE_CODEC, validatedStartDate) +"'";
myStmt = conn.createStatement(query);
...
//execute statement and get results

As you can see above, all that we did was encoded the input data (already validated) for SQL by using the OracleCodec, since we are using the Oracle database for our application. This has some obvious drawbacks if you are using multiple databases, and can use the ORM features of cross-database query generation, but that is rare for many apps. Most applications know the 1 database they are going to be running on, and I would argue that’s a good thing from a security perspective because then you can better understand the security ins and outs of that one DB.

Looking at the code, it’s fairly simple to encode most anything – you just have to be diligent to do so. As for the other types of injection, you may have to get your hands dirty and write an encoder for your specific application, or you may not. You’ll just have to check what the ESAPI team has already done. Additionally, it might be possible to get on the mailing list and request a new codec. Certainly, if you have any that you’ve written, I’m sure the dev team would love to at least see them, and possibly include them – you could be helping others out!.

Clearly, using the ESAPI framework, it’s possible to safely and securely prevent injection from the DB as well as other types of interpreters if you use the framework properly.

In summary, I’ll say that while I think either of these techniques work from a purely technical perspective, there are a couple of things you should consider before implementing protection. First, PreparedStatements are far more prevalent in industry. They are a solid solution to the SQL injection problem, and are widely understood and available. They’ve also been very widely tested both for performance and security. Essentially, they are a known entity. However, they do not solve any of the other types of injection. The equivalent to PreparedStatements do not exist for XML or XPath injection or others. You’d have to handle them differently. As for ESAPI, it will also work well, and has been tested for security and performance, but not nearly as much. Additionally, it does not have the industry reach that PreparedStatements do. However, ESAPI has a solution for the other types of injection as well, and a clear model for implementing new encoding mechanisms for new interpreter types. You can even write your own custom encoders if you choose. No matter which you choose (or both), my hope is that you’ve seen there is a need to be responsible and protect resources from injection. These solutions make it fairly trivial to implement solid protection for applications against injection.

Other articles in this series:
Part 1: The OWASP Top Ten and ESAPI
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Cross Site Scripting (XSS)

Update: Added inline comments referencing changes made regarding Jeff and Ben’s comments below.

Technorati Tags: , , , , , , , ,

A Simple Spring AOP Tutorial

No Gravatar

The Spring framework supports AOP very elegantly. Though it does not offer some of the features that AspectJ offers, it also is typically a simpler configuration to get going. This post is just an example of doing a very simple task (logging), a “cross-cutting concern” in AOP lingo, using the Spring framework.

This example will exist of a class with a main method, a business logic interface / class combo, an Advice (Spring’s way of encoding the AOP logic), and the associated Spring configuration file that ties everything together.

This example does not go into great detail about how Spring’s AOP mechanism works, but there is plenty of information in the Spring documentation about that. It simply uses the Java proxy mechanism. Also, I don’t go into all of the options for how you can configure AOP in Spring, though there are several. I only focus on the most recent recommendations.

Having said all of that … here we go.

First for the business logic interface / class:


package com.jtm.aop;

public interface SomeIntf {

	public void updateMe1();
}

package com.jtm.aop;

import org.apache.log4j.Logger;

public class MyClass1 implements SomeIntf {
	Logger log = Logger.getLogger(this.getClass());

	public void updateMe1() {
		log.info("in updateMe1");
	}
}

This was obviously a very simple class that just writes a log statement. Now onto the Advice mechanism:


package com.jtm.aop;

import java.lang.reflect.Method;

import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class PerformanceLoggingAdvice implements
	MethodBeforeAdvice,
	AfterReturningAdvice {

	/** Time in milliseconds */
	long startTime = 0;

	/** Time in milliseconds */
	long finishTime = 0;

	protected static final Logger log =
		Logger.getLogger(PerformanceLoggingAdvice.class);

	public void before(Method method, Object[] args,
			Object target) throws Throwable {
		startTime = System.currentTimeMillis();
		log.debug("Executing method " + method.getName()
			+ " on object " + target.getClass().getName());
	}

	public void afterReturning(Object returnValue,
			Method method, Object[] args, Object target) throws Throwable {
		finishTime = System.currentTimeMillis();
		double totalDuration = finishTime - startTime;
		log.debug("Finished executing method " + method.getName()
			+ " on object " + target.getClass().getName() + " in "
			+ totalDuration / 1000 + " seconds.");
	}

}

This class is doing a bit more. This class implements the Spring framework’s before and after advice interfaces. This allows the Spring framework to call these methods before and after the methods in the application where they are configured to do so by the Spring config file.

Now let’s see the main driver class:


package com.jtm.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class RunAll {
	public static void main(String[] args) {
		SomeIntf myClass1;

		ApplicationContext appContext =
			new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"});

		myClass1 = (SomeIntf) appContext.getBean("myClass1");

		myClass1.updateMe1();
	}

}

As you can see, this class simply loads Spring, locates the bean, and calls the update method.

Now on to the magic, the Spring config file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

	">

	<bean id="myClass1" class="com.jtm.aop.MyClass1" />

	<bean id="performanceLoggingAdvice"
		class="com.jtm.aop.PerformanceLoggingAdvice" />

	<aop:config>
		<!-- Performance logging pointcut -
			run for every method in a control or facade class -->
		<aop:pointcut id="performanceLoggingPointcut"
			expression="execution(* com.jtm..*.update*(..))" />

       		<aop:advisor
           		advice-ref="performanceLoggingAdvice"
            		pointcut-ref="performanceLoggingPointcut"
            		id="performanceLoggingInterceptorAdvisor"  />

	</aop:config>
</beans>

As you can see, there is more going on here than in the other sections. Let’s break this down.

1. The business logic and Advice classes are configured as standard beans
2. The aop namespace for Spring 2.5 is loaded at the top of the file
3. All of the AOP configuration is located within an aop:config tag
4. First we configure the pointcut, which is a regular-expression like description of when the performance logging code should be run. In this case, we have configured it to run on any class in any subpackage of the com.jtm package and on any method that starts with “update” and that takes any kind of parameters.
5. Next we configure the advisor, which combines the advice class with the pointcut.
6. Finally Spring looks at the code are runtime and auto-proxies the classes that need to be so that the AOP code can be applied at run-time.

That’s it! This is a quick run-through. If you have any further questions, feel free to post here or search for more tutorials online. Also, check out the Spring documentation for further information.

Hope this helps.
-jtm

A Simple Multi-Threaded Java HTTP Proxy Server

No Gravatar

This post is to show an example of a simple multi-threaded Java HTTP Proxy Server. This sample is not fully functional for every application. It’s very simple and works fine for HTTP GET requests, but is not coded to properly handle HTTP POST requests (nor any other HTTP methods). This is strictly as an example to show how simple it is to proxy requests. This one simply records the url of all requests that are passed through it. Please let me know if you have any questions, and feel free to steal it and improve on it. Let me know what you come up with.

This first bit of code is the actual multithreaded server. It simply starts up the proxy server on a given port, takes in an HTTP request, and spawns off the request to a new thread passing the socket to the thread, and starts that thread on the request.


package proxy;

import java.net.*;
import java.io.*;

public class ProxyServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        boolean listening = true;

        int port = 10000;	//default
        try {
            port = Integer.parseInt(args[0]);
        } catch (Exception e) {
            //ignore me
        }

        try {
            serverSocket = new ServerSocket(port);
            System.out.println("Started on: " + port);
        } catch (IOException e) {
            System.err.println("Could not listen on port: " + args[0]);
            System.exit(-1);
        }

        while (listening) {
            new ProxyThread(serverSocket.accept()).start();
        }
        serverSocket.close();
    }
}


This is the real meat of the application. However, it’s still a fairly simple class. It’s a thread that starts up, then receives the incoming request from the client, resends the request to the real server that the client intended to send it to (while logging the request), then receives the response from the real server, and propogates that same response to the client. Fairly simple process.


package proxy;

import java.net.*;
import java.io.*;
import java.util.*;

public class ProxyThread extends Thread {
    private Socket socket = null;
    private static final int BUFFER_SIZE = 32768;
    public ProxyThread(Socket socket) {
        super("ProxyThread");
        this.socket = socket;
    }

    public void run() {
        //get input from user
        //send request to server
        //get response from server
        //send response to user

        try {
            DataOutputStream out =
		new DataOutputStream(socket.getOutputStream());
            BufferedReader in = new BufferedReader(
		new InputStreamReader(socket.getInputStream()));

            String inputLine, outputLine;
            int cnt = 0;
            String urlToCall = "";
            ///////////////////////////////////
            //begin get request from client
            while ((inputLine = in.readLine()) != null) {
                try {
                    StringTokenizer tok = new StringTokenizer(inputLine);
                    tok.nextToken();
                } catch (Exception e) {
                    break;
                }
                //parse the first line of the request to find the url
                if (cnt == 0) {
                    String[] tokens = inputLine.split(" ");
                    urlToCall = tokens[1];
                    //can redirect this to output log
                    System.out.println("Request for : " + urlToCall);
                }

                cnt++;
            }
            //end get request from client
            ///////////////////////////////////

            BufferedReader rd = null;
            try {
                //System.out.println("sending request
		//to real server for url: "
                //        + urlToCall);
                ///////////////////////////////////
                //begin send request to server, get response from server
                URL url = new URL(urlToCall);
                URLConnection conn = url.openConnection();
                conn.setDoInput(true);
                //not doing HTTP posts
                conn.setDoOutput(false);
                //System.out.println("Type is: "
			//+ conn.getContentType());
                //System.out.println("content length: "
			//+ conn.getContentLength());
                //System.out.println("allowed user interaction: "
			//+ conn.getAllowUserInteraction());
                //System.out.println("content encoding: "
			//+ conn.getContentEncoding());
                //System.out.println("content type: "
			//+ conn.getContentType());

                // Get the response
                InputStream is = null;
                HttpURLConnection huc = (HttpURLConnection)conn;
                if (conn.getContentLength() > 0) {
                    try {
                        is = conn.getInputStream();
                        rd = new BufferedReader(new InputStreamReader(is));
                    } catch (IOException ioe) {
                        System.out.println(
				"********* IO EXCEPTION **********: " + ioe);
                    }
                }
                //end send request to server, get response from server
                ///////////////////////////////////

                ///////////////////////////////////
                //begin send response to client
                byte by[] = new byte[ BUFFER_SIZE ];
                int index = is.read( by, 0, BUFFER_SIZE );
                while ( index != -1 )
                {
                  out.write( by, 0, index );
                  index = is.read( by, 0, BUFFER_SIZE );
                }
                out.flush();

                //end send response to client
                ///////////////////////////////////
            } catch (Exception e) {
                //can redirect this to error log
                System.err.println("Encountered exception: " + e);
                //encountered error - just send nothing back, so
                //processing can continue
                out.writeBytes("");
            }

            //close out all resources
            if (rd != null) {
                rd.close();
            }
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }
            if (socket != null) {
                socket.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Hope you enjoy and learn a little from how simple it is in Java to perform network requests, as well as multi-threading to create a somewhat useful application that can be easily extended to be much more useful. Hope this helps.

A session size monitoring servlet

No Gravatar

This is a quick example of a servlet that will tell you the size of your session. This is helpful if you don’t have the tools built into your development suite to give you this information. I found this laying around that I had written a while back. It essentially is a simple servlet that grabs all the session attributes and writes out each to a ObjectOutputStream object. It then takes the size of the ByteArrayOutputStream object contained in the ObjectOutputStream object and displays that.


public class HttpSessionSizeServlet extends HttpServlet {
    private static Logger log = LogFactory.
	getLogger(HttpSessionSizeServlet.class);
    public void doGet(HttpServletRequest req,
		HttpServletResponse resp)
		throws ServletException, IOException {
        HttpSession session = req.getSession();
        if (session != null) {
            Enumeration e = session.getAttributeNames();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream s = new ObjectOutputStream(bos);

            while (e.hasMoreElements()) {
                Object o = session.getAttribute((String) e.nextElement());
                s.writeObject(o);
                s.flush();
            }
            log.info("size = " + bos.size());
        }
    }

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, IOException {
        //do nothing
    }
}

Hope this helps.

Writing a custom generic exception handler in Struts

No Gravatar

Exception handling in Struts is a very simple concept to grasp, once you know the tool that Struts has put in place to handle it. This tool is the org.apache.struts.action.ExceptionHandler . The ExceptionHandler mechanism allows you to configure it in the struts-config.xml file and then Struts will automagically pass any exception type it’s configured to handle to it at runtime. Here’s a simple example of how easy it is to create one of these classes .


package myapp.exc;

import org.apache.struts.action.ExceptionHandler;
//other struts imports

public class MyExceptionHandler extends ExceptionHandler {
  public ActionForward execute( Exception ex,
                              ExceptionConfig exConfig,
                              ActionMapping mapping,
                              ActionForm formInstance,
                              HttpServletRequest request,
                              HttpServletResponse response
  ) throws ServletException {
    //send email to support that something happened w/ stack trace included
    //print stack trace to logs
    ex.printStackTrace();
    return mapping.findForward("login");
  }
}

This method takes in several parameters (including the request/response objects) and returns the forward to where you want to take the user. After setting your class up, all you’ve got to do now is configure it in the struts-config.xml file. You add it to the global-exceptions section. Here’s an example of how to do that for 2 different handlers for 2 different types of exceptions.


<global-exceptions>
  <exception
    handler="myapp.exc.MyExceptionHandler"
    key="standard.error.message"
    path="/genericError.jsp"
    scope="request"
    type="myapp.exc.MyException"/>

  <exception
    handler="myapp.exc.AuthorizationExceptionHandler"
    key="unauthorized.error.message"
    path="/auth.jsp"
    scope="request"
    type="myapp.exc.AuthorizationException"/>
</global-exceptions>

As you can see, you can easily use what Struts has provided to setup a flexible declarative exception handling model for your application.

Hope this helps.

Writing a custom role based access control framework that integrates with Struts

No Gravatar

This article will tell you a fairly simple way to put a custom access control framework in place for your J2EE application that will let you integrate it with the struts framework role based access control protection mechanisms. There are a few pieces to this solution:
1. A storage mechanism for the accesses (roles) per user
2. Writing these accesses into the HttpSession per user (generally in the form of an easily accessible object with helper functions on the session)
3. Override the processRoles method of the struts RequestProcessor class in order to recognize your custom roles
4. Add roles=”…” to your struts actions to protect them based on the configured roles

Ok, in order then, here we go.

For #1 – this is usually done via a relational database – whatever application database you’re using, you’ll generally store the accesses for a given user. However, you could store these in flat files, ldap, or some other mechanism if you wanted to – that’s up to you.

For #2 – here’s an object you can use to hold the roles.


public class UserAccesses {
    private String userName;
    private String[] roles;

    public UserAccesses(String userName, String[] roles) {
        this.userName = userName;
        this.roles = roles;
    }

    public boolean hasRole(String role) {
        if (roles.length > 0) {
            for (int i = 0; i < roles.length; i++) {
                if (role.equals(roles[i]))
                    return true;
            }
        }
        return false;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer(1024);
        sb.append(userName);
        sb.append(" has roles: ");
        for(int i=0; i

This object stores a string array of the role names per user. Now here's some code to write this object into the session. This code should be called when the user logs into the application.


    List allAccessesList = new ArrayList();
    //if the user has the write stories access from the db
    allAccessesList.add(Constants.WRITE_STORIES);
    //if the user has the read stories access from the db
    allAccessesList.add(Constants.READ_STORIES);
    //if the user has the delete stories access from the db
    allAccessesList.add(Constants.DELETE_STORIES);

    String[] allUserAccesses =
	(String[])allAccessesList.toArray(new String[0]);
    UserAccesses userAccessesObj =
	new UserAccesses (userId, allUserAccesses);
    HttpSession session = request.getSession();
    session.setAttribute(Constants.USER_SESSION_ACCESSES, userAccessesObj);

On to #3 - here you have to write a custom class that overrides the processRoles method of the RequestProcessor class in struts


public class RolesRequestProcessor extends RequestProcessor {
    private static final Logger log =
	LogFactory.getLog(RolesRequestProcessor.class);
    public RolesRequestProcessor() {
        super();
    }

    /**
     * @see org.apache.struts.action.RequestProcessor
     *		#processRoles(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse,
     *      org.apache.struts.action.ActionMapping)
     */
    protected boolean processRoles(HttpServletRequest request,
		HttpServletResponse response, ActionMapping mapping)
        	throws IOException, ServletException {

        //Obtain the list of roles from action config
        String roles[] = mapping.getRoleNames();
        if ((roles == null) || (roles.length < 1)) {
            log.debug("No role is required for running this operation.");
            return (true);
        }
        //verify user possesses role
        StringBuffer sb =
		new StringBuffer("Check for required roles ....... n");

        //checking in ldap roles
        for (int i = 0; i < roles.length; i++) {
            sb.append(roles[i]);
            sb.append(", ");

            if (request.isUserInRole(roles[i])) {
                sb.append("Found a matching role in the ldap roles: " + roles[i]);
                return (true);
            }
        }

        // checking in custom database roles
        // Check the current user against the list of required roles
        HttpSession session = request.getSession();
        UserAccesses userAccessesObj = (UserAccesses )
        	session.getAttribute(Constants.USER_SESSION_ACCESSES);
        if (userAccessesObj == null) {
            return false;
        }
        for (int i = 0; i < roles.length; i++) {
            if (userAccessesObj .hasRole(roles[i])) {
                sb.append("Found a matching role in the custom roles: " + roles[i]);
                return (true);
            }
        }
        //end custom roles check

        //invoke declarative exception handling
        sb.append("n");
        sb.append("User does not have the required role");
        log.debug(sb.toString() + " ");
        ActionForward forward = null;
        try {
            forward = processException(request, response,
                new my.application.AuthorizationViolationException(),
		null, mapping);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        // forward user to the authorization error page...
        if (forward != null) {
            log.info("Forward to authorization error page");
            processForwardConfig(request, response, forward);
        }
        return (false);
    }
}

Finally #4 - here you just add the roles attribute to your struts configuration in order to get struts to check for the specified role(s) (multiple roles, is just a comma-delimeted group) to allow a user to perform a given action.


    <action path="/myApplication/deleteStory"
		type="my.actions.DeleteStoryAction" roles="DELETE_STORIES,ADMIN">
        <forward name="deleteSuccess" path="/myApplication/deleteSuccess.do" />
    </action>

This process has worked very well on my projects, and hopefully will on yours as well.

Hope this helps.

Transactions With Spring in Java

No Gravatar

This post will show you how to write the code to perform transaction handling in Java using the Spring framework. There are certainly many varied ways to handle this, but this is one that I’ve found works fairly well and tends to lead to a fairly clean code base.
The code below essentially forces the block of code all to occur within a transaction, and either causes the transaction to go through with a commit (assuming everything went well), or rolls it all back if anything failed. In this particular case, there are multiple stored procedures being called that all need to pass for the entire process to be valid. It’s true that this could all be handled in one procedure, but that could make the parameters very ugly. In this situation, I think it’s better to have multiple procedures called within one transaction in the java code.


public boolean saveUser(User user){
	boolean success = false;

	DefaultTransactionDefinition def = new DefaultTransactionDefinition();
	def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

	TransactionStatus status = transactionManager.getTransaction(def);
	Map results = null;

	try{
		LinkedHashMap inputTypesMap = new LinkedHashMap();
		inputTypesMap.put(Constants.USER_ID,new Integer(Types.INTEGER));
		inputTypesMap.put(Constants.FIRST_NAME,new Integer(Types.VARCHAR));
		inputTypesMap.put(Constants.LAST_NAME,new Integer(Types.VARCHAR));
		inputTypesMap.put(Constants.PHONE_NUMBER,new Integer(Types.VARCHAR));
		inputTypesMap.put(Constants.EMAIL_ADDRESS,new Integer(Types.VARCHAR));
		LinkedHashMap outputTypesMap = new LinkedHashMap();
		AdminStoredProcedure prc =
			new AdminStoredProcedure(ds,Constants.USER_SAV_PROCEDURE_NAME,
				inputTypesMap,outputTypesMap,null);
		LinkedHashMap inputValuesMap = new LinkedHashMap();
                inputValuesMap.put(Constants.USER_ID, user.getUserId());
		inputValuesMap.put(Constants.FIRST_NAME,contact.getContactFirstName());
		inputValuesMap.put(Constants.LAST_NAME,contact.getContactLastName());
		inputValuesMap.put(Constants.PHONE_NUMBER,contact.getPhoneNumber());
		inputValuesMap.put(Constants.EMAIL_ADDRESS,contact.getEmailAddress());

		results = prc.execute(inputValuesMap);

		//another procedure call, hence the need for the transaction
		userService.deleteUserGroupAssociation(user.getUserId());
		int[] contactGroups = user.getContactGroups();
		for(int i=0; i

Hope this helps.

Using ResourceBundles to handle messages in Java – ApplicationResources.properties

No Gravatar

Java has a couple of concepts that are used as best practices in web applications that can be very useful even if you don’t intend to use them for their strict purpose. The first is a properties file and the second is internationalization (i18n – 18 letters between the i and the n).
Properties files are simple key=value files. They contain records that are in this format generally:


my.key=My Value

Internationalization is a concept that allows an application to move it’s labels of field names, descriptions, etc. to be encoded in properties files with a specific extension representing the language. These follow the 2-letter ISO 3166 country code extensions. These are very useful in web applications and allow you to extract messages at will using both manual methods as well as tag libraries.

An example of the manual method is shown below:


ResourceBundle messages = ResourceBundle.getBundle("ApplicationResources");
String adminId = messages.getString("adminuserid");
String adminPassword = messages.getString("adminpassword");

This bit of code will extract the value of the adminuserid property from the ApplicationResources.properties file and place it’s value in the adminId field, and the same with the adminPassword field.

An example of using the jstl fmt taglib in order to display a message is shown below:


<fmt:message key="label.userId"/>

This bit of code will extract the value of the label.userId property and render it on the screen.

Hope this helps.

Next Page →