Each team will present for 30 minutes, including ~10 minutes of Q&A. All team members must participate and be prepared to discuss any aspect of the project. Presentation should include:
Portions Copyright © 2005-06 Python Software Foundation.
Risk | Importance | Discussion |
---|---|---|
Denial of service | Minor | Researchers can wait until the system comes back up |
Data in database destroyed | Minor | Restore from backup |
Unauthorized data access | Major | If competitors access data, competitive advantage may be lost |
Backups corrupted, so that data is permanently lost | Major | Redoing trials may cost millions of dollars |
Data corrupted, and corruption not immediately detected | Critical | Researchers may make recommendations or diagnoses that lead to injury or death |
QUERY_STRING
, while unexpected ones may be present.QUERY_STRING
may not even be formatted according to the HTTP specification.
form = cgi.FieldStorage()
test_id = form.getvalue('testid')
query = "SELECT date,result FROM Results WHERE (id=%s)" % test_id
cursor = connection.cursor()
cursor.execute(query)
results = cursor.fetchall()
cursor.close()
"1);UPDATE Results SET result=FALSE WHERE (id=*"
"SELECT date,result FROM Results WHERE (id=1);UPDATE Results SET result=FALSE WHERE (id=*)"
form = cgi.FieldStorage()
test_id = form.getvalue('testid')
query = "SELECT date,result FROM Results WHERE (id=%s)" % test_id
cursor = connection.cursor()
cursor.execute(query)
results = cursor.fetchall()
cursor.close()
form = cgi.FieldStorage()
test_id = form.getvalue('testid')
cursor = connection.cursor()
cursor.execute("SELECT date,result FROM Results WHERE (id=?)", test_id)
results = cursor.fetchall()
cursor.close()
This one occured in a BMI219 Python script from last year and was discovered during a recent security audit by a UCOP contractor. The CGI script was using a value from the request that was sent using a "hidden" form field. The script then simply concatenated the upload directory path with the form value, without checking whether the value contained path separators, e.g., “../../../../../../etc/passwd”. Even though parsing of the target file fails, the generated error messages included parts of the target file:
Blah blah blah. Offending line: root:x:0:0:root:/root:/bin/bash
There is no Python package for checking CGI input because it really depends on how the values will be used. A “/” should be illegal in path names but is probably just fine in dates. To verify whether a form value is malicious or even legal, the CGI script writer must apply domain-specific knowledge. For example, checking a date is fairly standard (and there exists code to do it in the “datetime” module); checking whether a protein sequence is legal is pretty specialized (but maybe Biopython has something to do that). The point is that there is no single call a script writer can use to guarantee all supplied form values are safe to use.
def read_file(filename, required_uid):
'''Read submission data from a file, checking that the file
is owned by the specified user.'''
owner = os.stat(filename)[ST_UID]
if owner != required_uid:
raise SecurityException('%s has incorrect owner' % filename)
stream = open(filename, 'r')
data = stream.read()
stream.close()
return data
CGI/1.0 test Python script report:
argc is 1
argv is ['/usr/local/www/rbvi/preview/cgi-bin/test-cgi.py']
You are apache on watson.cgl.ucsf.edu
cwd is /usr/local/www/rbvi/preview/cgi-bin
encryted channel
authenticated as tef
AUTH_TYPE=Basic
SERVER_SOFTWARE=Apache/2.2.15 (Red Hat)
SCRIPT_NAME=/cgi-bin/test-cgi.py
SERVER_SIGNATURE=Apache/2.2.15 (Red Hat) Server at bmi219.rbvi.ucsf.edu Port 443
REQUEST_METHOD=GET
REMOTE_USER=tef
SERVER_PROTOCOL=HTTP/1.1
QUERY_STRING=
PATH=/bin:/sbin:/usr/bin:/usr/sbin
SSL_TLS_SNI=bmi219.rbvi.ucsf.edu
HTTP_USER_AGENT=Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:28.0) Gecko/20100101 Firefox/28.0
HTTP_CONNECTION=keep-alive
SERVER_NAME=bmi219.rbvi.ucsf.edu
REMOTE_ADDR=169.230.11.112
SERVER_PORT=443
SERVER_ADDR=169.230.27.19
...
#!/usr/bin/python
print "Content-type: text/plain"
print
print "CGI/1.0 test Python script report:"
print
import sys
print "argc is", len(sys.argv)
print "argv is", sys.argv
import pwd, os, socket
print "You are", pwd.getpwuid(os.geteuid()).pw_name, "on", socket.gethostname()
print
print "cwd is", os.getcwd()
print
if "HTTPS" in os.environ and os.environ["HTTPS"] == "on":
print "encryted channel"
else:
print "unencrypted channel"
if "REMOTE_USER" in os.environ:
print "authenticated as", os.environ["REMOTE_USER"]
else:
print "unauthenticated"
print
for key, value in os.environ.items():
print "%s=%s" % (key, value)
print
import cgi
data = cgi.FieldStorage()
for key in data.keys():
print "%s: %s" % (key, data[key].value)