2008-10-20

What do you mean no Java output encoding !!!

I hear all the time that java does not have any good encoding libraries but have used some frameworks that do seem to encode the output properly. If anyone uses the struts framework and implements it properly then all your output is encoded properly if you use the following methods to output data.

 

<bean:write name="secData" property="username"/><br>
    <html:link href="./test.jsp" paramId="test" paramName="secData" paramProperty="username" > <bean:write name="secData" property="username"/></html:link><br>
    <html:hidden name="secData" property="username" /> <br>

The tag libraries bead:write, html:hidden, and html:link will all output either url encoded output for html:link (which creates an anchor tag) and html:hidden or will entity encode your output for bean:write.

 

What if your not using struts you ask?

Well this is great if you are using struts 1 and struts 2 (output tags are different for struts 2) but what you are not or you are writing servlets that generate html dynamically. This is not a problem. I dug a little deeper into struts to see what struts was doing and if there is a way to leverage this for other sites that do not use this framework. The URL encoding is simply URLEncode.encode( your string, your format). Its uses a default java class that has been around since 1.5. Just import java.net.URLEncoder.

 

Example:

String output = URLEncoder.encode("your String" , "UTF-8");

 

Struts 1 is using an entity encoder built specifically into the struts framework. The entity encoding is using a struts class called ResponseUtils. So you could import this class and still not use the struts MVC architecture.

Example:

String output = org.apache.struts.util.ResponseUtils.filter("your string");

 

Struts 2 does entity encoding by using a class TextUtils from WebWork. Import org.opensymphony.xwork2.util.TextUtils

Example:

String output = org.opensymphony.xwork2.util.TextUtils.htmlEncode("your string", true);

 

Proper Encoding with international Chars!!!!

There are other encoding options provided by the apache commons lang library. This is library is probably the most useful. To get it to properly encode international chars to the screen you need to first unescape the html before to escape the html. import org.apache.commons.lang.StringEscapeUtils;

 

Example:

String Output = StringEscapeUtils.escapeHtml(StringEscapeUtils.unescapeHtml(input));

 

Below is an example screenshot of the all above encodings in a simple servlet. Notice that StringEscapeUtils (the last one) will properly encode the xss attempt plus the Chinese  character set. This will solve the problem all you java developers have with output encoding international characters and can quit complaining that there isn't any good encoding options for java. =) My source code is attached here: http://my-security-projects.googlecode.com/files/testEncoding.war 

 

I hope this finally answers everyone's concerns for international character encoding in java. I'll let you all out there in the hacker community see if you can find a way to get past this model. Let me know if you do

 

image

 

Here is the page source:




