Tuesday, September 6, 2011

Simple Java tricks to protect your web application against SQL injection

Your application is vulnerable to SQL Injection when you send unfiltered strings to the database. Most modern ORM frameworks should take care of it (but don't take my word!... go ahead and check how secure your framework is).
Sometimes, you have to work with plain JDBC (or ODBC). Here is a couple of tricks that help:

1. First and foremost, avoid concatenating strings for SQL queries. Use prepared statements unless is not possible (i.e. cases when you have undefined number of parameters)
2. Leverage the language type system: If you're passing a number, use Integer instead of String... any invalid character will fail the conversion and will not reach the DB.
3. If there's no option but concatenate strings, make sure the database comment quotes are escaped (for example, in DB2 you have to replace the single quote character with 2 single quote characters: instead of "SELECT * FROM users WHERE name='"+param+"'" use "SELECT * FROM users WHERE name='"+param.replaceAll("'","''")+"'"

For something a little more advanced, you can wrap the strings in some kind of "EscapedString" class, and use that class in the signature of the DAOs (related to 2. )

Note: by no means this is a comprehensive list. Application security is very hard, check your database documentation...

Cheers,

Ujjwal Soni

How to Protect Against MySQL Injection on User Login Form

The below mysql database query is to to protect your database against MySQL injection through user login forms. This preventive action make spammers stay away from running the database query on your database with out your knowledge

Query to Protect Against MySQL Injection via Login Form

$username = stripslashes($username);
$password = stripslashes($password);
$username = mysql_real_escape_string($username);
$password = mysql_real_escape_string($password); 


Cheers,

Ujjwal Soni

-- In Dreams And In Love There Are No Impossibilities --

Monday, September 5, 2011

What will happen to Java, in Oracle's hands ?

I was asked by my friend few days back that "What will happen to Java, in Oracle's hands ?"

My answer was.. INSERT INTO "Oracle" SELECT * FROM "Sun"

'...Open source will continue at Oracle - along with Java. It could even profit. Just don't expect it to help anybody else.'

It will help. Oracle has more money than SUN.

I don't think it will become more proprietary. IBM, Redhat, Apache etc. will not allow that.

Java is OK. JVM is not OK. But at least we have CacaoVM and some opensource implementations, once Oracle will bastardize it. On the other hand, I don't think they want to screw it up on a main trunk. They did this to RedHat clone, called Oracle Linux, that is completely rubbish distribution. I would more worry about OpenSolaris — there might be started some unpleasant "fun" from Oracle... :-(

Java became popular because of open policies of Sun. Any attempt to commercialize or make Java more proprietary will turn out to be a bad move for technology.

I think Oracle will try to make more money from Java licenses and try to control Java and use it for competitive advantage, which will make other Java vendors insecure and will eventually move away from Java. In a free market Oracle is free to do this, but it will not be good for the technology.

Use it if you like it, don't try to own it

I just hope there won't appear String2 that is null and an empty string at the same time, as they did to VARCHAR... :-)

Cheers,

Ujjwal Soni

-- In Dreams And In Love There Are No Impossibilities --

Top "MUST HAVE" habits of a great software developer to ensure creating a world class quality coding product

Below are some of top "MUST HAVE" habits of a great software developer to ensure creating a world class quality coding product ::

1) Self discipline. So much bad code is due to laziness by developers who don't do what they know should be done.

2) Assume the code written doesn't work unless it is proven to work.
Don't assume that things will never fail. In other words, assume things will fail and provide for clean handling of it. Error messages reporting errors are required. Crash on error is unacceptable.

3) Hangs are unacceptable. All code should be bounded in time and an error must be reported if it runs over.
Do your own testing. It doesn't matter if you have a separate test group. Do your own testing anyway.

4) Never assume that a user will never do something with the code. Assume that a user will do anything and everything possible. Provide clean handling and error messages for everything not allowed.

5) The developer should insure that the code compiles with zero warning messages.
Always use a source code repository, even in a “team” of one person. The repository should be backed-up properly.

6) Never check-in code to a main repository that doesn't compile cleanly. Check-in to a branch repository for checkpointing or backups is ok.

7) Teamwork - few things are small enough or require so few skills that one person can do them well.

8) Discipline - do things right *all the time* if you want top quality.
Ability, Experience - one needs to learn on the job; they say you tend to get expert only after 10,000 hours at a skill.

9) Breadth - you need to understand other people's vision not just your own, or what you make will suit you and nobody else.

10) Luck - whether your idea or somebody else's, you need a good idea AND the luck to get it to market at the right time.

11) A good team - what you can't put toward the effort yourself, the rest of the team needs to supply.

12) Knowledge - especially of design patterns (and have to remember that they are giving direction, not the right solution) and frameworks

13) TESTS - they are prooving that the code works. He/she must write tests automatically without thinking: do I have to?

