-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
484 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MP1 checkpoint 1 grade for ptwrdhn2 (partner: tdubey3) | ||
|
||
1.1.1_addr : 2/2 | ||
Comment : '' | ||
|
||
1.1.1_eax : 2/2 | ||
Comment : '' | ||
|
||
1.1.2 : 4/4 | ||
Comment : '' | ||
|
||
1.1.3 : 4/4 | ||
Comment : '' | ||
|
||
1.1.4 : 4/4 | ||
Comment : '' | ||
|
||
1.1.5 : 4/4 | ||
Comment : '' | ||
|
||
total : 20/20 |
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import MySQLdb as mdb | ||
from bottle import FormsDict | ||
from hashlib import md5 | ||
|
||
# connection to database project2 | ||
def connect(): | ||
"""makes a connection to MySQL database. | ||
@return a mysqldb connection | ||
""" | ||
|
||
#TODO: fill out function parameters. Use the user/password combo for the user you created in 2.1.2.1 | ||
|
||
return mdb.connect(host="localhost", | ||
user="", | ||
passwd="", | ||
db=""); | ||
|
||
def createUser(username, password): | ||
""" creates a row in table named users | ||
@param username: username of user | ||
@param password: password of user | ||
""" | ||
|
||
db_rw = connect() | ||
cur = db_rw.cursor() | ||
#TODO: Implement a prepared statement using cur.execute() so that this query creates a row in table user | ||
db_rw.commit() | ||
|
||
def validateUser(username, password): | ||
""" validates if username,password pair provided by user is correct or not | ||
@param username: username of user | ||
@param password: password of user | ||
@return True if validation was successful, False otherwise. | ||
""" | ||
|
||
db_rw = connect() | ||
cur = db_rw.cursor() | ||
#TODO: Implement a prepared statement using cur.execute() so that this query selects a row from table user | ||
if cur.rowcount < 1: | ||
return False | ||
return True | ||
|
||
def fetchUser(username): | ||
""" checks if there exists given username in table users or not | ||
if user exists return (id, username) pair | ||
if user does not exist return None | ||
@param username: the username of a user | ||
@return The row which has username is equal to provided input | ||
""" | ||
|
||
db_rw = connect() | ||
cur = db_rw.cursor(mdb.cursors.DictCursor) | ||
print username | ||
#TODO: Implement a prepared statement so that this query selects a id and username of the row which has column username = username | ||
if cur.rowcount < 1: | ||
return None | ||
return FormsDict(cur.fetchone()) | ||
|
||
def addHistory(user_id, query): | ||
""" adds a query from user with id=user_id into table named history | ||
@param user_id: integer id of user | ||
@param query: the query user has given as input | ||
""" | ||
|
||
db_rw = connect() | ||
cur = db_rw.cursor() | ||
#TODO: Implement a prepared statment using cur.execute() so that this query inserts a row in table history | ||
db_rw.commit() | ||
|
||
#grabs last 15 queries made by user with id=user_id from table named history | ||
def getHistory(user_id): | ||
""" grabs last 15 distinct queries made by user with id=user_id from | ||
table named history | ||
@param user_id: integer id of user | ||
@return a first column of a row which MUST be query | ||
""" | ||
|
||
db_rw = connect() | ||
cur = db_rw.cursor() | ||
#TODO: Implement a prepared statement using cur.execute() so that this query selects 15 distinct queries from table history | ||
rows = cur.fetchall(); | ||
return [row[0] for row in rows] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
f1a86709d1e356b16542b866edbf82fe1442c9f041e2b0a1eb576396bc060f25 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import re, os | ||
from bottle import FormsDict, HTTPError | ||
from hashlib import md5 | ||
|
||
############################################################ | ||
# XSS Defenses | ||
|
||
class XSSNone(object): | ||
""" this class just returns user_input """ | ||
|
||
name = "No defense" | ||
@staticmethod | ||
def init(response): | ||
response.set_header("X-XSS-Protection", "0"); | ||
@staticmethod | ||
def filter(user_input): | ||
return user_input | ||
|
||
class XSSEncodeAngles(object): | ||
""" this class encodes < and > into < and > """ | ||
|
||
name = "Encode < and >" | ||
@staticmethod | ||
def init(response): | ||
response.set_header("X-XSS-Protection", "0"); | ||
@staticmethod | ||
def filter(user_input): | ||
#TODO: complete this filter definition | ||
return user_input | ||
|
||
############################################################ | ||
# CSRF Defenses | ||
|
||
class CSRFNone(object): | ||
""" this class provides no defense against CSRF """ | ||
|
||
name = "No defense" | ||
@staticmethod | ||
def init(request, response): | ||
return None | ||
@staticmethod | ||
def formHTML(token): | ||
return "" | ||
@staticmethod | ||
def validate(request, token): | ||
pass | ||
|
||
class CSRFToken(object): | ||
""" token validation class against CSRF """ | ||
|
||
name = "Token validation" | ||
@staticmethod | ||
def init(request, response): | ||
token = request.get_cookie("csrf_token") | ||
|
||
#TODO: implement Token validation | ||
|
||
return token | ||
@staticmethod | ||
def formHTML(token): | ||
return "<input type='hidden' name='csrf_token' value='" + token + "'>" | ||
@staticmethod | ||
def validate(request, token): | ||
if request.forms.get('csrf_token') != token: | ||
raise HTTPError(403, "CSRF Attack Detected (bad or missing token)") | ||
|
||
############################################################ | ||
|
||
xssDefenses = [XSSNone,XSSEncodeAngles] | ||
csrfDefenses = [CSRFNone,CSRFToken] | ||
|
||
xssDefense = xssDefenses[0] | ||
csrfDefense = csrfDefenses[0] | ||
|
||
def setCookies(response): | ||
response.set_cookie("xssdefense", str(xssDefenses.index(xssDefense))) | ||
response.set_cookie("csrfdefense", str(csrfDefenses.index(csrfDefense))) | ||
|
||
def setup(request, response): | ||
def getDefense(request, name): | ||
if name in request.forms: | ||
return int(request.forms.get(name)) | ||
elif name in request.query: | ||
return int(request.query.get(name)) | ||
else: | ||
return int(request.get_cookie(name,0)) | ||
global xssDefense, csrfDefense | ||
xss = getDefense(request, "xssdefense") | ||
if xss not in range(len(xssDefenses)): | ||
raise HTTPError(output="Invalid XSS Defense (%d)" % xss) | ||
csrf = getDefense(request, "csrfdefense") | ||
if csrf not in range(len(csrfDefenses)): | ||
raise HTTPError(output="Invalid CSRF Defense (%d)" % csrf) | ||
xssDefense = xssDefenses[xss] | ||
csrfDefense = csrfDefenses[csrf] | ||
setCookies(response) | ||
|
||
def selectors(): | ||
def getSelector(defenseList, selectedDefense=None): | ||
return "".join("<option value=%d%s>%d - %s</option>" % \ | ||
(i,(defenseList[i].name==selectedDefense.name and " selected" or ""), i, defenseList[i].name) \ | ||
for i in range(len(defenseList))) | ||
return FormsDict(xssoptions=getSelector(xssDefenses,xssDefense), | ||
csrfoptions=getSelector(csrfDefenses,csrfDefense)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#!/usr/bin/python2 | ||
import sys, os, re, bottle | ||
os.chdir(os.path.dirname(os.path.abspath(__file__))) | ||
|
||
from bottle import get, post, run, debug, request, response, redirect, view, FormsDict, HTTPError | ||
import defenses | ||
import database | ||
|
||
#a cookie which tracks user login | ||
authSecret = "77da94627587ed9ef35081b28ee5d06ee758a242ffded59efa7687b04873c89d" | ||
|
||
@get("/") | ||
@view("index") | ||
def index(): | ||
defenses.setup(request, response) | ||
csrftoken = defenses.csrfDefense.init(request, response) | ||
return dict(v=FormsDict(defenses=defenses.selectors(), | ||
user=getUser(), | ||
csrfcode=defenses.csrfDefense.formHTML(csrftoken))) | ||
|
||
@get("/search") | ||
@view("search") | ||
def search(): | ||
defenses.setup(request, response) | ||
csrftoken = defenses.csrfDefense.init(request, response) | ||
defenses.xssDefense.init(response) | ||
query = defenses.xssDefense.filter(request.query.q) | ||
user = getUser() | ||
if user and user.id: | ||
if query != "": | ||
database.addHistory(user.id, query) | ||
history = database.getHistory(user.id) | ||
else: | ||
history = None | ||
return dict(v=FormsDict(defenses=defenses.selectors(), | ||
user=getUser(), | ||
query=query, | ||
history=history, | ||
csrfcode=defenses.csrfDefense.formHTML(csrftoken))) | ||
|
||
@post("/login") | ||
def login(create=False): | ||
defenses.setup(request, response) | ||
csrftoken = defenses.csrfDefense.init(request, response) | ||
defenses.csrfDefense.validate(request, csrftoken) | ||
username = request.forms.get("username") | ||
password = request.forms.get("password") | ||
if not username or not password: | ||
raise HTTPError(400, "Required field is empty") | ||
if not re.match("[A-Za-z0-9]+$", username): | ||
raise HTTPError(400, "Invalid username") | ||
if create: | ||
if database.fetchUser(username): | ||
raise HTTPError(400, "User already exists") | ||
if len(password) < 4: | ||
raise HTTPError(400, "Password too short") | ||
database.createUser(username, password) | ||
if not database.validateUser(username, password): | ||
raise HTTPError(403, "Login unsuccessful") | ||
response.set_cookie("authuser", username, authSecret, httponly=True) | ||
redirect("./") | ||
|
||
@post("/logout") | ||
def logout(): | ||
defenses.setup(request, response) | ||
csrftoken = defenses.csrfDefense.init(request, response) | ||
defenses.csrfDefense.validate(request, csrftoken) | ||
response.delete_cookie("authuser") | ||
redirect("./") | ||
|
||
@post("/create") | ||
def create(): | ||
login(create=True) | ||
|
||
def getUser(): | ||
username = request.get_cookie("authuser", None, secret=authSecret) | ||
if username is None: | ||
return None | ||
return database.fetchUser(username) | ||
|
||
@post("/setdefenses") | ||
def setdefenses(): | ||
defenses.setup(request, response) | ||
if request.forms.get("location"): | ||
redirect(request.forms.get("location")) | ||
else: | ||
redirect("./") | ||
|
||
if __name__ == "__main__": | ||
debug(True) | ||
run(host='127.0.0.1', reloader=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>{{title}}</title> | ||
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen"> | ||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> | ||
<style> | ||
.navbar-inner { | ||
float: none; | ||
margin: 0 auto; | ||
display: table; | ||
table-layout: fixed; | ||
} | ||
.container { | ||
max-width: none !important; | ||
width: 800px; | ||
min-width: 800px; | ||
} | ||
.navbar { margin: 0; } | ||
.main { margin-top: 15px; } | ||
#logged-in-user { font-weight: bold; } | ||
.navbar-inverse form { color: #999; } | ||
h3 { margin-top: 0px; } | ||
h4 { margin-top: 5px; } | ||
.search-well { | ||
width: 475px; | ||
margin: 60px auto 60px auto; | ||
text-align: center; | ||
} | ||
.search-field { width: 300px; } | ||
.form-space { margin: 5px 0; } | ||
.form-more-space { margin: 15px 0 5px 0; } | ||
.well p { margin: 0 0 5px 0; } | ||
#query-lbl { color: red; } | ||
#searchcontrol { margin-bottom: 15px; } | ||
</style> | ||
<script> | ||
function applyDefenses(){ | ||
$('#location').val(document.location); | ||
$('#setdefenses').submit(); | ||
} | ||
$(function(){ | ||
$('#xssdefense').change(applyDefenses); | ||
$('#csrfdefense').change(applyDefenses); | ||
}); | ||
</script> | ||
</head> | ||
<body> | ||
<!-- Defense selector navbar --> | ||
<div class="navbar navbar-default navbar-static-top"> | ||
<div class="navbar-inner"> | ||
<form id="setdefenses" action="./setdefenses" method="post" class="navbar-form"> | ||
<div class="form-group"> | ||
<label for="csrfdefense">CSRF:</label> | ||
<select name="csrfdefense" id="csrfdefense" style="width:auto" class="form-control input-sm">{{!v.defenses.csrfoptions}}</select> | ||
<label for="xssdefense">XSS:</label> | ||
<select name="xssdefense" id="xssdefense" style="width:auto" class="form-control input-sm">{{!v.defenses.xssoptions}}</select> | ||
<input id="location" name="location" type="hidden"> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
<!-- Bungle navbar --> | ||
<div class="navbar navbar-inverse navbar-static-top"> | ||
<div class="container"> | ||
<div class="navbar-header"> | ||
<a id="bungle-lnk" class="navbar-brand" href="./">Bungle!</a> | ||
</div> | ||
<div class="nav navbar-nav navbar-right"> | ||
%if v.user is not None: | ||
<!-- Logout button --> | ||
<form action="./logout" method="post" class="navbar-form form-inline">{{!v.csrfcode}} | ||
Logged in as <span id="logged-in-user">{{v.user.username}}</span>. | ||
<input id="log-out-btn" type="submit" value="Log out" class="btn btn-link navbar-link"> | ||
</form> | ||
%else: | ||
<p class="navbar-text"> | ||
Not logged in. | ||
</p> | ||
%end | ||
</div> | ||
</div> | ||
</div> | ||
<div class="container main"> | ||
%include | ||
</div> | ||
</body> | ||
</html> |
Oops, something went wrong.