ngx_xss: Native support for cross-site scripting in an nginx
agentzh
agentzh at gmail.com
Tue Jan 26 13:20:53 MSK 2010
Hi, folks!
I'm delighted to announce the first release of our new module,
ngx_xss. This output filter module adds native support for simple
cross-site AJAX to the nginx server. Currently only cross-site GET is
implemented, but cross-site POST support is on our TODO list.
Here's a small example using our ngx_echo module together:
location /foo {
default_type "application/json";
echo '{"errcode":400,"errstr":"Bad Request"}';
xss_get on; # enable cross-site GET support
xss_callback_arg callback; # use $arg_callback
}
Then accessing /foo?callback=blah gives the following response:
blah({"errcode":400,"errstr":"Bad Request"}
);
And the ultimate response Content-Type is set to
"application/x-javascript", which can be overridden by the
"xss_output_type" directive like this
xss_output_type text/javascript;
By default, the ngx_xss module filter will skip responses with
Content-Type set to anything other than "application/json". If that's
not what you want, you can use the "xss_input_types" directive to
override that:
xss_input_types text/plain text/css;
This module can also be chained with other output filters like ngx_rds_json:
xss_get on;
xss_callback_arg _callback;
location /query {
drizzle_query "select name from products limit 0, 10";
drizzle_backend my_mysql;
rds_json on;
}
Then you can expect something like this when doing GET
/query?_callback=OpenResty.callback[32]
OpenResty.callback[32]([{"name":"Bike"},{"name":"Book"}]);
Be careful with the order of output filters while building nginx. The
ngx_rds_json filter expects a valid binary stream in the RDS format
while the ngx_xss filter expects some JSON text. If you don't take the
order right, you'll see your ngx_xss settings get completely ingored
in the final responses. Because the ngx_xss filter sees RDS first and
it ignores it due to its "application/x-resty-dbd-stream" content
type.
Below is the correct nginx configure command if you want to use
ngx_xss and ngx_rds_json together:
./configure \
--add-module=/path/to/xss-nginx-module \
--add-module=/path/to/rds-json-nginx-module \
# more options omitted here...
You see, the order of adding output filters on the configure time is
just the *reversed* order that the output filters are actually applied
at runtime. Generally speaking, the nginx output filter chain is a
stack, not a queue ;)
Only a very limited set of callback values is allowed to prevent
JavaScript injection. Valid callback values can be expressed using the
following (Ragel) grammar:
identifier = [$A-Za-z] [$A-Za-z0-9_]*;
index = [0-9]* '.' [0-9]+
| [0-9]+
;
main := identifier ( '.' identifier )*
('[' index ']')?
This is exactly the Ragel grammar used to generate the C validator
used by the ngx_xss module itself.
Sorry for writing long emails. Just be too lazy to write formal
documentation atm hence filling most of the docs into this
announcement :P
Enjoy!
-agentzh
More information about the nginx
mailing list