14) Digging in problems - it laverages the knowledge and gives him/her deep understanding of technology

15) Curiosity - to be up to date with other concepts

16) Document everything (tomorrow you do not remember what is in your head today).

17) Pay attention to what your customer - requirements analyst says and work with him/her. Do not assume that you know their needs better. It is their needs. Do not assume that your work is just writting code, it is also discussing your plans and results with your clients.

18) Always plan your next task and sketch a model of what you will build.

19) Always check on the internet for things you need. It is very rare that you were the first to need them. For every hint you get try to give something back to the community. If there is an open source project near your needs use it and expand it. It is better to focus on your new task than reinventing the wheel.

20) Always take some time to check if you need to use a new tool or programming language. A good programmer is not tied to a specific language, however he can be very good or specialized at one or more.

21)Proper error/exception handling... make sure that app should not crash

22)He/She should be 'Continuous Learner' and upgrade their skills in respective domain time to time..

23)Last,but not least, Think 'out of box'. Smart people can easily entertain new ideas, thoughts, and ways of doing things.

Cheers!!!

Ujjwal Soni

-- In Dreams And In Love There Are No Impossibilities

Thursday, August 11, 2011

Alfresco Webdav SSO Configuration

Hi,

I finally configured Oracle SSO with Alfresco Webdav. Below is how i achieved that.

I need to run Alfresco on tomcat deployed on other virtual machine, i created a class file as under

-- STEP 1



package my.custom;

import java.io.IOException; 
import java.util.List;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.AbstractAuthenticationFilter;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.alfresco.web.bean.repository.Repository;



public class WebDavAuthentication extends AbstractAuthenticationFilter implements Filter {
private static final String LOCALE = "locale";
public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
private static Log logger = LogFactory.getLog(OSSOAuthenticationFilter.class);
private ServletContext context;
private String loginPage;
private AuthenticationComponent authComponent;
private AuthenticationService authService;
private TransactionService transactionService;
private PersonService personService;
private NodeService nodeService;
private List m_languages;

public OSSOAuthenticationFilter() {
super();
}

public void destroy() {
// Nothing to do
}

/**
* Run the filter
*
* @param sreq
* ServletRequest
* @param sresp
* ServletResponse
* @param chain
* FilterChain
* @exception IOException
* @exception ServletException
*/
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException, ServletException {
// Get the HTTP request/response/session
HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse resp = (HttpServletResponse) sresp;
HttpSession httpSess = req.getSession(true);

String userName = null;
//Get headers setted by the oracle sigle sign one server
java.util.Enumeration reqMap = req.getHeaders("Osso-User-Dn");

if (reqMap == null) {
logger.error("No user logged in");
} else {
while (reqMap.hasMoreElements()){
//Get from the full dn the username
userName = ((String)reqMap.nextElement()).split(",")[0].trim().toString().split("=")[1].trim().toString();
//String tmp = value.split(",")[0].trim().toString();
//userName = tmp.split("=")[1].trim().toString();
}
}

if (logger.isDebugEnabled()) {
logger.debug("OSSO : User = " + userName);
}

// See if there is a user in the session and test if it matches
User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);

if (user != null) {
try {
// Debug
if (logger.isDebugEnabled())
logger.debug("OSSO : User " + user.getUserName() + " validate ticket");

if (user.getUserName().equals(userName)) {
UserTransaction tx1 = transactionService.getUserTransaction();
try {
tx1.begin();
authComponent.setCurrentUser(user.getUserName());
tx1.commit();
}catch(Exception ex){
logger.error("Failed due to transaction " + ex);
try {
tx1.rollback();
} catch (Exception ex2) {
logger.error("Failed to rollback transaction", ex2);
}

}
I18NUtil.setLocale(Application.getLanguage(httpSess));
chain.doFilter(sreq, sresp);
return;
} else {
// No match
//setAuthenticatedUser(req, httpSess, userName);
//below url is th oracle portal url
resp.sendRedirect("http://hostname:7778/alfresco");
return;
}
} catch (AuthenticationException ex) {
if (logger.isErrorEnabled())
logger.error("Failed to validate user " + user.getUserName(), ex);
}
}

setAuthenticatedUser(req, httpSess, userName);

// Redirect the login page as it is never seen as we always login by name
if (req.getRequestURI().endsWith(getLoginPage()) == true)
{
if (logger.isDebugEnabled())
logger.debug("Login page requested, chaining ...");

resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
return;
}
else
{
//below url is th oracle portal url
resp.sendRedirect("http://hostname:7778/alfresco");
//chain.doFilter(sreq, sresp);
return;
}

}