<html><body>
<h1> Servlet Test </h1>
<br><b>Input String: </b> <script>alert('xss');</script> &#29615;&#29699;&#32463;&#27982;&#19981;&#26223;
&#27668;&#20013;&#22269;&#32463;&#27982;&#22686;&#38271;&#25918;&#32531; &#20013;&#22269;&#32463;&#27982;
&#22312;&#29615;&#29699;&#19981;&#26223;&#27668;&#19979;&#21576;&#29616;&#25918;&#32531;&#24577;&#21183;
&#65292;&#26368;&#26032;&#22269;&#20869;&#29983;&#20135;&#24635;&#20540;&#22686;&#38271;&#20026;9.9%&#65292;
&#36890;&#32960;&#25345;&#32493;&#25918;&#32531;&#12290; &#20013;&#22269;&#20061;&#26376;&#36152;&#26131;
&#30408;&#20313;&#21019;&#32426;&#24405; &#35775;&#35848;&#65306;&#20013;&#22269;&#22806;&#36152;&#21069;
&#26223;&#19981;&#23481;&#20048;&#35266; &#37329;&#34701;&#39118;&#26292;&#65306;&#20013;&#22269;&#38754;
&#20020;&#30340;&#21361;&#26426;&#19982;&#26426;&#36935;
<br>
<b>java.net.URLEncoded: </b>%3Cscript%3Ealert%28%27xss%27%29%3B%3C%2Fscript%3E+++
%26%2329615%3B%26%2329699%3B%26%2332463%3B%26%2327982%3B%26%2319981%3B%26%2326223%3B
%26%2327668%3B%26%2320013%3B%26%2322269%3B%26%2332463%3B%26%2327982%3B%26%2322686%3B
%26%2338271%3B%26%2325918%3B%26%2332531%3B+%26%2320013%3B%26%2322269%3B%26%2332463
%3B%26%2327982%3B%26%2322312%3B%26%2329615%3B%26%2329699%3B%26%2319981%3B%26%2326223
%3B%26%2327668%3B%26%2319979%3B%26%2321576%3B%26%2329616%3B%26%2325918%3B%26%2332531
%3B%26%2324577%3B%26%2321183%3B%26%2365292%3B%26%2326368%3B%26%2326032%3B%26%2322269
%3B%26%2320869%3B%26%2329983%3B%26%2320135%3B%26%2324635%3B%26%2320540%3B%26%2322686
%3B%26%2338271%3B%26%2320026%3B9.9%25%26%2365292%3B%26%2336890%3B%26%2332960%3B%26
%2325345%3B%26%2332493%3B%26%2325918%3B%26%2332531%3B%26%2312290%3B+%26%2320013%3B
%26%2322269%3B%26%2320061%3B%26%2326376%3B%26%2336152%3B%26%2326131%3B%26%2330408
%3B%26%2320313%3B%26%2321019%3B%26%2332426%3B%26%2324405%3B+%26%2335775%3B%26
%2335848%3B%26%2365306%3B%26%2320013%3B%26%2322269%3B%26%2322806%3B%26%2336152%3B%26
%2321069%3B%26%2326223%3B%26%2319981%3B%26%2323481%3B%26%2320048%3B%26%2335266%3B+
%26%2337329%3B%26%2334701%3B%26%2339118%3B%26%2326292%3B%26%2365306%3B%26%2320013%3B
%26%2322269%3B%26%2338754%3B%26%2320020%3B%26%2330340%3B%26%2321361%3B%26%2326426%3B
%26%2319982%3B%26%2326426%3B%26%2336935%3B+
<br>
<b>(apache commons lang) org.apache.commons.lang.StringEscapeUtils: </b>&lt;script&gt;alert('xss');&lt;/script&gt;
&amp;#29615;&amp;#29699;&amp;#32463;&amp;#27982;&amp;#19981;&amp;#26223;&amp;#27668;&amp;#20013;&amp;#22269;&amp;#32463;
&amp;#27982;&amp;#22686;&amp;#38271;&amp;#25918;&amp;#32531; &amp;#20013;&amp;#22269;&amp;#32463;&amp;#27982;&amp;#22312;
&amp;#29615;&amp;#29699;&amp;#19981;&amp;#26223;&amp;#27668;&amp;#19979;&amp;#21576;&amp;#29616;&amp;#25918;&amp;#32531;
&amp;#24577;&amp;#21183;&amp;#65292;&amp;#26368;&amp;#26032;&amp;#22269;&amp;#20869;&amp;#29983;&amp;#20135;&amp;#24635;
&amp;#20540;&amp;#22686;&amp;#38271;&amp;#20026;9.9%&amp;#65292;&amp;#36890;&amp;#32960;&amp;#25345;&amp;#32493;&amp;#25918;
&amp;#32531;&amp;#12290; &amp;#20013;&amp;#22269;&amp;#20061;&amp;#26376;&amp;#36152;&amp;#26131;&amp;#30408;&amp;#20313;
&amp;#21019;&amp;#32426;&amp;#24405; &amp;#35775;&amp;#35848;&amp;#65306;&amp;#20013;&amp;#22269;&amp;#22806;&amp;#36152;
&amp;#21069;&amp;#26223;&amp;#19981;&amp;#23481;&amp;#20048;&amp;#35266; &amp;#37329;&amp;#34701;&amp;#39118;&amp;#26292;
&amp;#65306;&amp;#20013;&amp;#22269;&amp;#38754;&amp;#20020;&amp;#30340;&amp;#21361;&amp;#26426;&amp;#19982;&amp;#26426;
&amp;#36935;
<br>
<b>(struts-core-1.3.8.jar) org.apache.struts.util.ResponseUtils: </b>&lt;script&gt;alert(&#39;xss&#39;);&lt;/script&gt;
&amp;#29615;&amp;#29699;&amp;#32463;&amp;#27982;&amp;#19981;&amp;#26223;&amp;#27668;&amp;#20013;&amp;#22269;&amp;#32463;
&amp;#27982;&amp;#22686;&amp;#38271;&amp;#25918;&amp;#32531; &amp;#20013;&amp;#22269;&amp;#32463;&amp;#27982;&amp;#22312;
&amp;#29615;&amp;#29699;&amp;#19981;&amp;#26223;&amp;#27668;&amp;#19979;&amp;#21576;&amp;#29616;&amp;#25918;&amp;#32531;
&amp;#24577;&amp;#21183;&amp;#65292;&amp;#26368;&amp;#26032;&amp;#22269;&amp;#20869;&amp;#29983;&amp;#20135;&amp;#24635;
&amp;#20540;&amp;#22686;&amp;#38271;&amp;#20026;9.9%&amp;#65292;&amp;#36890;&amp;#32960;&amp;#25345;&amp;#32493;&amp;#25918;
&amp;#32531;&amp;#12290; &amp;#20013;&amp;#22269;&amp;#20061;&amp;#26376;&amp;#36152;&amp;#26131;&amp;#30408;&amp;#20313;
&amp;#21019;&amp;#32426;&amp;#24405; &amp;#35775;&amp;#35848;&amp;#65306;&amp;#20013;&amp;#22269;&amp;#22806;&amp;#36152;
&amp;#21069;&amp;#26223;&amp;#19981;&amp;#23481;&amp;#20048;&amp;#35266; &amp;#37329;&amp;#34701;&amp;#39118;&amp;#26292;
&amp;#65306;&amp;#20013;&amp;#22269;&amp;#38754;&amp;#20020;&amp;#30340;&amp;#21361;&amp;#26426;&amp;#19982;&amp;#26426;
&amp;#36935;
<br>
<b>(xwork) com.opensymphony.xwork2.util.TextUtils with spec chars: </b>&lt;script&gt;alert('xss');&lt;/script&gt;
&amp;#29615;&amp;#29699;&amp;#32463;&amp;#27982;&amp;#19981;&amp;#26223;&amp;#27668;&amp;#20013;&amp;#22269;&amp;
#32463;&amp;#27982;&amp;#22686;&amp;#38271;&amp;#25918;&amp;#32531; &amp;#20013;&amp;#22269;&amp;#32463;&amp;#27982;
&amp;#22312;&amp;#29615;&amp;#29699;&amp;#19981;&amp;#26223;&amp;#27668;&amp;#19979;&amp;#21576;&amp;#29616;&amp;#25918;
&amp;#32531;&amp;#24577;&amp;#21183;&amp;#65292;&amp;#26368;&amp;#26032;&amp;#22269;&amp;#20869;&amp;#29983;&amp;#20135;
&amp;#24635;&amp;#20540;&amp;#22686;&amp;#38271;&amp;#20026;9.9%&amp;#65292;&amp;#36890;&amp;#32960;&amp;#25345;&amp;
#32493;&amp;#25918;&amp;#32531;&amp;#12290; &amp;#20013;&amp;#22269;&amp;#20061;&amp;#26376;&amp;#36152;&amp;#26131;
&amp;#30408;&amp;#20313;&amp;#21019;&amp;#32426;&amp;#24405; &amp;#35775;&amp;#35848;&amp;#65306;&amp;#20013;&amp;
#22269;&amp;#22806;&amp;#36152;&amp;#21069;&amp;#26223;&amp;#19981;&amp;#23481;&amp;#20048;&amp;#35266; &amp;#37329;
&amp;#34701;&amp;#39118;&amp;#26292;&amp;#65306;&amp;#20013;&amp;#22269;&amp;#38754;&amp;#20020;&amp;#30340;&amp;#21361;
&amp;#26426;&amp;#19982;&amp;#26426;&amp;#36935;
<br>
<b>apache commons unescape then escape with StringEscapeUtils: </b>&lt;script&gt;alert('xss');&lt;/script&gt;
&#29615;&#29699;&#32463;&#27982;&#19981;&#26223;&#27668;&#20013;&#22269;&#32463;&#27982;&#22686;&#38271;&#25918;
&#32531; &#20013;&#22269;&#32463;&#27982;&#22312;&#29615;&#29699;&#19981;&#26223;&#27668;&#19979;&#21576;&#29616;
&#25918;&#32531;&#24577;&#21183;&#65292;&#26368;&#26032;&#22269;&#20869;&#29983;&#20135;&#24635;&#20540;&#22686;
&#38271;&#20026;9.9%&#65292;&#36890;&#32960;&#25345;&#32493;&#25918;&#32531;&#12290; &#20013;&#22269;&#20061;
&#26376;&#36152;&#26131;&#30408;&#20313;&#21019;&#32426;&#24405; &#35775;&#35848;&#65306;&#20013;&#22269;&#22806;
&#36152;&#21069;&#26223;&#19981;&#23481;&#20048;&#35266; &#37329;&#34701;&#39118;&#26292;&#65306;&#20013;&#22269;
&#38754;&#20020;&#30340;&#21361;&#26426;&#19982;&#26426;&#36935;
<br>
<form action="AscetikServlet" method="POST" >
<input type="text" id="input" name="input" >
<input type="submit" >
</form>
</body>
</html>


References:
Apache Commons Lang: http://commons.apache.org/lang/
Struts 1: http://struts.apache.org/
Struts 2: http://struts.apache.org/2.x/
WebWork: http://www.opensymphony.com/webwork/
Mycode: http://my-security-projects.googlecode.com/files/testEncoding.war
My code is written for tomcat 6 with java 1.6 and all the above libraries.

2 comments:

ascetik said...

I have one update to this. Bean write does not cover all the character sets as well as the apache commons libraries do. Just a note to think about.

Anonymous said...

A decent alternative for output encoding can be found in OWASP Enterprise Security API. It's really easy to use and adapt to whatever context you need.