slanted W3C logo

XQuery injection

Eric van der Vlist

XML Prague 2011

Picture © brianjmatis

I am not a security expert!

Use these recommendations at your own risk...

Picture © kchbrown

Thanks to

Alessandro Vernet Alessandro Vernet

Adam Retter Adam Retter

Picture © woodleywonderworks

What is code injection?

Code injection is the exploitation of a computer bug that is caused by processing invalid data. Code injection can be used by an attacker to introduce (or "inject") code into a computer program to change the course of execution. The results of a code injection attack can be disastrous. For instance, code injection is used by some computer worms to propagate.


Picture © DanCentury

SQL injection

Can potentially affect any site using a SQL database (LAMP, WAMP, ...)!

Picture © therefromhere

Cross Site Scripting (XSS)

Cross Site Scripting (XSS) could be called "HTML+JavaScript injection".

Can potentially affect any site using JavaScript!

Picture © bertboerland

XSS & SQL Injection market shares

Top 2 attack methods (1/3)

Chart © Web Hacking Incident Database

XQuery injection market share

XQuery injection is hardly ever mentioned.

Does that mean that XQuery is "injection safe"?

Picture © Eric van der Vlist

XQuery is not (yet?) popular enough

Attackers target low hanging fruits on popular platforms

XQuery is just not (yet?) popular enough (don't be mad at me if I say so!)

Picture © Eric van der Vlist

XQuery is a low hanging fruit

Lack of awareness of XQuery injection

People tend to think XPath/XQuery are safe, but...

  • XQuery Update Facilities
  • Powerful extension functions
  • Even the standard document() function is a risk
Picture © Eric van der Vlist

An attack

login screen
Picture © dboy

The guess

?_query=[ = ' ']]]>

http://localhost:8080/orbeon/exist/rest/db/app/users/?_query=//user[mail=%27" + username + "%27]"

Picture © jnkypt

Planing the injection

?_query=[ = ' ']]]>

:= ' or or .=']]>

?_query=[ = '' or or .='']]]>

Picture © doug88888

The injection

    let $message :=
        eXist collection
            The collection is :
{util:serialize(/*, ())}

return mail:send-email($message, 'localhost', ()) 
Picture © Rev. Xanatos Satanicos Bombasticos


  1. With single quotes... failed!
  2. With double quotes... failed!
  3. With single quotes, encoded...

Picture © lindztrom

Blind delete

Picture © thiếunhi* Sò lông

Educated update

Picture © arbyreed


Of course, the eXist-db HTTP client module can do much better!

Picture © matley0

Protection 1: limit the consequences

  • Do not store non encrypted passwords.
  • Limit the permissions of database users to the minimum (and use a user with read only permissions to perform read only queries)
  • Do not enable extensions modules unless you really need them.
Picture © peter barwick

Protection 2a: sanitize user input

For XQuery literals, escape:

Picture © valleygirl_tka

Protection 2b: keep user input out of queries

Use an extension function to get query parameters (when available)

//user[mail=request:get-parameter('mail', 0)]
Picture © tonrulkens

Protection: which one?

  • 1 (limitation) and 2a (sanitization) or 2b (query parameters)
  • 2a is standard (more portable)
  • 2b may be cleaner
  • Beware of *:eval[uate]() (more later)
Picture © Oberazzi

No filters, please!

What about forbidding simple quotes as a protection?

This would work...

... and give Tim O'Reilly a reason to rant about yet another dumb site!

Picture © Eric van der Vlist

How to


  • Some hints will follow
  • More details in the handouts (and soon on my blog)
Picture © Eric van der Vlist

In java



Picture © minifig




         encode-for-uri(san:sanitize-apos($user)), ''']')]]>


  declare namespace request='';
document(concat('http://.../?mail=', encode-for-uri($user),
         '&_query=', encode-for-uri($query) ))]]>
Picture © Eric van der Vlist

In XQuery



Picture © Eric van der Vlist

In XForms




    <_query>declare namespace request='';

Picture © Eric van der Vlist

Related attacks

We've covered "XQuery string literal injection"...

What else?

Picture © digitalrhino

XQuery numeric literal injection

Worse than string literals (no delimiters)

You must validate numeric values before using them...

... or use them as string literals and cast them in XPath/XQuery.

If you use request parameters you must cast them anyway.

Picture © artnoose

XQuery direct element injection

Useful with XQuery update to create/update elements

Safe using query parameters

Sanitization requires to escape 4 characters:

  1. & -> &amp;
  2. < -> &lt
  3. { -> {{
  4. } -> }}
Picture © viosplatter

XUpdate injection

Safer than XQuery Update Facilities for element injection (no enclosed expressions)

Exposed to string literal injection through its XPath expressions.

Things are worse if the implementation supports XPath 2.0, XQuery update facilities and extension functions.

When available, request parameters are safe

Sanitization is similar than for XQuery

Picture ©

*:eval[uate]() injection

saxon:evaluate(), util:eval() and friends are injection prone.

Sanitization is a solution.

When used inside a query, you may need to sanitize twice!

Variables defined out of the call play the same role as query parameters for XQuery injection.

When used inside a query, query parameters are safe inside the call.

Picture © MildlyDiverting

X* injection

What about XProc, XPL, Schematron, W3C XML Schema 1.1, XPointer, ... ?

Any language that uses XPath is prone to similar injections...

... iff user input is copied into XPath expressions.

Seems less likely for these ones, but who knows?

Maybe a subject for XML Prague 2012!

Picture © XWRN


Picture © silent (e)