/**
* Set the authenticated user.
*
* It does not check that the user exists at the moment.
*
* @param req
* @param httpSess
* @param userName
*/
private void setAuthenticatedUser(HttpServletRequest req, HttpSession httpSess, String userName) {
if (userName != null){
UserTransaction tx1 = transactionService.getUserTransaction();
// Set the authentication
try {
tx1.begin();
authComponent.setCurrentUser(userName);
tx1.commit();
} catch (Throwable ex) {
logger.error(ex);
try {
tx1.rollback();
} catch (Exception ex2) {
logger.error("Failed to rollback transaction", ex2);
}
}

// Set up the user information
UserTransaction tx = transactionService.getUserTransaction();
NodeRef homeSpaceRef = null;
User user;
try {
tx.begin();
user = new User(userName, authService.getCurrentTicket(), personService.getPerson(userName));
homeSpaceRef = (NodeRef) nodeService.getProperty(personService.getPerson(userName), ContentModel.PROP_HOMEFOLDER);
if(homeSpaceRef == null) {
logger.warn("Home Folder is null for user '"+userName+"', using company_home.");
homeSpaceRef = (NodeRef) nodeService.getRootNode(Repository.getStoreRef());
}
user.setHomeSpaceId(homeSpaceRef.getId());
tx.commit();
} catch (Throwable ex) {
logger.error(ex);

try {
tx.rollback();
} catch (Exception ex2) {
logger.error("Failed to rollback transaction", ex2);
}

if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else {
throw new RuntimeException("Failed to set authenticated user", ex);
}
}

// Store the user
httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);

// Set the current locale from the Accept-Lanaguage header if available
Locale userLocale = parseAcceptLanguageHeader(req, m_languages);

if (userLocale != null) {
httpSess.setAttribute(LOCALE, userLocale);
httpSess.removeAttribute(MESSAGE_BUNDLE);
}

// Set the locale using the session
I18NUtil.setLocale(Application.getLanguage(httpSess));
}
}

public void init(FilterConfig config) throws ServletException {
this.context = config.getServletContext();
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
transactionService = serviceRegistry.getTransactionService();
nodeService = serviceRegistry.getNodeService();

authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authService = (AuthenticationService) ctx.getBean("authenticationService");
personService = (PersonService) ctx.getBean("personService");

// Get a list of the available locales
ConfigService configServiceService = (ConfigService) ctx.getBean("webClientConfigService");
LanguagesConfigElement configElement = (LanguagesConfigElement) configServiceService.getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);

m_languages = configElement.getLanguages();
}

/**
* Return the login page address
*
* @return String
*/
private String getLoginPage() {
if (loginPage == null) {
loginPage = Application.getLoginPage(context);
}

return loginPage;
}
}



-- STEP 2 Place this class file under



C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\my\custom



-- STEP 3 Now you need to configure proxy pass in oc4j's httpd.conf file



$ORACLE_HOME/Apache/Apache/conf/httpd.conf, add the following entries:                                                                                    ProxyPass /alfresco/ http://host:8080/alfresco/

ProxyPass /alfresco http://host:8080/alfresco/


ProxyPassReverse /alfresco/ http://host:8080/alfresco/

ProxyPassReverse /alfresco http://host:8080/alfresco/

-- STEP 4 Now you need to enable sso on oracle portal



edit $ORACLE_HOME/Apache/Apache/conf/mod_osso.conf, add the following lines just before the :
require valid-user
AuthType Basic


require valid-user
AuthType Basic

Please restart apache after you have made this configuration 

-- STEP 5 Edit web xml file under

C:\Alfresco\tomcat\webapps\alfresco\WEB-INF

paste below lines before Authentication Filter 

<filter>
<filter-name>Osso Filter</filter-name>
<filter-class>my.custom.OSSOAuthenticationFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>Osso Filter</filter-name>
<url-pattern>/faces/jsp/browse/browse.jsp</url-pattern>
</filter-mapping>

<filter>
<filter-name>Osso Filter</filter-name>
<filter-class>my.custom.OSSOAuthenticationFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>Osso Filter</filter-name>
<url-pattern>/alfresco</url-pattern>
</filter-mapping> 

-- STEP 6 If alfresco is already running then stop and start alfresco
service from start menu under start -> alfresco -> stop alfreco
virtual server



Thats it, now oracle sso is configured successfully for Alfreco



Try opening http://oc4jserverhost/alfresco, it will redirect to oracle
portal sso login page, enter credentials, it will then redirect you to
alfresco home page on successful login.

Any issues implementing this, feel free to contact me..

Cheers,

Ujjwal Soni

Tuesday, August 2, 2011

Conflicting standard.jar with OC4J server

Today i was working on an application that was to be deployed on LIVE oc4j application server. The deployment went successful but when the application was being tested there were many errors as below related to standard. jar that was in OC4J lib and in my application's classpath.

The errors i got are as under ::


