I am writing a server-backend for a conceptional problem that might be hosted on some CTF challenge. It will be hosted on Ubuntu 12.04 LTS, nginx 1.1.19, and uWSGI 1.0.3-debian which will handle Python 2.7.3.
The goal of the challenge is to exploit the JavaScript loaded on contestants' browsers to trigger a PyV8-defined function runThis()
by successfully injecting the function call, quite alike XSS. The Python script described below will work as CGI and validate the contestants' input with PyV8, judging whether the XSS has succeeded or not.
However, it is a problem that this Python script is vulnerable to DoS attack (I suppose that some contestants may supply this script with "while(1){}")
I want to deal with this by setting a timeout to evalJavaScript()
, so I've tried to adopt a solution which uses SIGALRM from https://stackoverflow.com/a/601168/1402144 this reference, but it's not working.
Here is the conceptional code (greatly simplified in order not to give away too much about the game, and to concentrate on the current problem about timeout):
#!/usr/bin/env python
import PyV8
import cgi, cgitb
import signal
from contextlib import contextmanager
# Timeout handler
class TimeoutException(Exception):
pass
@contextmanager
def time_limit(seconds):
def timeout(signum, frame):
raise TimeoutException, "Timed out!"
signal.signal(signal.SIGALRM, timeout)
signal.alarm(seconds)
try:
yield
finally:
signal.alarm(0)
# end Timeout handler
# check JavaScript
class Global(PyV8.JSClass):
def runThis(self):
print "You have called this function via JavaScript."
def evalJavaScript(post_data):
try:
ctxt = PyV8.JSContext(Global())
ctxt.enter()
ctxt.eval(post_data)
ctxt.leave()
except Exception, e:
print e
print "Perhaps syntax error? Try again!"
# end JavaScript
# CGI
form = cgi.FieldStorage()
print 'Content-type: text/html'
print
try:
with time_limit(5):
evalJavaScript(form.getvalue('javascript'))
except TimeoutException, msg:
print "Timed out!"
# end CGI
URL:
http://localhost/validation.py?javascript=runThis()
- Result: "You have called this function via JavaScript."
URL:
http://localhost/validation.py?javascript=while(1){}
- Result: Nginx timing out, while the Python script keeps running at 100% CPU usage.
I also issued
kill -ALRM ${pid}
to the process but it had absolutely no influence to it.
- Result: Nginx timing out, while the Python script keeps running at 100% CPU usage.
I also issued
I've also tested a very small script, which worked.
import signal
from time import sleep
def main():
while 1:
sleep(1)
print "main"
def timeout_handler(signum, frame):
raise Exception
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(10)
try:
main()
except:
print "whoops"
Below are the references I've looked through so far:
- Timing out a multiprocessing function
- Have a function time out if a certain condition is not fulfilled in time
- How to timeout function in python, timeout less than a second
- Timeout on a function call
- Timeout function using threading in python does not work
- Python server that shuts itself after some time being idle
- Multiple subprocesses with timeouts
- How to limit execution time of a function call in Python How to Interrupt/Stop/End a hanging multi-threaded python program
- http://docs.python.org/2/library/multiprocessing.html
- http://pguides.net/python-tutorial/python-timeout-a-function/
Could you kindly give me a hint as to what I am doing wrong, or even better, suggest a better way to achieve the anti-DoS solution?