Implementing Python Scripts
You can create Python scripts to expand the scope of vWAF to suit your specific requirements. This provides additional options and flexibility for administrators with Python scripting experience to expand the functionality of the included handlers.
To create and apply scripts:
- Using the script editor, create the required script(s). Each script is added to the script library (the script library hosts all configured scripts at the application level)
- Using the script library, sort the scripts to determine the order in which they run.
- Using the script handler, enable the required scripts for the application and each path, as needed.
Scripts can include all basic Python operators plus additional modules and functions. For details of the supported modules and functions, see Accessible Python Modules and Functions.
Script Editor
You create and edit scripts using the script editor. The editor checks the syntax and highlights issues as you enter your script. For each script you can add the following 'parts':
- Init
executed during the script handler initialization phase. These are typically significant set up tasks, for example.
- Request
executed during the Script Handler request.
- Response
executed during the Script Handler response.
Script Library
The scripts you create are saved in a script library. Scripts can be enabled at the application level and to relevant paths, as needed. The script library allows you to specify the order in which scripts are executed.
Script Handler
The script handler executes the scripts. You configure the script handler for each application and path, as needed, to enable the required scripts. The scripts available for the application are stored in the script library.
A selection of example scripts are included below.
Creating scripts
To create a script.
Repeat the process to add further scripts.
Managing scripts in the script library
Scripts you create are stored in the script library. You can enable any or all of the scripts for your application and appropriate paths. The scripts in the library are available to any path.
Scripts are executed in the order in which they are sorted. You can change the order of the scripts by clicking the relevant up or down icon.
To edit a script, click the edit icon.
To delete a script, click the delete icon.
If you edit or delete a script, commit the change.
Enabling scripts
You apply the required scripts to your application and application paths as needed.
The scripts are enabled and executed in the order specified.
Example Scripts
This section provides a selection of example scripts.
Example script: Add content to end of page
The following simple example script adds some own content (e.g. a company logo) to the end of each page:
if http.is_request(): http.filter_response_full() else: ct = http.get_response_header("content-type") if ct and ct.split(';')[0].lower() == "text/html": body = http.get_response_body() if len(body) > 0: try: idx = body.upper().index("</BODY>") newbody = [] newbody.append(body[:idx]) newbody.append("<BR/><IMG SRC='logo.gif'/></BODY>") newbody.append(body[idx+len("</BODY>"):]) http.set_response_body("".join(newbody)) except ValueError: http.log("no closing html body tag found")
Example script: Call server scripts based on request URL
The following script takes the request URI (e.g. /image/mandelbrot1.gif) and translates it to /image_handler.php with the subpath argument set to the rest of the URI (e.g. /mandelbrot1.gif):
if http.is_request(): uri = http.get_request_uri() path = [ s for s in uri.split('/') if len(s) > 0 ] if len(path) > 0: uri = "/%s_handler.php" % path[0] subpath = '/' if len(path) > 1: subpath += '/'.join(path[1:]) http.set_request_uri(uri,[("subpath",subpath)])
Example script: checking and setting a cookie
The following script retrieves a cookie given in a request. If the cookie isn’t valid in the session, the script redirects to a given URL. If no cookie has been given at all, the script generates and sets a random response cookie.
if http.is_request(): s = http.get_storage() c = http.get_request_cookie('MYVALIDATOR') if 'MYVALIDATOR' in s: if s['MYVALIDATOR'] != c: http.log('found session with invalid validator') http.redirect('/') elif c: s['MYVALIDATOR'] = c else: s['MYVALIDATOR'] = http.make_random_cookie() http.set_response_cookie('MYVALIDATOR', s['MYVALIDATOR'])
Example script: adding an IP address to the global IP blacklist
If a user calls the URL /honeypot, the following script adds the IP address of the request to the global IP blacklist for a duration of 5 minutes (300 seconds).
if http.is_request() and http.get_url() == "/honeypot": ip = http.get_client_ip() http.generate_blacklist_event(ip, 300)
Example scripts: Validating XML
The following is a simple example of how to verify some incoming XML requests against a given XML Schema:
xml_schema_string = ''' ... ''' if http.is_request() and http.get_request_method() == 'POST' and http.get_request_header('content-type').lower() == 'text/xml': xml_body = str(http.get_request_body()).strip() xml = lxml_etree.parse(StringIO(xml_body)) xml_schema = lxml_etree.XMLSchema(lxml_etree.parse (StringIO(xml_schema_string.strip()))) if not xml_schema.validate(xml): http.log("xml request does not match schema") http.set_returncode(403)
The following example validates the XML against a defined XML DTD. If the XML is valid, the script writes the value true to the vWAF Log Files.
xml_string = '''<?xml version="1.0" encoding="ISO-8859-1"?> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>'''; dtd_string = '''<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)><!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)><!ELEMENT body (#PCDATA)>''' xml = lxml_etree.XML(xml_string) dtd_io = StringIO(dtd_string) dtd = lxml_etree.DTD(dtd_io) http.log(str(dtd.validate(xml)))
The following example validates the XML against a given XML Schema file. If the XML is valid, the script writes the value true to the vWAF Log Files.
xml_string = '''<?xml version="1.0" encoding="ISO-8859-1"?> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>'''; schema_string = '''<xsd:schema xmlns:xsd="http://www.w3.org/ 2001/XMLSchema"> <xsd:element name="note" type="noteType"/> <xsd:complexType name="noteType"> <xsd:sequence> <xsd:element name="to" type="xsd:string" /> <xsd:element name="from" type="xsd:string" /> <xsd:element name="heading" type="xsd:string" /> <xsd:element name="body" type="xsd:string" /> </xsd:sequence> </xsd:complexType> </xsd:schema>''' xml_io = StringIO(xml_string) schema_io = StringIO(schema_string) schema_doc = lxml_etree.parse(schema_io) schema = lxml_etree.XMLSchema(schema_doc) xml_doc = lxml_etree.parse(xml_io) http.log(str(schema.validate(xml_doc)))