11/08/02 13:31:07 vqwiki.WikiException: org.apache.taglibs.standard.tag.common.core.Util.escapeXml(Ljava/lang/String;)Ljava/lang/String;
11/08/02 13:31:07       at vqwiki.servlets.SaveTopicServlet.doPost(SaveTopicServlet.java:150)
11/08/02 13:31:07       at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
11/08/02 13:31:07       at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:835)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:341)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.forward(ServletRequestDispatcher.java:230)
11/08/02 13:31:07       at vqwiki.servlets.VQWikiServlet.dispatch(VQWikiServlet.java:107)
11/08/02 13:31:07       at vqwiki.servlets.WikiServlet.doPost(WikiServlet.java:733)
11/08/02 13:31:07       at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
11/08/02 13:31:07       at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:835)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:341)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.forward(ServletRequestDispatcher.java:230)
11/08/02 13:31:07       at vqwiki.servlets.FrontControllerFilter.doFilter(FrontControllerFilter.java:91)
11/08/02 13:31:07       at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:16)
11/08/02 13:31:07       at vqwiki.servlets.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:74)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:670)
11/08/02 13:31:07       at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:341)
11/08/02 13:31:07       at com.evermind.server.http.HttpRequestHandler.handleNotFound(HttpRequestHandler.java:1038)
11/08/02 13:31:07       at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:853)
11/08/02 13:31:07       at com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:231)
11/08/02 13:31:07       at com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:136)
11/08/02 13:31:07       at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192)
11/08/02 13:31:07       at java.lang.Thread.run(Thread.java:534)


I resolved this error by editing my web application's orion-web.xml

I un-commented below line from the file :


 <!-- Uncomment this element to control web application class loader behavior. -->
        <web-app-class-loader search-local-classes-first="true"  include-war-manifest-class-path="true" /> 

Regards,

Ujjwal Soni









Monday, July 25, 2011

Load Data while Scrolling Page Down with jQuery and PHP

Hi All,

Today, i will show you data loading while page scrolling down with jQuery and PHP. We have lots of data but can not display all. This script helps you to display little data and make faster your website.

Database Table


 
CREATE TABLE messages(

mes_id INT PRIMARY KEY AUTO_INCREMENT,

msg TEXT);

load_data.php

When we are scrolling down a webpage, the script($(window).scroll) finds that you are at the bottom and calls the last_msg_funtion(). Take a look at $.post("") eg: $.post("load_data.php?action=get&last_msg_id=35")




<?php
include('config.php');
$last_msg_id=$_GET['last_msg_id'];
$action=$_GET['action'];

if($action <> "get")
{
?>

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
function last_msg_funtion()
{
var ID=$(".message_box:last").attr("id");
$('div#last_msg_loader').html('<img src="bigLoader.gif">');
$.post("load_data.php?action=get&last_msg_id="+ID,

function(data){
if (data != "") {
$(".message_box:last").after(data);
}
$('div#last_msg_loader').empty();
});
};

$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height() - $(window).height()){
last_msg_funtion();
}
});
});
</script>
</head>
<body>
<?php
include('load_first.php'); //Include load_first.php
?>
<div id="last_msg_loader"></div>
</body>
</html>
<?php
}

else
{
include('load_second.php'); //include load_second.php
}
?>

load_first.php
Contains PHP code to load 20 rows form the message table.
<?php
$sql=mysql_query("SELECT * FROM messages ORDER BY mes_id DESC LIMIT 20");
while($row=mysql_fetch_array($sql))
{
$msgID= $row['mes_id'];
$msg= $row['msg'];
?>
<div id="<?php echo $msgID; ?>" class="message_box" > 
<?php echo $msg; ?>
</div> 
<?php
} 
?>



load_second.php

Contains PHP code to load 5 rows less than last_msg_id form the message table.  


<?php
$last_msg_id=$_GET['last_msg_id'];
$sql=mysql_query("SELECT * FROM messages WHERE mes_id < '$last_msg_id' ORDER BY mes_id DESC LIMIT 5");
$last_msg_id="";
while($row=mysql_fetch_array($sql))
{
$msgID= $row['mes_id'];
$msg= $row['msg']; 
?>
<div id="<?php echo $msgID; ?>" class="message_box" > 
<?php echo $msg;
?>
</div>
<?php
} 
?>


CSS


body
{
font-family:'Georgia',Times New Roman, Times, serif;
font-size:18px;
}
.message_box
{
height:60px;
width:600px;
border:dashed 1px #48B1D9;
padding:5px ;
}
#last_msg_loader
{
text-align: right;
width: 920px;
margin: -125px auto 0 auto;
}
.number
{
float:right;
background-color:#48B1D9;
color:#000;
font-weight:bold;
}




Please let me know any problems implementing this or any suggetions you have.


Cheers,

Ujjjwal Soni