First working commit - Basic Scans and bugs :)
commit
7f9d2735da
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -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"]
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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];
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
@ -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( 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 !
|
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
After Width: | Height: | Size: 163 KiB |
|
@ -0,0 +1 @@
|
|||
gunicorn --workers=3 server:app
|
|
@ -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( 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)
|
Binary file not shown.
Loading…
Reference in New Issue