This repository has been archived on 2024-06-12. You can view files and clone it, but cannot push or open issues or pull requests.
ipserv/cert/script.js

186 lines
5.2 KiB
JavaScript
Raw Normal View History

2024-04-22 01:48:05 +01:00
const VALID_KEYS = {
ip: {
required: true,
match: /^(\d{1,3}\.){3}\d{1,3}$/
},
city: {
required: false,
match: /^[a-zA-Z ]+$/
},
country: {
required: false,
match: /^[a-zA-Z ]+$/
},
countryCode: {
required: false,
match: /^[A-Z]{2}$/
},
asn: {
required: false,
match: /^\d+$/
},
isp: {
required: false,
match: /^.+$/ // ISP names can be anything really
},
lat: {
required: false,
match: /^-?\d+(\.\d+)?$/
},
lon: {
required: false,
match: /^-?\d+(\.\d+)?$/
},
hostname: {
required: false,
match: /^.+$/
},
timezone: {
required: false,
match: /^[^\/]\/.+$/
},
locale: {
required: false,
match: /^[a-z]{2}([_-][A-Z]{2})?$/
},
subnet: {
required: false,
match: /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/
},
abuse: {
required: false,
match: /^.+$/
}
}
const BOBS = [
"|",
"/",
"-",
"\\"
]
async function isCORSEnabled(url) {
try {
const response = await fetch(url, { method: "GET", mode: "cors"});
return response.ok;
} catch {
return false;
};
}
async function getRealIP() {
const response = await fetch("https://api.ipify.org?format=json");
const data = await response.json();
return data.ip;
}
async function checkRaw(url, real) {
const response = await fetch(url);
const text = await response.text();
return text === real;
}
async function checkRoot(url) {
const response = await fetch(url);
const data = await response.json();
return data
}
async function checkLookup(url) {
const response = await fetch(url);
const data = await response.json();
return data
}
async function checkImFeelingLucky(url) {
const response = await fetch(url);
const data = await response.json();
return data;
}
function checkReturnedJSON(data) {
let dataIncluded = 0;
for (let key in VALID_KEYS) {
if (data[key]) {
if(VALID_KEYS[key].match.test(data[key])) {
console.debug("Server included key %s (value: '%s')", key, data[key]);
dataIncluded++;
} else {
console.warn("Server included key %s (value: '%s'), but it's not valid", key, data[key]);
}
} else {
if (VALID_KEYS[key].required) {
console.warn("Server didn't include required key %s", key);
} else {
console.log("Server didn't include optional key %s", key)
}
}
}
return dataIncluded;
}
async function main(e) {
e.preventDefault();
const base_url = document.querySelector("input").value;
const log = document.getElementById("results");
log.textContent = "Checking: " + base_url + "\n";
log.textContent += "Checking if CORS is enabled on the target... ";
const corsEnabled = await isCORSEnabled(base_url);
log.textContent += corsEnabled ? "Yes\n" : "No\n";
if (!corsEnabled) {
log.textContent += "CORS is not enabled, the script will not work\n";
return;
}
log.textContent += "Getting external IP from trusted source... ";
const realIP = await getRealIP();
log.textContent += realIP + "\n";
log.textContent += "Checking /... ";
const root = await checkRoot(base_url);
const rootFeatures = checkReturnedJSON(root)
let rootOK = rootFeatures >= 1 && root.ip === realIP;
log.textContent += rootOK ? `OK (${rootFeatures}/${Object.keys(VALID_KEYS).length} features)\n` : "FAILED\n";
log.textContent += "Checking /lookup... ";
const lookup = await checkLookup(base_url + "/lookup?ip=" + realIP);
const lookupFeatures = checkReturnedJSON(lookup)
let lookupOK = lookupFeatures >= 1 && lookup.ip === realIP;
log.textContent += lookupOK ? `OK (${rootFeatures}/${Object.keys(VALID_KEYS).length} features)\n` : "FAILED\n";
log.textContent += "Checking /imfeelinglucky (this may take a while) ";
let changed = false;
for(let i=0; i<512; i++) {
console.debug("Checking /imfeelinglucky iteration %d/512", i);
const lucky = await checkImFeelingLucky(base_url + "/imfeelinglucky");
const luckyFeatures = checkReturnedJSON(lucky)
let luckyOK = luckyFeatures >= 1 && lucky.ip != realIP;
if (luckyOK) {
console.debug("Server modified IP, OK")
log.textContent = log.textContent.slice(0, -1)
log.textContent += `OK (${luckyFeatures}/${Object.keys(VALID_KEYS).length} features, took ${i} attempts for a modified IP)\n`;
changed = true;
break;
}
else {
console.debug("Server did not modify IP, retrying")
log.textContent = log.textContent.slice(0, -1)
log.textContent += BOBS[i % 4];
}
}
if(!changed) {
log.textContent += "FAILED (did not modify returned IP within 512 tries)\n";
}
log.textContent += "Checking /raw... ";
const raw = await checkRaw(base_url + "/raw", realIP);
log.textContent += raw ? "OK\n" : "FAILED\n";
}
document.querySelector("form").addEventListener("submit", main);