Saltar a: navegación, buscar



In progress

Before you begin


A note about SQL injection




The problem Hibernate addresses


See original article.

How it works


See this configuration example



Hitting the database





         Session sess = factory.openSession();
         Transaction tx;
         try {
              tx = sess.beginTransaction();
              q.setString(0, "Izi");
         catch (Exception e) {
             if (tx!=null) tx.rollback();
             throw e;
         finally {


        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        Person aPerson = (Person) session
                .setParameter("pid", personId); 


Security Implications


     Person aPerson = (Person) session
     Session sess = factory.openSession();
     try {
          //set transaction timeout to 3 seconds
          // do some work

Defining Transaction Bounds

Usually, ending a Session involves four distinct phases:

  • flush the session
  • commit the transaction
  • close the session
  • handle exceptions


  • If commit() is present, no need to call flush() as it does this already.
  • Most database communication methods only propagate exceptions if they're outside the scope of the session. (this is an assumption based on the many functions whose source I've examined, I won't be perusing the entire api source to back this assumption)

Consider this example:

       // Non-managed environment idiom
       Session sess = factory.openSession();
       Transaction tx = null;
       try {
              tx = sess.beginTransaction();
              // do some work
       catch (RuntimeException e) {
              if (tx != null) tx.rollback();
              throw e; // or display error message
       finally {

Most Common Functions:

  • Session.beginTransaction() - begin transaction (doh)
  • Session.getTransaction() - begin transaction
  • Session.flush() - end transaction
  • Session.close() - end session
  • Transaction.begin() - begin transaction
  • Transaction.commit() - end transaction
  • Transaction.rollback() -

Creating, manipulating and executing queries

  • The Session interface defines methods that create Query and SQLQuery objects - these are the methods we care about because they allow the developer to construct query strings (as opposed to letting Hibernate perform the sql operations).
  • The Query/SQLQuery objects are mutable and executable, but are not actually SUNK until Transaction.commit(), or Query.executeUpdate() is called. However, I think it is best that we flag functions that create and construct Query objects as they would be in direct contact with tainted data.
  • Once a Query or SQLQuery object is obtained from the Session, the parameters of its sql string should be set using the setter functions like setParameter(), the setters are listed here. These setters check for type mismatch, or guess the type, then check for positional mismatch and named parameter mismatch so they're pretty safe me thinks. Concatenating tainted parameters using the '+' operator, on the other hand, would be equivalent to mis-using a prepared-statement.

Consider this example:

     String table = (String) req.getParameter("table");//obviously retarded
     String parameter1 = request.getParameter("param1");

     Session session = sessionFactory.getCurrentSession();
                SQLQuery query = session.createSQLQuery("SELECT * FROM " + table + "WHERE stuff= ?"); /*B00*/
                query.setParameter(0, parameter1); /*YAY*/
     } catch (Exception e) {} 
     session.close();//omfg no rollback?

Most Common Functions:

  • Session.createSQLQuery(String queryString) - creates a Query with given SQL string - technically executed on commit() or flush() but this function is more directly related to the taint source.
  • Session.createQuery(String queryString) - creates Query with given HQL string.
  • Session.createFilter(Object collection, String queryString) - creates a Query with filter string.
  • Query.setParameter() - variations on this binds parameters to "?" and ":namedparams"
  • Query.executeUpdate() -
  • Query.getQueryString() -

More Examples

Using queries from other Queries:

     String sql;

          Query q1 = session.createQuery(taintSQL); //pretend taintSQL came from unchecked input
          sql = q1.getQueryString(); //get taintSQL
          Query q2 = new QueryImpl(sql, session, parameterMetadata); //reuse taintSQL w/o validation
          session.getTransaction.commit(); //evil prevails

Using executeUpdate()

     public void executeUpdateHQL(Session session, String evil)//a few calls deep from where evil became tainted
          Query query = session.createQuery(evil);  /*B00*/
          query.setString("newName","EEvil"); //these don't matter if the sql is already evil
          int rowCount = query.executeUpdate();  /*B00*/
          System.out.println("Rows affected: " + rowCount);

          //See the results of the update and some other random stuff
          query = session.createQuery("from Supplier");
          List results = query.list();            


named parameter (preferred)

Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
q.setString("name", "Fritz");
Iterator cats = q.iterate();

positional parameter

q.setString(0, "Izi");
Iterator cats = q.iterate();

named parameter list

List names = new ArrayList();
Query q = sess.createQuery("from DomesticCat cat where cat.name in (:namesList)");
q.setParameterList("namesList", names);
List cats = q.list();

Executing a bunch of actions (relevant fns listed in the excel sheet)

	private List executions;
	executions = new LinkedList();
	private void executeActions(List list) throws HibernateException {
		for ( Iterator execItr = list.iterator(); execItr.hasNext(); ) {
			execute( (Executable) execItr.next() );
	public void execute(Executable executable) {
		final boolean lockQueryCache = session.getFactory().getSettings().isQueryCacheEnabled();
		if ( executable.hasAfterTransactionCompletion() || lockQueryCache ) {
			executions.add( executable );
		if (lockQueryCache) {
				.preinvalidate( executable.getPropertySpaces() );

Persisting tainted data

  • Assume persistent objects have JavaBeans style setter methods as this is most common practice. When these setters are called with tainted parameters consider this object to be tainted.
  • We should flag all functions where tainted objects are made persistent. Although most documents will define Session.save() or Session.persist() as making an object persistent, it is actually PENDING until a call to Transaction.commit() is made. Whether or not we want to flag the saves, or the commits is up to scan dev - keep in mind that if we're flagging commit() we must first decide that the code between Transaction.begin() or Session.beginTransaction() and Transaction.commit() contains eevil.
  • The only associated cwe I can think of right now is stored xss.

Consider this example:

     Session session = sessionFactory.getCurrentSession();
     String firstname = req.getParameter("firstname");
     String lastname = request.getParameter("lastname");

          Transaction tx = session.beginTransaction();

          Person thePerson = session.load(Person.class, new Long(69));//loading an already persistent object
          thePerson.setFirstname(firstname);// then adding tainted data to it
          session.save(thePerson);  //persisting our changes

     } catch (Exception e) {
          if (tx!=null) tx.rollback();
          throw e;

Most Common Functions:

  • Session.save(Object object) - save object to the session, object should not contain tainted data.
  • Session.persist(Object object) -
  • Session.void replicate(Object object, ReplicationMode?? replicationMode) -
  • Session.void saveOrUpdate(Object object) -
  • Session.update(Object object)() -
  • Session.evict(Object object)() - remove instance from session cache
  • Session.clear() - evict all loaded instances
  • Session.load(Class theClass, Serializable id) - gets an object from the db for you to manipulate.