1#!/usr/bin/env python
2
3"""
4Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
5See the file 'LICENSE' for copying permission
6"""
7
8from lib.core.compat import xrange
9from lib.core.enums import PRIORITY
10
11__priority__ = PRIORITY.HIGHEST
12
13def dependencies():
14    pass
15
16def tamper(payload, **kwargs):
17    """
18    Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' counterpart
19
20    Requirement:
21        * MySQL
22        * SQLite (possibly)
23        * SAP MaxDB (possibly)
24
25    Tested against:
26        * MySQL 5.0 and 5.5
27
28    Notes:
29        * Useful to bypass very weak and bespoke web application firewalls
30          that filter the IFNULL() function
31
32    >>> tamper('IFNULL(1, 2)')
33    'IF(ISNULL(1),2,1)'
34    """
35
36    if payload and payload.find("IFNULL") > -1:
37        while payload.find("IFNULL(") > -1:
38            index = payload.find("IFNULL(")
39            depth = 1
40            comma, end = None, None
41
42            for i in xrange(index + len("IFNULL("), len(payload)):
43                if depth == 1 and payload[i] == ',':
44                    comma = i
45
46                elif depth == 1 and payload[i] == ')':
47                    end = i
48                    break
49
50                elif payload[i] == '(':
51                    depth += 1
52
53                elif payload[i] == ')':
54                    depth -= 1
55
56            if comma and end:
57                _ = payload[index + len("IFNULL("):comma]
58                __ = payload[comma + 1:end].lstrip()
59                newVal = "IF(ISNULL(%s),%s,%s)" % (_, __, _)
60                payload = payload[:index] + newVal + payload[end + 1:]
61            else:
62                break
63
64    return payload
65