Updated a lot

master
John Hammond 2017-01-02 00:59:10 -05:00
parent 4b32a9117f
commit 0d925a0ae7
73 changed files with 666 additions and 3442 deletions

View File

@ -1,21 +1,25 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAP1fDj/HP2uuMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV MIIESTCCAzGgAwIBAgIJAIaxYiOmR5/yMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX VQQGEwJVUzELMAkGA1UECAwCQ1QxEzARBgNVBAcMCk5ldyBMb25kb24xKjAoBgNV
aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE3MTUyMTMyWhcNMTcwODE3MTUyMTMyWjBF BAoMIVVuaXRlZCBTdGF0ZXMgQ29hc3QgR3VhcmQgQWNhZGVteTETMBEGA1UECwwK
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 Q3liZXIgVGVhbTEfMB0GA1UEAwwWZ2l0aHViLmNvbS9Kb2huSGFtbW9uZDEnMCUG
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CSqGSIb3DQEJARYYam9obmhhbW1vbmQwMTBAZ21haWwuY29tMB4XDTE3MDEwMjAx
CgKCAQEA5pWsXxqGQzZ98uxLdNpOYWDEWk/dqeJJwTu1oUzkhUkZDbgTfxOzrLnO NDQwOVoXDTE4MDEwMjAxNDQwOVowgboxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD
SeePBMzGIPQKE/l4jesX58JK69657Yhqzvie9/4i5A+vyQ3V7BQnCI92YYTPHltP VDETMBEGA1UEBwwKTmV3IExvbmRvbjEqMCgGA1UECgwhVW5pdGVkIFN0YXRlcyBD
HLvKJ9FkR0ves8o4vLRUFNwAz8zS4piUEhMCMbbZEYRx3+cSH3xu8RQYcwzdw0Tv b2FzdCBHdWFyZCBBY2FkZW15MRMwEQYDVQQLDApDeWJlciBUZWFtMR8wHQYDVQQD
gHUu8lU/nLrOR+p+ovfh/ZlriMGQtSU1F1CBk/wyMESj0ELJx61A3omzIr7rMXiQ DBZnaXRodWIuY29tL0pvaG5IYW1tb25kMScwJQYJKoZIhvcNAQkBFhhqb2huaGFt
fDsvfl+GcB+qt+zfuYSPJXAXoY1R6ojAJjXC2LBR1z0C6y7xS7o37HCFUBNWavHq bW9uZDAxMEBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
d1EzZqNf6Mwa1XYWmJ/appqt1brK3wIDAQABo1AwTjAdBgNVHQ4EFgQUWhlBuC7J AQC4FWxCUkvF10cSg5QnT2NNFTHYRfJT/KU4rQYQKIOAkXhODqVjpOtHNHkY+2N8
jiUEhpmbMIdzbC7RlK8wHwYDVR0jBBgwFoAUWhlBuC7JjiUEhpmbMIdzbC7RlK8w GuqECkqUVUXtu2hyH4CN1qmhmF4+qCGfs4UvNDF1rmbTlT1CNlOs5wh8i02acy8A
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAE93tp9oWgVU1oUyjh8Hm 4SVLquybiEWKIbKnBCPileFTRG0ZvesVVTOOPBpI2D1xh4kdriBBwx0+J/NM0L0w
b0z0VCSPzp/IQ4Ja8ElmL6GF/GsJ9jeH2Yfi/EWO1XFKMY2xGbHci/MSxOX0+ZjS e1MGgqDzjEc9AZ/ewZrhUlKkFWfk3ezU3z1brqDfi1YgzQfboZaXFN7yOzG2tdO4
EgSbYt8lKCBnxYA3OO8F2PyLKEyB7GQ9B++2giSFGnkLUHw0DmWz1LZ81n/Dd2iV EysGs97DuVno84LlZCF/7ZwYgIORP4jVWOkUhtv6yj0uoqrkwQSw7LvoCf6mU2n9
L8tFJwwhaGpoutqcWgEm4whBOgQp/IWCQ1Cy3YDHaORGB4TOAETuvcqhAeTEyltz zR+xIwPs68xuuTXbfLdmSfn5AgMBAAGjUDBOMB0GA1UdDgQWBBRw9d7+KE7rC1ch
99Bz7+vSnZ3m3YgibTl2WdWsBEeXS7ghT0mLPBHQPH61hJxqWaBvhoiZiT0b1I73 j3W38kzB2R6bUTAfBgNVHSMEGDAWgBRw9d7+KE7rC1chj3W38kzB2R6bUTAMBgNV
JcuDpEJx3r2vAXj6JUIRer2TK080IMBvBKTGr4ZSacO3rg7gOweud/NYo4cCgUvC HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBqXIRW8vqLougRyb5xjCvQ4evP
pA== fe6ycRGARxqoAPJedpOncDXXJADZfqEMUDYPC0YQXcZUB51o2glwbPdvGRX22d3N
zJHzwN3YnwT27h/yQFWQ6q6vFqlS1RwyTm168VKi5M23H0q0dFYI/jY9SO0BIJHw
poBNeSLwHcQ1QZYudBkOXqf4VM5IRSKxCFGOdlLuRcFoP56u83stbLli/pMxBdMF
WT3fajTIGmVQMmTHwpbXqLhMDvZHFzg30MO8uncM38DCB64wPFyWBXN98mADnol5
qwFYJ+l+BS+l3T0FrAav9NtQMzJ1FRnUO5gY8cdOU/Xji9vxkBWrvaPxcNHG
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJD7t75jgxkMMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTYwMjE0MjIwMjM0WhcNMTcwMjEzMjIwMjM0WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAoUeVnOJidItTApBwBLrGo0rKh77skVEQHObEVNAKSF2rHf66Ix/Um4J6
OGG440pEGzDiY+2lS8VP40JsZmNXV9920SpJLE6Pv0tb7Nth0B5lrorM9M3Mj6BC
D5E17opvoQFFOu/mjc7elLvHamap2AsqAbk1siyGIC8DecIiNoyMsZeB0d/HZhNi
My8gX8j7I+UMrrn01qriSu3GTh79a3mq4nMC0xtomZZc5jLXZ1C5+dXSGuLpHaqE
kqq80CxmCo0cvAuU6f+WJ+2EXGAJdawvBIGcRbOyYd5WC7GXWSD8EOosI+/7fcaf
kAXy6CYJfng4oDZgJxgNgZ8x5uujZwIDAQABo1AwTjAdBgNVHQ4EFgQU5FXGhyiD
kvpqEgmkVkW9lZgZEp8wHwYDVR0jBBgwFoAU5FXGhyiDkvpqEgmkVkW9lZgZEp8w
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAnGBGn8Cj67RFMwc19cpw
YLBKu3J6p84Q5gqH5hbR2welyidGTkebbyviUmfoxBg1N3OkpNuq+l/M8yPSWTJB
Ij4DNvqHBAICI9eGy3oaaR9tPAvj0bRQXCR5rWHeC9jJrcQblqViKz87UcAX0SVC
WQLtiANgZCFTh0zNMeyn4GRoObwN244KpQdUxNt9ssh4p4/hY9hZ+1BBA4D2Rku3
ncweJ3bQhEkeQIdtl0MIZF5QM+3P++mcRBbim1JcyBdl2Ew4RQVtObdomTStrR+p
zq52cPJgDo83K1j+VOs/R2R/wFv2bfRwY+QrnsHBF8006l/GDtbUTjx0zdHKeIsT
Nw==
-----END CERTIFICATE-----

View File

@ -1,3 +0,0 @@
#!/bin/bash
rm -f server.py certificate.crt privateKey.key

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQChR5Wc4mJ0i1MC
kHAEusajSsqHvuyRURAc5sRU0ApIXasd/rojH9Sbgno4YbjjSkQbMOJj7aVLxU/j
QmxmY1dX33bRKkksTo+/S1vs22HQHmWuisz0zcyPoEIPkTXuim+hAUU67+aNzt6U
u8dqZqnYCyoBuTWyLIYgLwN5wiI2jIyxl4HR38dmE2IzLyBfyPsj5QyuufTWquJK
7cZOHv1rearicwLTG2iZllzmMtdnULn51dIa4ukdqoSSqrzQLGYKjRy8C5Tp/5Yn
7YRcYAl1rC8EgZxFs7Jh3lYLsZdZIPwQ6iwj7/t9xp+QBfLoJgl+eDigNmAnGA2B
nzHm66NnAgMBAAECggEBAIzF4v2RTMbVZZtzX5OBRCj7+1QJfoxI6XuQogY1oQQR
Xm9MDETkX7ttZCkagztBc7kYLkNzBzjf/R8st1mXlIGK+DcSZdRarnYW3SIdS39R
SQfU95kmmUs0YvUblqukAlPSvA75n5Bf5UCFt0ZUXiPJet0OQKRI4Lnuz2XT4fEh
0lUJTKxU6kZwAM37mRtHlJnQ59/qEGPwCz5fe+wAfzwznRVoGB9VQU00k8TX0TT/
JZPPvP2rMcCoiCa6on4Z9gHEtSZN60g35aAcp22SgIk5hxL6bc1OjLN6jDUiVrHf
oYcTGwODzpbyMiSO5N+fGJc0f5VvsTZpwUX8oLAKEAECgYEAzvDbAkLpsU6nYjhs
SNqsToUhnLYKVtDgHdR4Rx6xnIqNp0Zl/o27lWn9ZT9XTwYtkUzm+Vv1iyYvMIY4
3U+0K1vf/Z3fXAptSjwqhRrAEwj6dGu4qsXKcPnabGfNjZqRhx3vAD+T65KQXMrY
OhGFC3wuFug1RhQzFUmPt2uYDgECgYEAx4OSHovko6LpuJBto07nuWCRs4aKofzW
9imdyAau3PbR34RTs0Wwu+LLY8Q8FKor1Eur+8Dp00WJgI2tLE+iVN9aupK/SdVx
ed9UDLnI20nCrf4LFV/HDk7nXLnlvUn2Ndq9lUxi/5AhAfTzibG3q/DwVB5vqdyk
PdYm+GSwAWcCgYEAv9aEELqbDWWOwfzwVTFyXnAIUtBnEUgdG0omHjgUCrxeyNz4
HFyjssVIxJ1NgNKHV5Vk4XEgVViWknM7L959dVx8bw31S8vWuOTBvhaoTH0cQOTD
knw9STI2DBzGbykFE67qKt7Fb7K05XCdtmcbYSRDTbUB/e8n0+oXsr+pfAECgYEA
i+aLmJXZ3pDHON81shULUicQJAXMwmfsSDLIa9Gb3l/IrOY6VvQgSK9wlWWuB4OI
NlZVo7QTgk05bQZrjy3ME52HHlr2fYyJBL+ATWgdGv+u3pjMJtHBYBweChxkp4Xs
erkGxWEJ7lCfhKLB/yS6OXw62ZF6FW8dUCsRqo3YCTMCgYEAr94W8AIlq7uiE7N+
jlRzfedml2JcrDzOLDqcixZh454Q5bMSfJJqoCeLxqHQacQhwngVjztn9EtBr+GC
IFNYCdCoeBtVnWkizKtKohlwAjmxNY9SENFRwCzF5waQErf1PTcPJvD7JG/4S9vL
t84Xs6f6CImQis+03rwtQ3XRc3w=
-----END PRIVATE KEY-----

View File

@ -1,345 +0,0 @@
#!/usr/bin/env python
from flask import Flask
from flask import render_template, request, session, g, url_for, flash, get_flashed_messages, redirect
import sqlite3
import json
import sys, os
from colorama import *
import sys
from threading import Thread
from time import sleep
from uuid import uuid4
import flag_server
from passlib.hash import sha256_crypt
from contextlib import closing
flag_rotation_seconds = 60
correct_answers = {}
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
# ===========================================================================
DATABASE = '/tmp/attack.db'
CONFIG = 'services.json'
CERTIFICATE = 'certificate.crt'
PRIVATE_KEY = 'privateKey.key'
SECRET_KEY = 'this_key_needs_to_be_used_for_session_variables'
if DATABASE == '$DATABASE':
error("This server has not yet been configured with a database file!")
exit(-1)
if CONFIG == '$CONFIGURATION':
error("This server has not yet been configured with a configuration file!")
exit(-1)
if CERTIFICATE == '$CERTIFICATE_FILE':
error("This server has not yet been configured with a certificate!")
exit(-1)
if PRIVATE_KEY == '$PRIVATEKEY_FILE':
error("This server has not yet been configured with a private key!")
exit(-1)
app = Flask( __name__ )
app.config.from_object(__name__)
needed_configurations = [
"app_title", "app_about", "app_navigation_logged_out",
"app_navigation_logged_in", "services"
]
def flag_rotator( services ):
global correct_answers
round = 0
while 1:
print "FLAG ROUND", round, "="*50
correct_answers = {}
for service in services:
flag = flag_server.generate_flag()
flag_server.save_flag( flag, "services/" + service['folder_name'] )
correct_answers[ flag ] = service['points']
round += 1
sleep( flag_rotation_seconds )
if not ( os.path.exists(CONFIG) ):
error("This configuration file '" + CONFIG + "' does not seem to exist!")
exit(-1)
else:
success("The configuration file exists!")
handle = open( CONFIG )
configuration = json.loads(handle.read().replace("\n","").replace("\t",""))
try:
for needed_config in needed_configurations:
assert configuration[needed_config]
except Exception as e:
error("Configuration file '" + sys.argv[1] + "' does not have the following configuration tag:")
warning(e.message)
error("Please fix this and re-run the server.")
exit(-1)
handle.close()
success("The configuration looks good!")
success("Starting the flag rotator...")
flag_rotation = Thread( target = flag_rotator, args = ( configuration['services'],) )
flag_rotation.daemon = True
flag_rotation.start()
success("Spinning up the server...")
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
def connect_db():
return sqlite3.connect( app.config['DATABASE'] )
@app.before_request
def before_request():
g.db = connect_db()
@app.teardown_request
def teardown_request(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
def render( template_name, **kwargs ):
return render_template( template_name,
app_title = configuration['app_title'],
app_navigation_logged_out = configuration['app_navigation_logged_out'],
app_navigation_logged_in = configuration['app_navigation_logged_in'],
**kwargs
)
@app.route("/login", methods=["GET", "POST"])
def login():
error = ""
if request.method == "POST":
cur = g.db.execute('select username, password from users')
# username, password_hash
users = dict(( row[0], row[1] ) for row in cur.fetchall())
if not request.form['username'] in users.iterkeys():
error = 'This username is not in the database!'
else:
if not ( sha256_crypt.verify( request.form['password'], users[request.form['username']] ) ):
error = "Incorrect password!"
else:
session_login( request.form['username'] )
return redirect( "challenges" )
return render( 'login.html', error = error )
@app.route("/register", methods=["GET", "POST"])
def register():
cur = g.db.execute('select username from users')
usernames = [row[0] for row in cur.fetchall() ]
error = ""
if request.method == "POST":
if unicode(request.form['username']) in usernames:
error = 'This username is already in use!'
elif (request.form['password'] == ""):
error = "You must supply a password!"
elif request.form['password'] != request.form['confirm']:
error = 'Your passwords do not match!'
else:
# I use this for command-line submission...
identifier = str(uuid4())
cur = g.db.execute('insert into users (username, password, solved_challenges, score, last_submission, uuid) values ( ?, ?, ?, ?, ?, ? )', [
request.form['username'],
sha256_crypt.encrypt( request.form['password']),
"", # No challenges completed
0, # no score.
0, # no last submission time,
identifier # and a completely unique idenitifier
] )
g.db.commit()
flash("Hello " + request.form['username'] + ", you have successfully registered!")
session_login( request.form['username'] )
return redirect( "challenges" )
return render( 'register.html', error = error )
@app.route("/scoreboard")
def scoreboard():
cur = g.db.execute('select username, score from users order by score desc, last_submission asc')
response = cur.fetchall()
users = [ { "username": row[0], "score": row[1] } for row in response]
return render("scoreboard.html", users = users )
@app.route("/logout")
def logout():
session_logout()
return redirect("about")
@app.route("/")
@app.route("/about")
def about(): return render("about.html", app_about=configuration['app_about'])
@app.route("/challenges")
def challenges_page():
if not ( session['logged_in'] ):
return render("login.html", error = "You must log in to be able to see the challenges!")
try:
cur = g.db.execute('select uuid from users where username =?',
[ session['username'],] )
uuid = cur.fetchone()[0]
except Exception as e:
print error(e.message)
uuid = ''
return render("challenges.html", challenges = configuration['services'], url=request.url_root, session_value = uuid )
@app.route("/check_answer", methods=["GET", "POST"])
def check_answer():
global correct_answers
if request.method == "POST":
if request.form['answer'] in session['solved_challenges']:
return json.dumps({'correct': -1});
if ( request.form['answer'] in correct_answers.keys() ):
flag = request.form['answer']
new_score = int(session['score']) + correct_answers[flag]
cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')) where username = (?)", [
new_score,
session['username']
] );
session['solved_challenges'].append( request.form['answer'] )
session['score'] = new_score
g.db.commit();
return json.dumps({'correct': 1, 'new_score': new_score});
else:
return json.dumps({'correct': 0});
@app.route("/submit", methods=[ "POST" ])
def submit():
global correct_answers
if request.method == "POST":
if ( request.form['flag'] in correct_answers.keys() ):
flag = request.form['flag']
cur = g.db.execute('select score, solved_challenges from users where uuid = (?)',
[ request.form['uuid'], ])
current_score, solved_challenges = cur.fetchone()
solved_challenges = solved_challenges.split()
if ( flag in solved_challenges ):
return 'You already submitted this flag!\n'
print solved_challenges
new_score = current_score + correct_answers[flag]
solved_challenges.append( flag + " " )
cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')), solved_challenges = (?) where uuid = (?)", [
new_score,
' '.join(solved_challenges),
request.form['uuid']
] );
# session['solved_challenges'].append( request.form['flag'] )
session['score'] = new_score
g.db.commit();
# return json.dumps({'correct': 1, 'new_score': new_score});
return 'Correct!\n';
else:
# return json.dumps({'correct': 0});
return 'Incorrect!\n';
def session_login( username ):
flash("You were successfully logged in!")
cur = g.db.execute('select solved_challenges, score from users where username = (?)',
[username])
solved_challenges, score = cur.fetchone()
session['logged_in'] = True
session['username'] = username
session['score'] = score
session['solved_challenges'] = []
def session_logout():
flash("You have been successfully logged out.")
session['logged_in'] = False
session.pop('username')
session.pop('score')
if ( __name__ == "__main__" ):
context = (CERTIFICATE, PRIVATE_KEY)
app.run( host="0.0.0.0", debug=False, ssl_context=context, port = 444 )

View File

@ -1,345 +0,0 @@
#!/usr/bin/env python
from flask import Flask
from flask import render_template, request, session, g, url_for, flash, get_flashed_messages, redirect
import sqlite3
import json
import sys, os
from colorama import *
import sys
from threading import Thread
from time import sleep
from uuid import uuid4
import flag_server
from passlib.hash import sha256_crypt
from contextlib import closing
flag_rotation_seconds = 60
correct_answers = {}
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
# ===========================================================================
DATABASE = '$DATABASE'
CONFIG = '$CONFIGURATION'
CERTIFICATE = '$CERTIFICATE_FILE'
PRIVATE_KEY = '$PRIVATEKEY_FILE'
SECRET_KEY = 'this_key_needs_to_be_used_for_session_variables'
if DATABASE == '$DATABASE':
error("This server has not yet been configured with a database file!")
exit(-1)
if CONFIG == '$CONFIGURATION':
error("This server has not yet been configured with a configuration file!")
exit(-1)
if CERTIFICATE == '$CERTIFICATE_FILE':
error("This server has not yet been configured with a certificate!")
exit(-1)
if PRIVATE_KEY == '$PRIVATEKEY_FILE':
error("This server has not yet been configured with a private key!")
exit(-1)
app = Flask( __name__ )
app.config.from_object(__name__)
needed_configurations = [
"app_title", "app_about", "app_navigation_logged_out",
"app_navigation_logged_in", "services"
]
def flag_rotator( services ):
global correct_answers
round = 0
while 1:
print "FLAG ROUND", round, "="*50
correct_answers = {}
for service in services:
flag = flag_server.generate_flag()
flag_server.save_flag( flag, "services/" + service['folder_name'] )
correct_answers[ flag ] = service['points']
round += 1
sleep( flag_rotation_seconds )
if not ( os.path.exists(CONFIG) ):
error("This configuration file '" + CONFIG + "' does not seem to exist!")
exit(-1)
else:
success("The configuration file exists!")
handle = open( CONFIG )
configuration = json.loads(handle.read().replace("\n","").replace("\t",""))
try:
for needed_config in needed_configurations:
assert configuration[needed_config]
except Exception as e:
error("Configuration file '" + sys.argv[1] + "' does not have the following configuration tag:")
warning(e.message)
error("Please fix this and re-run the server.")
exit(-1)
handle.close()
success("The configuration looks good!")
success("Starting the flag rotator...")
flag_rotation = Thread( target = flag_rotator, args = ( configuration['services'],) )
flag_rotation.daemon = True
flag_rotation.start()
success("Spinning up the server...")
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
def connect_db():
return sqlite3.connect( app.config['DATABASE'] )
@app.before_request
def before_request():
g.db = connect_db()
@app.teardown_request
def teardown_request(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
def render( template_name, **kwargs ):
return render_template( template_name,
app_title = configuration['app_title'],
app_navigation_logged_out = configuration['app_navigation_logged_out'],
app_navigation_logged_in = configuration['app_navigation_logged_in'],
**kwargs
)
@app.route("/login", methods=["GET", "POST"])
def login():
error = ""
if request.method == "POST":
cur = g.db.execute('select username, password from users')
# username, password_hash
users = dict(( row[0], row[1] ) for row in cur.fetchall())
if not request.form['username'] in users.iterkeys():
error = 'This username is not in the database!'
else:
if not ( sha256_crypt.verify( request.form['password'], users[request.form['username']] ) ):
error = "Incorrect password!"
else:
session_login( request.form['username'] )
return redirect( "challenges" )
return render( 'login.html', error = error )
@app.route("/register", methods=["GET", "POST"])
def register():
cur = g.db.execute('select username from users')
usernames = [row[0] for row in cur.fetchall() ]
error = ""
if request.method == "POST":
if unicode(request.form['username']) in usernames:
error = 'This username is already in use!'
elif (request.form['password'] == ""):
error = "You must supply a password!"
elif request.form['password'] != request.form['confirm']:
error = 'Your passwords do not match!'
else:
# I use this for command-line submission...
identifier = str(uuid4())
cur = g.db.execute('insert into users (username, password, solved_challenges, score, last_submission, uuid) values ( ?, ?, ?, ?, ?, ? )', [
request.form['username'],
sha256_crypt.encrypt( request.form['password']),
"", # No challenges completed
0, # no score.
0, # no last submission time,
identifier # and a completely unique idenitifier
] )
g.db.commit()
flash("Hello " + request.form['username'] + ", you have successfully registered!")
session_login( request.form['username'] )
return redirect( "challenges" )
return render( 'register.html', error = error )
@app.route("/scoreboard")
def scoreboard():
cur = g.db.execute('select username, score from users order by score desc, last_submission asc')
response = cur.fetchall()
users = [ { "username": row[0], "score": row[1] } for row in response]
return render("scoreboard.html", users = users )
@app.route("/logout")
def logout():
session_logout()
return redirect("about")
@app.route("/")
@app.route("/about")
def about(): return render("about.html", app_about=configuration['app_about'])
@app.route("/challenges")
def challenges_page():
if not ( session['logged_in'] ):
return render("login.html", error = "You must log in to be able to see the challenges!")
try:
cur = g.db.execute('select uuid from users where username =?',
[ session['username'],] )
uuid = cur.fetchone()[0]
except Exception as e:
print error(e.message)
uuid = ''
return render("challenges.html", challenges = configuration['services'], url=request.url_root, session_value = uuid )
@app.route("/check_answer", methods=["GET", "POST"])
def check_answer():
global correct_answers
if request.method == "POST":
if request.form['answer'] in session['solved_challenges']:
return json.dumps({'correct': -1});
if ( request.form['answer'] in correct_answers.keys() ):
flag = request.form['answer']
new_score = int(session['score']) + correct_answers[flag]
cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')) where username = (?)", [
new_score,
session['username']
] );
session['solved_challenges'].append( request.form['answer'] )
session['score'] = new_score
g.db.commit();
return json.dumps({'correct': 1, 'new_score': new_score});
else:
return json.dumps({'correct': 0});
@app.route("/submit", methods=[ "POST" ])
def submit():
global correct_answers
if request.method == "POST":
if ( request.form['flag'] in correct_answers.keys() ):
flag = request.form['flag']
cur = g.db.execute('select score, solved_challenges from users where uuid = (?)',
[ request.form['uuid'], ])
current_score, solved_challenges = cur.fetchone()
solved_challenges = solved_challenges.split()
if ( flag in solved_challenges ):
return 'You already submitted this flag!\n'
print solved_challenges
new_score = current_score + correct_answers[flag]
solved_challenges.append( flag + " " )
cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')), solved_challenges = (?) where uuid = (?)", [
new_score,
' '.join(solved_challenges),
request.form['uuid']
] );
# session['solved_challenges'].append( request.form['flag'] )
session['score'] = new_score
g.db.commit();
# return json.dumps({'correct': 1, 'new_score': new_score});
return 'Correct!\n';
else:
# return json.dumps({'correct': 0});
return 'Incorrect!\n';
def session_login( username ):
flash("You were successfully logged in!")
cur = g.db.execute('select solved_challenges, score from users where username = (?)',
[username])
solved_challenges, score = cur.fetchone()
session['logged_in'] = True
session['username'] = username
session['score'] = score
session['solved_challenges'] = []
def session_logout():
flash("You have been successfully logged out.")
session['logged_in'] = False
session.pop('username')
session.pop('score')
if ( __name__ == "__main__" ):
context = (CERTIFICATE, PRIVATE_KEY)
app.run( host="0.0.0.0", debug=False, ssl_context=context, port = 444 )

View File

@ -1,176 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:03:36
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
service_name = "Balloon Saloon"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
board = \
'''
| |
1 | 2 | 3
____|_____|_____
| |
4 | 5 | 6
____|_____|_____
| |
7 | 8 | 9
| |
'''
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
# Client-side: ...
'''
try:
# run self.functions()...
pass
except:
log( Fore.YELLOW + self.client_address[0] + " dropped connection!" )
'''
self.send("There are 9 places the balloon can land, but it floats away at RANDOM!")
self.send( board )
self.send("Can you hit the balloon? I'm going to let the balloon go ... RIGHT NOW!")
random_seed = int( mktime(gmtime()) )
seed(random_seed)
position = None
entered = -1
while int(entered) - 1 != position:
self.send("What spot will you shoot?")
entered = self.receive()
position = randint(0, 8)
try:
if ( int(entered) - 1 == position ):
self.send("You shot the balloon! Here is your reward")
self.send(get_flag())
break
else:
self.send( "Aww, you missed! Here's where the balloon was:")
balloon = board.replace( str(position + 1), 'O' )
for i in nums:
balloon = balloon.replace( str(i), ' ' )
self.send( balloon )
self.send("Try again!")
continue
except ValueError:
continue
info( "Ended connection with " + str(self.client_address) + "." )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1,128 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: John Hammond
# @Last Modified time: 2016-02-10 17:16:36
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime
from string import digits as nums
# DECLARE ALL INITIAL CONSTANTS
host, port = "0.0.0.0", 5029
logging = True
service_name = "Balloon Saloon"
board = \
'''
| |
1 | 2 | 3
____|_____|_____
| |
4 | 5 | 6
____|_____|_____
| |
7 | 8 | 9
| |
'''
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
log( Fore.CYAN + "Received connection from " + \
str(self.client_address) + "!" )
# Client-side: ...
'''
try:
# run self.functions()...
pass
except:
log( Fore.YELLOW + self.client_address[0] + " dropped connection!" )
'''
self.send("There are now 100 places the balloon can land, but it floats away at RANDOM!")
self.send( board )
self.send("Can you hit the balloon? I'm going to let the balloon go ... RIGHT NOW!")
random_seed = int( mktime(gmtime()) )
position = None
entered = -1
while int(entered) - 1 != position:
self.send("What spot will you shoot?")
entered = self.receive()
position = randint(0, 8)
try:
if ( int(entered) - 1 == position ):
self.send("You shot the balloon! Here is your reward")
self.send(get_flag())
break
else:
self.send( "Aww, you missed! Here's where the balloon was:")
balloon = board.replace( str(position + 1), 'O' )
for i in nums:
balloon = balloon.replace( str(i), ' ' )
self.send( balloon )
self.send("Try again!")
continue
except ValueError:
continue
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def log( string ):
if logging: print string
def main():
# Turn on colors...
init( autoreset=True )
log( Fore.CYAN + "Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
log( Fore.MAGENTA + Style.BRIGHT + service_name + \
Fore.GREEN + " server started on " + str(server.server_address) + "!")
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
if __name__ == "__main__":
main()

View File

@ -1 +0,0 @@
30e62931eae444ed95d47d40878b56ff8cafc464

View File

@ -1,123 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:03:10
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
service_name = "Service Name"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
info( "Ended connection with " + str(self.client_address) + "!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1,146 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:03:45
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
service_name = "BitBot"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self, prompt = "" ):
self.send( prompt, newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
# Client-side: ...
# try:
# run self.functions()...
flag = get_flag()
try:
for bit in flag:
sent = bin(ord(bit))[2:]
self.send( sent )
entered = self.receive()
if ( entered != sent ):
return
else:
continue
pass
except:
warning( "Dropped connection with " + str(self.client_address) + "." )
info( "Ended connection with " + str(self.client_address) + "." )
# except:
# log( Fore.YELLOW + self.client_address[0] + " dropped connection!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1 +0,0 @@
3ca209fda0cb0fe0f2f13ed9e19c80cbf7703d1e

View File

@ -1,136 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:03:55
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
service_name = "ByteBot"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self, prompt = "" ):
self.send( prompt, newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
flag = get_flag()
self.send("Hello! I'm the ByteBot! ", newline = False)
for bit in flag:
self.send( "Here is part of the flag: " + bit )
entered = self.receive()
if ( entered != bit ):
return
else:
continue
pass
info( "Ended connection with " + str(self.client_address) + "!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1 +0,0 @@
a5fb5cc517e81ed61f184fed3f76d65822053e8b

View File

@ -1,127 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:04:06
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
from base64 import b64encode
service_name = "D-CODE"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
def get_flag():
h = open( 'flag', 'r' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
# Client-side: ...
self.send( b64encode(get_flag()) )
info( "Ended connection with " + str(self.client_address) + "!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1 +0,0 @@
8041b71f6711756b2be286547b2024aef0fefadf

View File

@ -1 +0,0 @@
2617780d830597c701758eb6a0ceafc52b84d82b

View File

@ -1,129 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:04:24
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
service_name = "Flagger"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
def get_flag():
h = open( 'flag', 'r' )
the_flag = h.read()
h.close()
return the_flag
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
# Client-side: ...
try:
self.send( get_flag() )
pass
except:
warning( self.client_address[0] + " dropped connection!" )
info( "Ended connection with " + str(self.client_address) + "!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1,37 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 10:40:14
# @Last Modified by: john
# @Last Modified time: 2016-02-08 18:41:39
from pwnlib import *
import socket
host = 'localhost'
port = 5060
s = tubes.remote.remote( host, port )
print s.recvuntil("> ")
s.sendline('y')
print s.recvuntil("> ")
while (True):
s.sendline('on')
try:
print s.recv()
except:
print some_error_variable.message
print "It dropped connection!"
s.close()

View File

@ -1 +0,0 @@
3ccc616747dbfaffe78b6e80701a77afd189f25f

View File

@ -1,197 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-14 17:04:35
import threading
import SocketServer
from colorama import *
from random import randint, choice, seed
from time import mktime, gmtime, sleep
from string import digits as nums
from json import loads
import sys
service_name = "LampChamp 0"
debug = True
init( autoreset = True )
if (debug):
def success( string ):
print Fore.GREEN + Style.BRIGHT + "[+] " + string
def error( string ):
sys.stderr.write( Fore.RED + Style.BRIGHT + "[-] " + string + "\n" )
def warning( string ):
print Fore.YELLOW + "[!] " + string + "\n"
def info( string ):
print Fore.CYAN + "[.] " + string + "\n"
else:
def success( string ): pass
def error( string ): pass
def warning( string ): pass
def info( string ): pass
def get_port():
handle = open("../../services.json")
data = handle.read()
data = loads(data.replace("\n",'').replace('\t',''))
handle.close()
port = None
for service in data['services']:
if service_name == service['title']:
port = int(service['port'])
if port == None:
error("Port number not found in the configuration file!")
exit(-1)
else:
return port
# DECLARE ALL INITIAL CONSTANTS
host = '0.0.0.0'
port = get_port()
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
def center_text( text, width ):
sides = width / 2 - len(text) / 2
return " " * sides + text + " " * sides
class Service(SocketServer.BaseRequestHandler):
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def print_banner( self ):
self.send( "=" * max_width)
self.send( center_text( "Welcome to LampChamp!", max_width ) )
self.send( "=" * max_width )
self.send( "" )
def prompt( self ):
ready = False
self.send( "To become the LampChamp, you must turn on ALL the lights!" )
self.send( "How many will there be? Well, you'll never know!" )
self.send("")
self.send( "Are you ready for this challenge? (y/n)" )
while ( not ready ):
entered = self.receive()
if ( entered.startswith( "y" ) ):
ready = True
else:
self.send( "Awww, why not? Come on, think it over! Are you ready? (y/n)" )
ready = False
self.send( "Awesome! Good luck!" )
self.send( "Here is your first task: " )
self.send( "" )
def test_lamps( self ):
'''
This initialize() function takes the place of the object's
__init__() constructor because that is annoying to overwrite with
a threaded SocketServer object.
'''
number_of_lamps = randint(100,300)
for i in range( number_of_lamps ):
self.send( lamps[i % len(lamps)] )
self.send( "Turn ON this lamp!" )
lamp_state = self.receive( ).lower()
if ( lamp_state == "on" or lamp_state == "turn on"):
self.send( "Congrats! You've now turned on " + str(i+1) + " lamps! " +\
"You're almost the LampChamp!" )
else:
self.send("Boo! You weren't able to turn the lamp on!")
self.send("You can't handle this challenge. Better luck next time!")
return False
self.send("")
self.send("You did it! You got all the lamps!")
self.send("YOU ARE THE NEW LAMPCHAMP!!!")
self.send("Here is your reward:")
self.send( get_flag() )
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
info( "Received connection from " + str(self.client_address) + "!" )
# Client-side: ...
try:
self.print_banner()
self.prompt()
self.test_lamps()
except:
warning( self.client_address[0] + " dropped connection!" )
info( "Ended connection with " + str(self.client_address) + "!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def main():
try:
get_flag()
except:
error( "Could not get flag file!")
exit(-1)
info("Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
success( service_name + " started on " + str(server.server_address) + "!")
# Now let the main thread just wait...
while ( True ): sleep(10)
if __name__ == "__main__":
main()

View File

@ -1,257 +0,0 @@
# This file includes an array of strings that are used as the lamp images.
lamps = [
r'''
_____
/ \
/ \
/_________\
| |
| |
| |
| |
| |
| |
| |
| |
| |
_| |_
(_____)
''',
r'''
_____
/ \
/ \
/_________\
_|_|_
| |
| |
|_____|
''',
r'''
______
___________________.' // \\
/ \\\\| // \\
| `""` ||.-.||
| ||'-'||
\___________________ \\ //
'.___\\_//
''',
r'''
_...._
.' '.
/ \
| |
\ ~~ /
`\ || /`
|_||_|
{____}
{____}
()
''',
r'''
_.-"```"-._
.' '.
/ .-. \
; | | ;
| | | |
; \_/ ;
\ (_) /
'. .'
`;_______;`
|_..--"`)
(_..--'`|
|_..--'`)
(_..--'`|
`-...-`
''',
r'''
__
."` `".
/ \
| .-..-. |
\ \ / /
'.____.'
{_.="}
{_.="}
`-..-`
''',
r'''
.
. .
.
|
. ~ ~ ~ ~ ~ ~ .
` `$'`$'`$'`$'`S '
' '
' '
' '
' '
' '
' '
' '
' '
' '
' '
' '
. . '`$' `S''. .
`. `$' `$' `$` `$' `$' `$' .'
` , , , , , , , , , , '
( ) )
) * ( (
( * ) )
) * ( *
( * )
) * (
( * )
) * (
( * )
( * )
) * (
( * )
`@~@~@~@~@~@'
`@.@.@.@.@'
''',
r'''
_____
/ \
|_____|
/ _ \
/ ( ) \
/ ` \
/ _ \
/ ( ) \
\ )\ /
\ ( ) /
\ ,-'( /
\/-----\/
| |
/ \
/_________\--._
.-._)
(__
`-|E
''',
r'''
.88888888.
.8888888888.
.88 88.
.88 88.
.88 88.
.88 88.
.88 ::. 88.
.88 ':' 88.
.88 .::. 88.
.88 .:::: 88.
.88 ':::' 88.
.88 .:::. .:. .: 88.
.88 ::::: ':' ':' 88.
88 ':::' .::. 88
88 .::. .::::: .:. 88
88 '::' :::::' ':' 88
'88 .::::: .::. 88'
'88 .:::::' ::::: 88'
'88 ::::::. ':::' 88'
'88 ::::::::. 88'
'88 .:. ::::::::. 88'
'88 '::.::::::::::..88'
'88 .::::::::::::::88'
'88::::::::::::::88'
'88::::::::::::88'
88::::::::::::88
.888888888888888888.
.888%%%%%%%%%%%%%%888.
.888%%%%%%%%%%%%%%%%888.
.888%%%%%%%%%%%%%%%%%%888.
.888%%%%%%%%%%%%%%%%%%%%888.
888%%JGS%%%%%%%%%%%%%%%%%%%888
88888888888888888888888888888888
''',
r'''
.--._.--.--.__.--.--.__.--.--.__.--.--._.--.
_(_ _Y_ _Y_ _Y_ _Y_ _)_
[___] [___] [___] [___] [___] [___]
/:' \ /:' \ /:' \ /:' \ /:' \ /:' \
|:: | |:: | |:: | |:: | |:: | |:: |
\::. / \::. / \::. / \::. / \::. / \::. /
\::./ \::./ \::./ \::./ \::./ \::./
'=' '=' '=' '=' '=' '='
''',
r'''
_ _ _
'.` `.'
_ >_< _
_.-'`-.-=-.-`'-._
.;'.--./ \.--.';.
.' > \ / < '.
/.__./\__.';-=-;'.__/\.__.\
| \ / \/ \/ \ / |
; | | | | |
'._/\ /\ /\ /\_.'
`-` ;-.-;2 `-`
> <
.-'{___}'-.
'-.._____..-'
|||
|||
/'-'\
.-',_ _,'-.
/'-. .`. .-'\
.=' . `. .` . '=.
'-'`-./ \.-`'-'
'._.'
''',
r'''
(~)
(' `)
).(
(`_~_ _ _~_')
/` / | \ '\
/ --- /----|----\ --- \
/_____ /_____|_____\ _____\
` / | \ '
`------/-------|-------\------'
`- - - /- - - - | - - - -\ - - -'
` /.\ | /.\ | /.\ | /.\ '
` \~/ | \~/ | \~/ | \~/ '
`\ /`\ /`\ /`\ /`\ /`\ /`\ /`\ /'
` ` ` (_`___`_) ` | ` `
) ( |
) ( *
( )
( )
` '
` '
` '
` '
` '
` '
` '
` '
`. .'
) ` ` (
( ~ ` ~` ~ )
------------------` ~ ~ ~ ~ '--------------
''',
r'''
___
.-"` `"-.
.' '.
/ \
/ # \
| # |
| |
; .-~~~-. ;
; ) ( ;
\ ( ) /
\ \ / /
\ ) ( /
| | | |
|__|_|__|
{=======}
}======={
{=======}
}======={
{=======}
`""u""`
''',
]

View File

@ -1,86 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: john
# @Date: 2016-02-08 08:44:14
# @Last Modified by: john
# @Last Modified time: 2016-02-08 16:35:22
import threading
import SocketServer
from colorama import *
from random import randint, choice
# DECLARE ALL INITIAL CONSTANTS
host, port = "0.0.0.0", 5000
logging = True
service_name = "QR-uiz"
class Service(SocketServer.BaseRequestHandler):
def get_flag():
h = open( 'flag' )
the_flag = h.read()
h.close()
return the_flag
def send( self, string, newline = True ):
if newline: string = string + "\n"
self.request.sendall( string )
def receive( self ):
self.send( "> ", newline=False )
return self.request.recv( 4096 ).strip()
def handle(self):
'''
This handle() function is like the main function of the server;
it is what is ran after each connection.
'''
# Server-side: ...
log( Fore.CYAN + "Received connection from " + \
str(self.client_address) + "!" )
# Client-side: ...
try:
# run self.functions()...
pass
except:
log( Fore.YELLOW + self.client_address[0] + " dropped connection!" )
class ThreadedService(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def log( string ):
if logging: print string
def main():
# Turn on colors...
init( autoreset=True )
try:
get_flag()
except:
log( Fore.RED + Style.BRIGHT + "Could not get flag file!")
exit(-1)
log( Fore.CYAN + "Starting server..." )
server = ThreadedService((host, port), Service)
server.allow_reuse_address = True
log( Fore.MAGENTA + Style.BRIGHT + service_name + \
Fore.GREEN + " server started on " + str(server.server_address) + "!")
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
if __name__ == "__main__":
main()

View File

@ -1,176 +0,0 @@
#!/usr/bin/env bash
# Author: John Hammond
# Date: 11JAN2016
# Description:
# This script should install all the necessary dependencies and generate a self-signing
# certificate to be used by a CTF server you can run on your own local machine.
# If you configure your own CTF with a .json file, you can give that to the server
# script and it will easily spin up a CTF competition for everyone in the local
# network.
#
# Optional variables: this should be modified by the commandline arguments
DATABASE=""
CONFIGURATION=""
# Internal variables; do not edit.
DEPENDENCIES="python-pip sqlite3 python-flask python-passlib"
SERVER_FILE="server_base.py"
NEW_SERVER_FILE="server.py"
SCHEMA_FILE="schema.sql"
PRIVATEKEY_FILE='privateKey.key'
CERTIFICATE_FILE='certificate.crt'
CURRENT_USER=`logname`
RED=`tput setaf 1` # code for red console text
GREEN=`tput setaf 2` # code for green text
NC=`tput sgr0` # Reset the text color
function display_help() {
cat <<EOF
usage:
$0 -d DATABASE -c CONFIGURATION
parameters:
-d
Specify the database file that will be created and used for this server.
Example: '/tmp/ctf-practice.db'
-c
Specify the configuration file that will be used for this server.
Example: 'ctf_practice.json'
-h
Display help message
EOF
}
function install_dependencies(){
echo "$0: ${GREEN}installing dependenices...${NC}"
apt-get update || panic
apt-get -y install $DEPENDENCIES || panic
}
function create_certificate(){
echo "$0: ${GREEN}creating HTTPS certificates...${NC}"
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout $PRIVATEKEY_FILE -out $CERTIFICATE_FILE || panic
sed "0,/\$CERTIFICATE_FILE/{s/\$CERTIFICATE_FILE/$CERTIFICATE_FILE/}" $SERVER_FILE > $NEW_SERVER_FILE || panic
sed -i "0,/\$PRIVATEKEY_FILE/{s/\$PRIVATEKEY_FILE/$PRIVATEKEY_FILE/}" $NEW_SERVER_FILE || panic
}
function create_database(){
echo "$0: ${GREEN}creating sqlite3 database...${NC}"
rm -f $DATABASE
sqlite3 $DATABASE < $SCHEMA_FILE || panic
chown $CURRENT_USER $DATABASE || panic
sed -i '0,/\$DATABASE/{s/\$DATABASE/'${DATABASE//\//\\/}'/}' $NEW_SERVER_FILE || panic
}
function configure_ctf(){
echo "$0: ${GREEN}configuring CTF...${NC}"
sed -i "0,/\$CONFIGURATION/{s/\$CONFIGURATION/$CONFIGURATION/}" $NEW_SERVER_FILE || panic
}
function create_new_server(){
cp $SERVER_FILE $NEW_SERVER_FILE
chown $CURRENT_USER $NEW_SERVER_FILE
chmod 744 $NEW_SERVER_FILE
}
function configure_firewall(){
# Allow incoming connections...
echo "$0: ${GREEN} Configuring firewall for HTTPS connections...${NC}"
ufw allow https
}
function main()
{
install_dependencies
create_new_server
create_certificate
create_database
configure_ctf
configure_firewall
echo "$0: ${GREEN} CTF server successfully setup!${NC}"
echo "$0: ${GREEN} You should now be able to run the server with the command: ${NC}"
echo '`sudo python server.py`'
exit 0
}
# Print a fatal error message and exit
# Usage:
# some_command parameter || panic
#
# This will print the panic message and exit if `some_command` fails.
function panic
{
echo "$0: ${RED}fatal error${NC}"
exit -1
}
# Make sure the user is root (e.g. running as sudo)
if [ "$(id -u)" != "0" ]; then
echo "$0: ${RED}you must be root to configure this box.${NC}"
exit -1
fi
# Parse script options
while getopts d:c:h opt; do
case $opt in
d)
echo "$0: ${GREEN}using database file ${OPTARG}${NC}"
DATABASE=$OPTARG
;;
c)
echo "$0: ${GREEN}using configuration file ${OPTARG}${NC}"
CONFIGURATION=$OPTARG
;;
h)
display_help
exit 0
;;
\?)
exit -1
;;
esac
done
# Make sure we entered a database name
if [ "$DATABASE" == "" ]; then
echo "$0: ${RED}you must specify a database file!${NC}"
display_help
exit -1
fi
# Make sure we entered a configuration file
if [ "$CONFIGURATION" == "" ]; then
echo "$0: ${RED}you must specify a configuration file!${NC}"
display_help
exit -1
fi
# This makes it so every function has a "pre-declaration" of all the functions
main "$@"

View File

@ -1,115 +0,0 @@
$(document).ready(function(){
$('input').first().focus();
show_messages('.error');
show_messages('.message');
show_messages('.success');
$('.challenge_title').click(function(){
$(this).next().slideToggle();
});
});
function check_answer( challenge_id ){
var given_answer = $('#'+challenge_id+' input[name="answer"]').val();
$.ajax(
{ url:"/check_answer",
method: "POST",
data: {
"challenge_id": challenge_id,
"answer": given_answer
},
dataType: "json",
success:(function(response){
if ( response['correct'] == 1){
var new_score = response['new_score'];
say_correct( new_score );
correct_challenge( challenge_id );
//$('#'+ challenge_id + ' #challenge_body').slideUp();
}
if ( response['correct'] == 0){
$.notify('Incorrect!', 'error');
// say_wrong();
}
if ( response['correct'] == -1){
$.notify('You have already submitted this flag!', 'warn');
//say_already();
}
})});
return false;
};
function say_correct( new_score ){
// $('.success').text("You are correct! Nice work!");
// show_message('success');
$.notify('You are correct! Nice work!', 'success');
$('#score').text( String(new_score) );
}
function correct_challenge(challenge_id){
// Flash green
$("#" + challenge_id + " h3").animate({
'background-color': '#eeFFee',
'color': '#348017',
'border': '1px solid #254117;'
}, 500, function(){
$("#" + challenge_id + " h3").animate({
'background-color': '#fbfbfb',
'color': '#585858',
'border': '1px solid #eaeaea;'
}, 3000, function(){}
)});
}
function say_wrong(){
$('.error').text("Incorrect!");
show_message('error');
}
function say_already(){
$('.message').text("You have already submitted this flag!");
show_message('message');
}
function show_message(name){
$('.' + name).slideDown();
window.setTimeout( hide_messages, 2000 );
}
function show_messages(name){
if ( $(name).text() != '' ){
show_message(name.slice(1));
}
}
function hide_messages( ){
$('.message').slideUp();
$('.error').slideUp();
$('.success').slideUp();
}

View File

@ -1,5 +0,0 @@
Put any downloadable files in this directory!
<server_root>/static/downloads

View File

@ -1,5 +0,0 @@
Put any downloadable files in this directory!
<server_root>/static/downloads

View File

@ -1,46 +0,0 @@
#include <ctype.h>
#include <string.h>
#include <stdio.h>
char secret_code[] = "b!Lr}C%R}qSQFG";
void alter_digit(char *s)
{
for (int i = 0; i < strlen(s); ++i)
{
if (isdigit(s[i]))
{
int x = 10;
x += 4 * 3;
x -= 7;
s[i] = s[i] ^ x;
}
}
}
void rotate(char *s)
{
char aux;
int n = strlen(s);
for (int i = 0; i < n / 2; ++i)
{
aux = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = aux;
}
}
int main(int argc, char const *argv[])
{
rotate(secret_code);
for (int i = 0; i < strlen(secret_code); ++i)
{
if (i % 2 == 0)
secret_code[i] -= 2;
else
secret_code[i] += 2;
}
alter_digit(secret_code);
puts(secret_code);
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,291 +0,0 @@
html, body{
font-family: "Helvetica";
height: 99%;
background-color: #ededef;
color: #585858;
padding-bottom: 60px;
}
#page{
max-width: 900px;
min-height: 80%;
background-color: white;
margin-left: auto;
margin-right: auto;
border-radius: 10px;
box-shadow: 0px 0px 20px silver;
padding-bottom: 20px;
}
#content{
margin-top: 80px;
padding: 0px 80px;
padding-bottom: 20px;
}
#title{
padding-top: 20px;
padding-left: 20px;
margin: 30px;
font-size: 240%;
padding-bottom: 20px;
}
.navigation{
width: 95.7%;
list-style: none;
margin: -25px 20px;
margin-left: auto;
margin-right: auto;
height: 35px;
border-bottom: 1px solid silver;
vertical-align: middle;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#feccb1+0,ea5507+79,f17432+92,fb955e+100 */
background: #feccb1; /* Old browsers */
background: -moz-linear-gradient(top, #feccb1 0%, #ea5507 79%, #f17432 92%, #fb955e 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #feccb1 0%,#ea5507 79%,#f17432 92%,#fb955e 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #feccb1 0%,#ea5507 79%,#f17432 92%,#fb955e 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#feccb1', endColorstr='#fb955e',GradientType=0 ); /* IE6-9 */
border-bottom: 2px solid #eaeaea;
}
.navigation li{
min-width: 100px;
display: inline-block;
text-align: center;
vertical-align: middle;
margin: 6px;
}
.navigation li:hover{
text-shadow: 0px 0px 10px black;
}
pre{
border: 1px solid #bebebe;
font-size: 83%;
margin-left: auto;
margin-right: auto;
text-indent: 0px;
text-align: left;
white-space: pre-line;
padding: 10px;
vertical-align: middle !important;
background-color: #fafafa;
/*overflow-x: scroll;*/
color: darkblue;
}
.navigation a{
color: white;
text-shadow: 0px 0px 5px black;
text-transform: uppercase;
font-weight: bold;
font-size: 20px;
text-decoration: none;
vertical-align: middle;
}
#challenges{
border: 1px solid #eaeafa;
border-radius: 5px;
padding: 20px;
width: 700px;
margin-left: auto;
margin-right: auto;
box-shadow: 0px 0px 30px #eaeaea;
}
#challenges input{
border: 1px solid #eaeafa;
border-radius: 5px;
box-shadow: 0px 0px 30px #eaeaea;
}
#scoreboard{
border: 1px solid #eaeafa;
border-radius: 5px;
padding: 20px;
width: 700px;
margin-left: auto;
margin-right: auto;
box-shadow: 0px 0px 30px #eaeaea;
}
input{
border: 1px solid silver;
border-radius: 3px;
/*font-size: 20px;*/
width: 95%;
padding: 3px;
margin: 10px;
}
#login_form{
margin-right: auto;
margin-left: auto;
border: 1px solid #eaeafa;
border-radius: 5px;
padding: 30px 150px;
width: 300px;
margin-left: auto;
margin-right: auto;
box-shadow: 0px 0px 30px #eaeaea;
}
#register_form{
margin-right: auto;
margin-left: auto;
border: 1px solid #eaeafa;
border-radius: 5px;
padding: 30px 150px;
width: 300px;
margin-left: auto;
margin-right: auto;
box-shadow: 0px 0px 30px #eaeaea;
}
.challenge{
border: 1px solid #eaeaea;
padding: 10px;
margin-bottom:10px;
}
.message{
padding: 8px;
position: absolute;
top:154px;
background-color: #FFF8DC;
border: 1px solid #EAC117;
color: #966F33;
width: 883px;
font-weight: bold;
text-align: center;
display: none;
}
.success{
padding: 8px;
position: absolute;
top:154px;
background-color: #eeFFee;
border: 1px solid #254117;
color: #348017;
width: 883px;
font-weight: bold;
text-align: center;
display: none;
}
.error{
padding: 8px;
position: absolute;
top:154px;
width: 883px;
background-color: #FFeeee;
border: 1px solid #9F000F;
color: #C11B17;
margin-left: auto;
margin-right: auto;
font-weight: bold;
text-align: center;
display: none;
}
.challenge_title{
border: 1px solid #eaeaea;
padding: 5px;
margin:-11px;
background-color: #fbfbfb;
cursor: pointer;
}
.challenge form{
margin-top: 30px;
}
.challenge li{
list-style: none;
float: left;
padding-bottom: 10px;
padding-left: 20px;
margin-top: -5px;
}
.challenge_title span{
float: right;
vertical-align: middle;
opacity:.5;
margin-right: 5px;
}
.status{
padding: 8px;
position: absolute;
top:154px;
width: 883px;
text-align: right;
opacity: .5;
z-index: 5;
font-size: smaller;
}
p {
text-indent: 20px;
line-height: 140%;
}
#content a{
color: #56A5EC;
}
#content a:visited{
color: #56A5EC;
}
th{
text-align: left;
text-decoration: underline;
}

View File

@ -1,4 +0,0 @@
#!/bin/bash
ps aux|grep "server.py"|cut -d" " -f6| while read line; do sudo kill -9 $line; done
ps aux|grep "server.py"|cut -d" " -f7| while read line; do sudo kill -9 $line; done

View File

@ -1,10 +0,0 @@
{% extends "base_page.html" %}
{% block content %}
<h2> About </h2>
{% if app_about %}
{{ app_about | safe }}
{% endif %}
{% endblock %}

View File

@ -1,53 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title> {{ app_title }} </title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='stylesheet.css')}}">
<script src="{{ url_for('static', filename='jquery.js' ) }}"></script>
<script src="{{ url_for('static', filename='notify.js' ) }}"></script>
<script src="{{ url_for('static', filename='jquery-ui.min.js' ) }}"></script>
<script src="{{ url_for('static', filename='control.js' ) }}"></script>
</head>
<body>
<div id="page">
<h1 id="title"> {{ app_title }} </h1>
<ul class="navigation">
{% if session.logged_in %}
{% for name, url in app_navigation_logged_in.iteritems() %}
<a href="{{ url }}"> <li> {{ name }} </li> </a>
{% endfor %}
{% else %}
{% for name, url in app_navigation_logged_out.iteritems() %}
<a href="{{ url }}"> <li> {{ name }} </li> </a>
{% endfor %}
{% endif %}
</ul>
{% if session.logged_in %}
<div class="status">
{{ session.username }} <strong>|</strong> <span id="score">{{ session.score }} pts </span>
</div>
{% endif %}
<div class="success">{% if success %}{{ success }}{% endif %}</div>
<div class="error">{% if error %}{{ error }}{% endif %}</div>
<div class="message">{% if message %}{{ message }}{% endif %}</div>
{% for message in get_flashed_messages() %}
<div class="success"> {{ message }} </div>
{% endfor %}
<div id="content">
{% block content %}
{% endblock %}
</div>
</div>
</body>
</html>

View File

@ -1,39 +0,0 @@
{% extends "base_page.html" %}
{% block content %}
<h2> Services </h2>
<div id="challenges">
<div class="challenge" id="0">
<h3 class="challenge_title"> Submit a Flag</h3>
<form action="{{ url_for('challenges_page') }}" id="challenge_body" method="post">
{% if challenges %}
<h4> The running services are... </h4>
{% for challenge in challenges %}
<p style=' text-indent:0px; margin-left:30px;padding-bottom:10px;'>
<span style='font-weight: bold;'> {{ challenge.title }}</span> ( {{ challenge.points }} pts ):
{{ challenge.description | safe }}
<b>Connect on port {{ challenge.port }}. </b>
</p>
{% endfor %}
{% endif %}
<h4> Submit by the command-line via... </h4>
<pre>
curl -k "{{ url }}submit" --data "uuid={{session_value}}&flag=&lt;FLAG&gt;"
</pre>
<input type="hidden" name="challenge_id" value="0">
<input type="text" name="answer">
<input type="submit" value="Submit" onclick="return check_answer(0)">
</form>
</div>
</div>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "base_page.html" %}
{% block content %}
<h2> Login </h2>
<p>
Please log in with a registered username.
</p>
<p>
<strong> Note that the username field is case-sensitive.</strong>
</p>
<br>
<form id="login_form" action="{{ url_for('login') }}" method="post">
<strong>Username:</strong> <input type="text" name="username">
<strong>Password:</strong> <input type="password" name="password">
<input type="submit" value="Login">
</form>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% extends "base_page.html" %}
{% block content %}
<h2> Register </h2>
<p>
Please register the username and password you would like to log in with.
</p>
<p>
<strong> Do not use a password you use for other webites.</strong> Your password is stored in the database as a <a href="https://en.wikipedia.org/wiki/SHA-2">SHA256 hash</a>, and it is still passed to the server over a secure <a href="https://en.wikipedia.org/wiki/HTTPS">HTTPS</a> connection, but the next line of defense is for you, the user, to never use synchronized passwords.
</p>
<br>
<form id="register_form" action="{{ url_for('register') }}" method="post">
<strong>Username:</strong> <input type="text" name="username">
<strong>Password:</strong> <input type="password" name="password">
<strong>Confirm Password:</strong> <input type="password" name="confirm">
<input type="submit" value="Register">
</form>
{% endblock %}

View File

@ -1,37 +0,0 @@
{% extends "base_page.html" %}
{% block content %}
<h2> The Scoreboard </h2>
<p>
How do you stack up against the other players?
</p>
<table id="scoreboard">
<tr>
<th> Place </th>
<th> Name </th>
<th> Score </th>
</tr>
<!-- {% for username in usernames %}
<tr>
<td> &nbsp; &nbsp;{{ loop.index }} </td>
<td> {{ username }} </td>
<td> &nbsp; &nbsp; {{ scores[ loop.index0 ] }} </td>
</tr>
{% endfor %} -->
{% for user in users %}
<tr>
<td> &nbsp; &nbsp;{{ loop.index }} </td>
<td> {{ user["username"] }} </td>
<td> &nbsp; &nbsp; {{ user[ "score" ] }} </td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,107 +0,0 @@
html, body{
font-family: "Helvetica";
height: 100%;
background-color: #ededef;
color: #585858;
}
#page{
max-width: 900px;
min-height: 80%;
background-color: white;
margin-left: auto;
margin-right: auto;
border-radius: 10px;
box-shadow: 0px 0px 20px silver;
}
h1{
padding: 20px;
margin: 30px;
font-size: 240%;
}
.navigation{
width: 95.7%;
list-style: none;
margin: -25px 20px;
margin-left: auto;
margin-right: auto;
height: 35px;
border-bottom: 1px solid silver;
vertical-align: middle;
background: #1e5799;
background: -moz-linear-gradient(top, #1e5799 0%, #207cca 47%, #2989d8 84%, #7db9e8 100%);
background: -webkit-linear-gradient(top, #1e5799 0%,#207cca 47%,#2989d8 84%,#7db9e8 100%);
background: linear-gradient(to bottom, #1e5799 0%,#207cca 47%,#2989d8 84%,#7db9e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#7db9e8',GradientType=0 );
border-bottom: 2px solid #eaeaea;
}
.navigation li{
min-width: 100px;
display: inline-block;
text-align: center;
vertical-align: middle;
margin: 6px;
}
.navigation li:hover{
text-shadow: 0px 0px 10px black;
}
.navigation a{
color: white;
text-shadow: 0px 0px 5px black;
text-transform: uppercase;
font-weight: bold;
font-size: 20px;
text-decoration: none;
vertical-align: middle;
}
#challenges{
border: 1px solid #eaeafa;
border-radius: 5px;
padding: 20px;
margin-top: 50px;
width: 700px;
margin-left: auto;
margin-right: auto;
box-shadow: 0px 0px 30px #eaeaea;
}
input{
border: 1px solid silver;
border-radius: 3px;
font-size: 20px;
width: 95%;
padding: 0px 0px;
margin: 10px;
}
.challenge{
border: 1px solid #eaeaea;
padding: 10px;
margin-bottom:10px;
}
.challenge h2{
border: 1px solid #eaeaea;
padding: 5px;
margin:-11px;
background-color: #fbfbfb;
margin-bottom: 30px
}

Binary file not shown.

BIN
here.db Normal file

Binary file not shown.

4
install_dependencies.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
apt-get -y update && apt-get -y install pip sqlite3
pip install passlib flask colorama image python-resize-image

View File

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY----- -----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDmlaxfGoZDNn3y MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4FWxCUkvF10cS
7Et02k5hYMRaT92p4knBO7WhTOSFSRkNuBN/E7Osuc5J548EzMYg9AoT+XiN6xfn g5QnT2NNFTHYRfJT/KU4rQYQKIOAkXhODqVjpOtHNHkY+2N8GuqECkqUVUXtu2hy
wkrr3rntiGrO+J73/iLkD6/JDdXsFCcIj3ZhhM8eW08cu8on0WRHS96zyji8tFQU H4CN1qmhmF4+qCGfs4UvNDF1rmbTlT1CNlOs5wh8i02acy8A4SVLquybiEWKIbKn
3ADPzNLimJQSEwIxttkRhHHf5xIffG7xFBhzDN3DRO+AdS7yVT+cus5H6n6i9+H9 BCPileFTRG0ZvesVVTOOPBpI2D1xh4kdriBBwx0+J/NM0L0we1MGgqDzjEc9AZ/e
mWuIwZC1JTUXUIGT/DIwRKPQQsnHrUDeibMivusxeJB8Oy9+X4ZwH6q37N+5hI8l wZrhUlKkFWfk3ezU3z1brqDfi1YgzQfboZaXFN7yOzG2tdO4EysGs97DuVno84Ll
cBehjVHqiMAmNcLYsFHXPQLrLvFLujfscIVQE1Zq8ep3UTNmo1/ozBrVdhaYn9qm ZCF/7ZwYgIORP4jVWOkUhtv6yj0uoqrkwQSw7LvoCf6mU2n9zR+xIwPs68xuuTXb
mq3VusrfAgMBAAECggEBALMroiDUD3eyo/NawNcvuq/X7TrvzCHxf7Xym5OWmAsp fLdmSfn5AgMBAAECggEASK9EyMcf3iVLjdbgZ8kj52rH/KJZtanbPw6qhzTH/7rw
XZpXam7X9ElGp5CtqWflZh69Age7VX2RK6YeRvE4w+halAP3FC9G/f2QYtsrMQqc qrmDul2C/OGOMzwHoxgpoytBGWK2MtE9w1oG83pgDktQYyMV664Bl4rfQJ01QrP5
LihssWPdOsMv2C1Pjimafv0XaxjxDV00EhGTUd4mHceNH6Fbu9y9Y7ZE3+dHOcHU tSwoS+wJYMvMP4DdfVZo2IDL3fmno4v8s4+h77TIfI1XGsPvj8PNkIrQwhSH5kw2
CO0QRIUkcJfzndM+X/EeXSRuP6G0+pXdQ+tSKDeH1rNFgTFs17RTmt/36d2JW/O/ x03/s1X0tYgy7LxMgFH2IkDRIGIhxpfEiSKHssGfGp732Wl6HxiBQ0mvni27OgJg
GFLpOfoOtVJ7V8ouaE8B/3wbFbEolv85AoMDBh1Q+v3PSKhUGvbHBDf6SRwyxVQv du7QHQIH1I9mRKBS0pvzR2BYqdvDYiacJifewxe2/WnYGvfCQmam6MXvtupncCLg
aOExMY2Mgdw4R1tAUckKgKktYrUVKjlh4OJ7+Yyy/0ECgYEA+rD2UXoWnqxFEWPr 7jM6P5QgX3cQ0g4STpO752ZHHGTHenRFzu+7B0lBAQKBgQDttTpqed5nv3IR8cNm
J7btiyS6QBIsW9pO3bPkX+lZ6XhCMHlI2lD6dkVwCRUTxP8yPsgiyNkCE9936sCX 7Xyk9+8XP4nReFaDUFOBJxR89e2X+hh4TKFa8MZUMOJjabs06xLRXs76MnRCDHWA
kK3CFBURvJQryoOrdOtCz+fFbtgifmNKQbKLxVLEm/FVJpqRReN6CV4UEdxZnnpV ZXlvicWBQQxl6eCsDiVvRH+I7oioLo8MAyXwUt8dvBHJQA8cWAaLlql3WfAS4GzT
Tkg1h1xw2IB2YedKYXOw3jPDlGkCgYEA63e1xMYK6L4PGdGsswAiUdKxsKflH+Tf S+C7tAs1n5qAppKNsy1ySDeBGQKBgQDGP9BeEQuZBKl4UqQQTW/uEnb5IqtuHSK+
gGTc+6Xrc92IIDD4yZ8Bk8NS1fFwpR82endlqfwn8QhxUsxbuGfg/5Yj3AVRmeLw 66aXRrLUhTpHFXdQu9ti+oYh90BBwKPZZY8WJV28t2U+taHYhaaBWpETBjzfmRPJ
7BQQUYRMCa+iuwRZTMWxZKXHACEQDoC3EPVtWeh5uxzKbd+MAbTHMvUM9STCaz55 NeuYoSoW86C5fn1tg94Y00GfjHLDbSdTxl+DRkNOzufZlCZvKAZskIQZV+Trgtz7
ZU9SeaAsXAcCgYAC5z/DC83tQoN+QxD7IcQ4g1Fg4pT+71VQff/cGIDBEnJ5yz3L Pw7giR774QKBgFtKO2oC7bAobRWJJMMVt8XfVho2k6Y3sfnyUm+KY6ruA9ZW/SjO
wXpVGlLE2CildGspjPnSJ6k9f64M2vQmaczAnMnazECBlOrMbNkWPVHtCbXEjvPS PTWgvHo+3+LQC05ybSKtZ43c7JslD8dEsVNttMVEBw/otxk8wZGu28/p09/LKbKy
NPYnb+D1CWN6EfoyvAKyzxMebdXf3vzT7kQocCqiZ0J3uc0DuepHeIQAWQKBgQC2 TtKx8PAJd0cz69m10KWxMdodVz7Yo9KuFFvh9GAesIZx8lyrEGwQYgiZAoGAee23
fJ1DthRoUjvTz7sfMwBmF3scpNIfCLrqf8D/ypQSxOKlyC5X28JWKS9+nVKmtez7 hpMvMd5nKISTOR+XTrH2kEWdb+zleMzQOcwWopSKAjwWlQXk6VwxcORzlb0YSNWo
tqL0vXabB+cDu1tuLBulGVALSZf3QnljDR2kf3qKmzLr66/lnuUfUpdKk1UlWD4I ijNTEoUs9MObFeMlQ/tirHOyrsakH6VVEBtXGqSeXleIZvmqeFQ90RX9Y2pXvLON
h5zK7C/Dgsmjo3eXLuqepGn5ZxbCFLXyfSo3FpqqawKBgBg7W25kn/bd/aJp3yAY /NwS+35PpEb02HqicNT1Ge0v8xUaOkBPMxPChaECgYBouXMmAGjSY91JYtNOtFnl
gcRgpQksIKg/3l/PrWY0hCAn+a49JgRQWNIFUcWViW93lvrSjdchsZovkGIfMQp4 V1sRLNnCzYfqMmI8Pve1M2waTpCiVi+FLUvd4x4CrmcblMjBJcigM63Ve0ONsbPH
uuynpeQWWVGREI887XdXACI+AkQQProQme2Xh+h4CGy+4o0Q85SxYsFFUeM2oDfg MEIIK8SRmTVOVUA9hqgUySnQaBjCggPBrXldgndNWMHnYKldXqxSQj0pNsVrc6tC
c9e+nPQ/tMMD85mSV69KEhEQ ROgtL6cYIaFSYsPgVIP60w==
-----END PRIVATE KEY----- -----END PRIVATE KEY-----

681
server.py
View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from flask import Flask from flask import Flask
from flask import render_template, request, session, g, url_for, flash, get_flashed_messages, redirect from flask import render_template, request, session, g, url_for, flash, get_flashed_messages, redirect, send_from_directory
import sqlite3 import sqlite3
import json import json
import sys, os import sys, os
@ -9,17 +9,50 @@ from colorama import *
import sys import sys
from threading import Thread from threading import Thread
from time import sleep from time import sleep
from werkzeug.utils import secure_filename
from uuid import uuid4 from uuid import uuid4
from textwrap import dedent
from PIL import Image # needed to resize the image they upload
import re # Used to verify phone numbers
from resizeimage import resizeimage
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.mime.text import MIMEText
from passlib.hash import sha256_crypt from passlib.hash import sha256_crypt
from contextlib import closing from contextlib import closing
CERTIFICATE = 'certificate.crt'
PRIVATE_KEY = 'privateKey.key'
bad_word_found = ""
f = open("badwords.txt")
bad_words = f.read().split('\n')
f.close()
def contains_bad_word( string ):
global bad_word_found
words = string.split(" ")
for word in words:
if word in bad_words:
bad_word_found = word
return True
else:
return False
price_cap = 10000
debug = True debug = True
init( autoreset = True ) init( autoreset = True )
email_from = 'ObjeeTrade'
if (debug): if (debug):
@ -37,19 +70,36 @@ else:
def error( string ): pass def error( string ): pass
def warning( string ): pass def warning( string ): pass
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
def send_email( to_address, subject, message ):
msg = MIMEText(message, 'html')
msg["Subject"] = subject
msg['From'] = email_from
msg['To'] = to_address
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login('objeetrade@gmail.com', 'Go Coast Guard')
server.sendmail(email_from, [to_address], msg.as_string())
server.quit()
# =========================================================================== # ===========================================================================
DATABASE = '/tmp/bears.db' ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
CERTIFICATE = 'certificate.crt' DATABASE = 'database.db'
UPLOAD_FOLDER = 'uploads'
PRIVATE_KEY = 'privateKey.key' PRIVATE_KEY = 'privateKey.key'
SECRET_KEY = 'this_key_needs_to_be_used_for_session_variables' SECRET_KEY = 'this_key_needs_to_be_used_for_session_variables'
if DATABASE == '$DATABASE': # if DATABASE == '/tmp/bearshop_database.db':
error("This server has not yet been configured with a database file!") # error("This server has not yet been configured with a database file!")
exit(-1) # exit(-1)
if CERTIFICATE == '$CERTIFICATE_FILE': if CERTIFICATE == '$CERTIFICATE':
error("This server has not yet been configured with a certificate!") error("This server has not yet been configured with a certificate!")
exit(-1) exit(-1)
@ -61,6 +111,10 @@ app = Flask( __name__ )
app.config.from_object(__name__) app.config.from_object(__name__)
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
def init_db(): def init_db():
with closing(connect_db()) as db: with closing(connect_db()) as db:
with app.open_resource('schema.sql', mode='r') as f: with app.open_resource('schema.sql', mode='r') as f:
@ -70,6 +124,7 @@ def init_db():
def connect_db(): def connect_db():
return sqlite3.connect( app.config['DATABASE'] ) return sqlite3.connect( app.config['DATABASE'] )
@app.before_request @app.before_request
def before_request(): def before_request():
g.db = connect_db() g.db = connect_db()
@ -85,200 +140,550 @@ def teardown_request(exception):
@app.route("/") @app.route("/")
def index(): def index():
if not ( session['logged_in'] ): if not 'logged_in' in session: return redirect('login')
return redirect('login') cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
return redirect('products')
@app.route("/login", methods=["GET", "POST"]) @app.route("/login", methods=["GET", "POST"])
def login(): def login():
error = "" email = password = ""
if request.method == "POST": if request.method == "POST":
cur = g.db.execute('select email, password from users') cur = g.db.execute('select email, password, uuid from users')
# username, password_hash users = dict(( row[0].lower(), row[1] ) for row in cur.fetchall())
users = dict(( row[0], row[1] ) for row in cur.fetchall())
print "You POSTed", users
if not request.form['email'] in users.iterkeys(): email = request.form['email'].lower()
password = request.form['password']
if ( email == "" ):
flash("You need to enter an e-mail address!")
elif not email.endswith("uscga.edu"):
flash("This does not look like a valid USCGA EDU e-mail address!")
elif not email in users.iterkeys():
flash('This e-mail is not in the database!') flash('This e-mail is not in the database!')
else: else:
if ( password == "" ):
if not ( sha256_crypt.verify( request.form['password'], users[request.form['username']] ) ): flash("You need to enter a password!")
elif not ( sha256_crypt.verify( request.form['password'], users[email] ) ):
flash("Incorrect password!") flash("Incorrect password!")
else: else:
session_login( request.form['email'] ) session_login( request.form['email'] )
return redirect( "verify" )
return redirect( "about" ) return render_template( 'login.html', email=email, password = password )
return render_template( 'login.html' )
@app.route("/register", methods=["GET", "POST"]) @app.route("/register", methods=["GET", "POST"])
def register(): def register():
cur = g.db.execute('select email from users') cur = g.db.execute('select email from users')
usernames = [row[0].lower() for row in cur.fetchall() ]
usernames = [row[0] for row in cur.fetchall() ] email = password = confirm = ""
error = ""
if request.method == "POST": if request.method == "POST":
email = request.form['email'].lower()
password = request.form['password']
confirm = request.form['confirm']
if unicode(request.form['email']) in usernames: if unicode(request.form['email']) in usernames:
flash('This e-mail is already registered!') flash('This e-mail is already registered!')
elif (not request.form['email'].endswith('@uscga.edu')):
flash('You must use an "@uscga.edu" domain e-mail!')
elif (request.form['password'] == ""): elif (request.form['password'] == ""):
flash("You must supply a password!") flash("You must supply a password!")
elif request.form['password'] != request.form['confirm']: elif request.form['password'] != request.form['confirm']:
flash('Your passwords do not match!') flash('Your passwords do not match!')
else: else:
# I use this for command-line submission... # I use this for command-line submission...
identifier = str(uuid4()) identifier = str(uuid4())
cur = g.db.execute('insert into users (email, password, uuid) values ( ?, ?, ? )', [ cur = g.db.execute('insert into users (email, name, password, uuid, your_products, room, phone, verified) values ( ?, ?, ?, ?, ?, ?, ?, ? )', [
request.form['email'], email,
" ".join( [email.split(".")[0].title(), email.split(".")[2].split("@")[0].title() ]),
sha256_crypt.encrypt( request.form['password']), sha256_crypt.encrypt( request.form['password']),
identifier # and a completely unique idenitifier identifier, # a completely unique idenitifier
"", # They currently have no products being sold
"", # They can enter their room number later
"", # They can enter their phone number later
0 # verified? ...since they just registered, no!
] ) ] )
g.db.commit() g.db.commit()
flash("Hello " + request.form['username'] + ", you have successfully registered!")
session_login( request.form['email'] ) session_login( request.form['email'] )
return redirect( "challenges" ) send_verification_link()
return redirect( "verify" )
return render_template( 'register.html', error = error )
# @app.route("/scoreboard")
# def scoreboard():
# cur = g.db.execute('select username, score from users order by score desc, last_submission asc')
# response = cur.fetchall()
# users = [ { "username": row[0], "score": row[1] } for row in response] return render_template( 'register.html', email = email, password = password, confirm = confirm )
@app.route("/send_verification_link")
def send_verification_link():
# return render("scoreboard.html", users = users ) if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
# @app.route("/logout") if ( session['logged_in'] ):
# def logout():
# session_logout() email = session['email']
# return redirect("about") name = session['name']
cur = g.db.execute('select uuid, verified from users where email = (?)', [email])
# @app.route("/") identifier, verified = cur.fetchone()
# @app.route("/about") if ( verified == 1 ):
# def about(): return render("about.html", app_about=configuration['app_about']) flash("Your e-mail address has already been verified.")
return redirect('products')
else:
send_email( email,
'Your Registration Verification Code',
render_template("verification_email.html", identifier = identifier, name = name
))
# @app.route("/challenges") # THIS IS ONLY FOR TESTING....
# def challenges_page(): send_email( 'johnhammond010@gmail.com',
'Your Registration Verification Code',
render_template("verification_email.html", identifier = identifier, name = name
))
# if not ( session['logged_in'] ): flash("An e-mail has been sent!")
# return render("login.html", error = "You must log in to be able to see the challenges!") return redirect("verify")
# try:
# cur = g.db.execute('select uuid from users where username =?',
# [ session['username'],] )
# uuid = cur.fetchone()[0]
# except Exception as e:
# print error(e.message)
# uuid = ''
# return render("challenges.html", challenges = configuration['services'], url=request.url_root, session_value = uuid )
# @app.route("/check_answer", methods=["GET", "POST"])
# def check_answer():
# global correct_answers
# if request.method == "POST":
# if request.form['answer'] in session['solved_challenges']:
# return json.dumps({'correct': -1});
# if ( request.form['answer'] in correct_answers.keys() ):
# flag = request.form['answer']
# new_score = int(session['score']) + correct_answers[flag]
# cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')) where username = (?)", [
# new_score,
# session['username']
# ] );
# session['solved_challenges'].append( request.form['answer'] )
# session['score'] = new_score
# g.db.commit();
# return json.dumps({'correct': 1, 'new_score': new_score});
# else:
# return json.dumps({'correct': 0});
# @app.route("/submit", methods=[ "POST" ])
# def submit():
# global correct_answers
# if request.method == "POST":
# if ( request.form['flag'] in correct_answers.keys() ):
# flag = request.form['flag']
# cur = g.db.execute('select score, solved_challenges from users where uuid = (?)',
# [ request.form['uuid'], ])
# current_score, solved_challenges = cur.fetchone() @app.route("/products")
def products():
# solved_challenges = solved_challenges.split() if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
cur = g.db.execute('select name, picture, price, uuid from products')
products = [ [ row[0], row[1], row[2], row[3] ] for row in cur.fetchall()[::-1]]
# if ( flag in solved_challenges ): return render_template("products.html", products = products)
# return 'You already submitted this flag!\n'
# print solved_challenges @app.route("/products/<uuid>")
def product(uuid):
# new_score = current_score + correct_answers[flag] if not 'logged_in' in session: return redirect('login')
# solved_challenges.append( flag + " " ) cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
# cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')), solved_challenges = (?) where uuid = (?)", [ verified = cur.fetchone()[0]
# new_score, if not verified:
# ' '.join(solved_challenges), return redirect('verify')
# request.form['uuid']
# ] );
# # session['solved_challenges'].append( request.form['flag'] ) cur = g.db.execute('select name, price, picture, description, seller, interested_people from products where uuid = (?)', [uuid] )
# session['score'] = new_score name, price, picture, description, seller, interested_people = cur.fetchone()
# g.db.commit();
# # return json.dumps({'correct': 1, 'new_score': new_score}); cur = g.db.execute('select uuid from users where name = (?)', [seller] )
# return 'Correct!\n'; seller_uuid = cur.fetchone()[0]
# else:
# # return json.dumps({'correct': 0});
# return 'Incorrect!\n';
def session_login( username ):
interested_people = [ person for person in interested_people.split('\n') if person ]
return render_template('item.html', name=name, picture=picture, description=description, seller=seller, price=price, uuid=uuid, interested_people =interested_people, seller_uuid = seller_uuid)
@app.route("/remove_product/<uuid>")
def remove_product(uuid):
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
cur = g.db.execute('select seller from products where uuid = (?)', [uuid])
product_seller = cur.fetchone()[0]
flash("You were successfully logged in!") if ( product_seller == session['name'] ):
cur = g.db.execute('delete from products where uuid = (?)', [uuid])
g.db.commit()
cur = g.db.execute('select your_products from users where email = (?)', [session['email']])
your_products = cur.fetchone()[0];
your_products = your_products.replace(uuid,'')
your_products = your_products.strip()
print your_products
cur = g.db.execute('update users set your_products = (?) where email = (?)', [
your_products,
session['email']
])
g.db.commit()
# cur = g.db.execute('select solved_challenges, score from users where username = (?)', flash("The product has been successfully removed.")
# [username]) return redirect("products")
else:
return "This product does not belong to you. Nice try, but no."
# solved_challenges, score = cur.fetchone() @app.route("/verify", methods=["GET", "POST"])
def verify():
identifier = ""
if not 'logged_in' in session: return redirect('login')
else:
cur = g.db.execute('select uuid, verified from users where email = (?)', [session['email']])
uuid, verified = cur.fetchone()
if ( verified ):
# flash("Your e-mail address has already been verified.")
return redirect('products')
else:
if ( request.method == "GET" ):
identifier = request.args.get('identifier')
if ( request.method == "POST" ):
identifier = request.form['identifier']
if ( identifier ):
if ( identifier == uuid ):
cur = g.db.execute("update users set verified = (?) where email = (?)", [
1,
session['email']
] );
g.db.commit();
return redirect('products')
else:
flash("Incorrect verification code.")
return render_template( 'verify.html', identifier = identifier)
@app.route("/search")
def search():
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
return render_template("search.html")
@app.route("/edit/<uuid>", methods=["GET", "POST"])
def edit(uuid):
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
if ( request.method == "GET" ):
cur = g.db.execute('select name, price, picture, description, seller from products where uuid = (?)', [uuid] )
name, price, picture, description, seller = cur.fetchone()
return render_template('edit.html', name=name, picture=picture, description=description, seller=seller, price=price[1:], uuid=uuid)
if ( request.method == "POST" ):
name = request.form['name']
# uuid = request.form['uuid']
picture = request.form['picture']
cur = g.db.execute('select seller from products where uuid = (?)', [uuid])
product_seller = cur.fetchone()[0]
if ( product_seller == session['name'] ):
# picture = request.form['picture']
price = request.form['price']
name = request.form['name']
description = request.form['description']
if (contains_bad_word(price.lower()) or \
contains_bad_word(description.lower()) or \
contains_bad_word(name.lower())
):
flash("Detected a bad word: '" + bad_word_found + "'. Not accepting that.")
return redirect(url_for('edit', uuid=uuid))
if ( name == "" ):
flash("Please enter a name of the product!")
return redirect(url_for('edit', uuid=uuid))
elif ( price == "" ):
flash("Please enter the price of the product in dollars!")
return redirect(url_for('edit', uuid=uuid))
elif ( description == "" ):
flash("Please enter a description of your product!")
return redirect(url_for('edit', uuid=uuid))
elif ( '.' in price ):
if ( price[-3] != '.' ):
flash("That does not look like a valid price!")
return redirect(url_for('edit', uuid=uuid))
try:
price_number = round(float(price),2)
warning(str(price_number))
if (price_number != abs(price_number)):
flash("That does not look like a valid price!")
return redirect(url_for('edit', uuid=uuid))
elif ( price_number >= price_cap ):
flash("Please enter a cost less than $" + str(price_cap))
return redirect(url_for('edit', uuid=uuid))
else:
# We should be good to process the form
price_number = '$' + format(price_number, '.2f')
if 'picture' not in request.files:
pass # They don't have to update the picture
else:
file = request.files['picture']
if file and allowed_file(file.filename):
filename = secure_filename(str(uuid4()) + "." + file.filename.split('.')[-1])
save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(save_location)
p = Image.open(save_location)
try:
p = resizeimage.resize_cover(p, (350, 350))
except:
pass
p.save(save_location)
# return redirect(url_for('uploaded_file', filename=filename))
picture = (url_for('uploaded_file', filename=filename))
cur = g.db.execute("update products set name = (?), picture = (?), description = (?), price = (?) where uuid = (?)", [
name,
str(picture),
description,
price_number,
uuid
] );
g.db.commit()
except:
# print price
flash("That does not look like a valid price!")
return redirect(url_for('edit', uuid=uuid))
else:
flash("This is not your own product!")
return redirect(request.referrer)
return redirect(url_for('product', uuid=uuid))
@app.route("/profile/<uuid>", methods= ["GET", "POST"])
def profile(uuid):
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified, room, phone from users where uuid = (?)', [session['uuid']])
verified, room, phone = cur.fetchone()
if not verified:
return redirect('verify')
cur = g.db.execute('select email, your_products from users where uuid = (?)', [uuid])
email, your_products = cur.fetchone()
name = " ".join( [email.split(".")[0].title(), email.split(".")[2].split("@")[0].title() ])
your_products = your_products.split(" ")
products = []
for product in your_products:
cur = g.db.execute('select name from products where uuid = (?)', [product])
product_name = cur.fetchone()
if product_name != None:
product_name = product_name[0]
products.append( [product_name, product] )
if ( request.method == "POST" ):
if uuid == session['uuid']:
phone = room = ""
phone = request.form['phone']
room = request.form['room']
name = session['name']
if ( not re.search('\d\d\d-\d\d\d-\d\d\d\d', phone) ):
flash("Please enter the phone number in the form: ###-###-####")
return render_template("profile.html", name = name, products = products, phone = phone, room = room )
elif ( not ( re.search('E\d\d\d$', room) or re.search('\d\d\d\d$', room) ) ) :
flash("Please enter a proper room number, #### or E###.")
return render_template("profile.html", name = name, products = products, phone = phone, room = room )
else:
flash("Your profile has been saved successfully!")
cur = g.db.execute('update users set room = (?), phone = (?) where uuid = (?)', [
room,
phone,
session['uuid']
])
g.db.commit()
return render_template("profile.html", name = name, products = products, phone = phone, room = room )
return render_template("profile.html", name = name, products = products, room = room, phone = phone )
@app.route("/show_interest/<seller>/<uuid>")
def show_interest(seller, uuid):
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified, room, phone from users where uuid = (?)', [session['uuid']])
verified, room, phone = cur.fetchone()
if not verified:
return redirect('verify')
cur = g.db.execute('select interested_people, name from products where uuid = (?)', [uuid])
interested_people, product_name = cur.fetchone();
interested_people += '\n' + session['name']
interested_people = interested_people.strip()
cur = g.db.execute('update products set interested_people = (?) where uuid = (?)', [
interested_people,
uuid
])
g.db.commit()
cur = g.db.execute('select email from users where name = (?)', [seller])
sellers_email = cur.fetchone()[0]
send_email( sellers_email,
'Someone is interested in your product!',
render_template("interest_email.html",
name = session['name'],
product_name = product_name,
room = room,
phone = phone,
email = session['email']
))
flash("You showed interest in this product! An e-mail has been sent to notify the seller.")
return redirect( request.referrer )
@app.route("/sell", methods=["GET", "POST"])
def sell():
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
name = picture = description = price = ""
if ( request.method == "POST" ):
name = request.form['name']
price = request.form['price']
description = request.form['description']
if ( contains_bad_word(price.lower()) or \
contains_bad_word(description.lower()) or \
contains_bad_word(name.lower())
):
flash("Detected a bad word: '" + bad_word_found + "'. Not accepting that.")
return render_template("sell.html", name=name, price = price, description = description)
if ( name == "" ):
flash("Please enter a name of the product!")
return render_template("sell.html", name=name, price = price, description = description)
elif ( price == "" ):
flash("Please enter the price of the product in dollars!")
return render_template("sell.html", name=name, price = price, description = description)
elif ( description == "" ):
flash("Please enter a description of your product!")
return render_template("sell.html", name=name, price = price, description = description)
elif ( '.' in price ):
if ( price[-3] != '.' ):
flash("That does not look like a valid price!")
return render_template("sell.html", name=name, price = price, description = description)
try:
price_number = round(float(price),2)
warning(str(price_number))
except:
print price
flash("That does not look like a valid price!")
return render_template("sell.html", name=name, price = price, description = description)
if (price_number != abs(price_number)):
flash("That does not look like a valid price!")
return render_template("sell.html", name=name, price = price, description = description)
elif ( price_number >= price_cap ):
flash("Please enter a cost less than $" + str(price_cap))
return render_template("sell.html", name=name, price = price, description = description)
else:
# We should be good to process the form
price_number = '$' + format(price_number, '.2f')
if 'picture' not in request.files:
pass # We make it optional for them to upload files, remember?
else:
file = request.files['picture']
if file and allowed_file(file.filename):
filename = secure_filename(str(uuid4()) + "." + file.filename.split('.')[-1])
save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(save_location)
p = Image.open(save_location)
try:
p = resizeimage.resize_cover(p, (350, 350))
except:
pass
p.save(save_location)
# return redirect(url_for('uploaded_file', filename=filename))
picture = (url_for('uploaded_file', filename=filename))
uuid = str(uuid4())
cur = g.db.execute('insert into products (name, picture, description, price, seller, interested_people, uuid) values ( ?, ?, ?, ?, ?, ?, ? )', [
name,
str(picture),
description,
price_number, # Since you are just selling this product, no one is interested yet!
session['name'],
"",
uuid
] );
g.db.commit()
cur = g.db.execute('select your_products from users where email = (?)', [session['email']])
your_products = cur.fetchone()[0];
your_products += ' ' + uuid
your_products = your_products.strip()
print your_products
cur = g.db.execute('update users set your_products = (?) where email = (?)', [
your_products,
session['email']
])
g.db.commit()
return redirect('products')
return render_template("sell.html", name=name, price = price, description = description)
@app.route("/log_out", methods=["GET", "POST"])
def log_out():
session_logout()
return redirect('login')
def session_login( email ):
flash("You have been successfully logged in!")
session['logged_in'] = True session['logged_in'] = True
# session['username'] = username session['email'] = email.lower()
# session['score'] = score cur = g.db.execute('select uuid from users where email = (?)', [session['email']])
# session['solved_challenges'] = [] uuid = cur.fetchone()
if uuid != None: uuid = uuid[0];
session['uuid'] = uuid
session['name'] = " ".join( [email.split(".")[0].title(), email.split(".")[-2].split("@")[0].title() ])
def session_logout(): def session_logout():
flash("You have been successfully logged out.") flash("You have been successfully logged out.")
session['logged_in'] = False session.pop('logged_in')
# session.pop('username') session.pop('email')
# session.pop('score') session.pop('uuid')
session.pop('name')
if ( __name__ == "__main__" ): if ( __name__ == "__main__" ):
context = (CERTIFICATE, PRIVATE_KEY) context = (CERTIFICATE, PRIVATE_KEY)
app.run( host="0.0.0.0", debug=True, ssl_context=context, threaded=True) app.run( host="0.0.0.0", debug=True, ssl_context=context, port = 444, threaded = True )

View File

@ -428,7 +428,10 @@ def edit(uuid):
save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename) save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(save_location) file.save(save_location)
p = Image.open(save_location) p = Image.open(save_location)
p = resizeimage.resize_cover(p, (350, 350)) try:
p = resizeimage.resize_cover(p, (350, 350))
except:
pass
p.save(save_location) p.save(save_location)
# return redirect(url_for('uploaded_file', filename=filename)) # return redirect(url_for('uploaded_file', filename=filename))
picture = (url_for('uploaded_file', filename=filename)) picture = (url_for('uploaded_file', filename=filename))
@ -604,7 +607,10 @@ def sell():
save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename) save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(save_location) file.save(save_location)
p = Image.open(save_location) p = Image.open(save_location)
p = resizeimage.resize_cover(p, (350, 350)) try:
p = resizeimage.resize_cover(p, (350, 350))
except:
pass
p.save(save_location) p.save(save_location)
# return redirect(url_for('uploaded_file', filename=filename)) # return redirect(url_for('uploaded_file', filename=filename))
picture = (url_for('uploaded_file', filename=filename)) picture = (url_for('uploaded_file', filename=filename))

View File

@ -44,14 +44,23 @@ function install_dependencies(){
apt-get -y install $DEPENDENCIES || panic apt-get -y install $DEPENDENCIES || panic
} }
function create_certificate(){ function create_certificate(){
echo "$0: ${GREEN}creating HTTPS certificates...${NC}" echo "$0: ${GREEN}creating HTTPS certificates...${NC}"
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout $PRIVATEKEY_FILE -out $CERTIFICATE_FILE || panic openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout $PRIVATEKEY_FILE -out $CERTIFICATE_FILE <<EOF || panic
US
CT
New London
United States Coast Guard Academy
Cyber Team
github.com/JohnHammond
johnhammond010@gmail.com
EOF
sed "0,/\$CERTIFICATE_FILE/{s/\$CERTIFICATE_FILE/$CERTIFICATE_FILE/}" $SERVER_FILE > $NEW_SERVER_FILE || panic sed "0,/\$CERTIFICATE_FILE/{s/\$CERTIFICATE_FILE/$CERTIFICATE_FILE/}" $SERVER_FILE > $NEW_SERVER_FILE || panic
sed -i "0,/\$PRIVATEKEY_FILE/{s/\$PRIVATEKEY_FILE/$PRIVATEKEY_FILE/}" $NEW_SERVER_FILE || panic sed -i "0,/\$PRIVATEKEY_FILE/{s/\$PRIVATEKEY_FILE/$PRIVATEKEY_FILE/}" $NEW_SERVER_FILE || panic
} }
@ -61,7 +70,7 @@ function create_database(){
rm -f $DATABASE rm -f $DATABASE
sqlite3 $DATABASE < $SCHEMA_FILE || panic sqlite3 $DATABASE < $SCHEMA_FILE || panic
chown $CURRENT_USER $DATABASE || panic chown $CURRENT_USER $DATABASE
sed -i '0,/\$DATABASE/{s/\$DATABASE/'${DATABASE//\//\\/}'/}' $NEW_SERVER_FILE || panic sed -i '0,/\$DATABASE/{s/\$DATABASE/'${DATABASE//\//\\/}'/}' $NEW_SERVER_FILE || panic
} }

View File

@ -143,7 +143,6 @@ a:visited{
right: 0; right: 0;
margin: auto; margin: auto;
} }
#vertical{ #vertical{

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
static/icon.xcf Normal file

Binary file not shown.

View File

@ -3,8 +3,9 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>USCGA BearShop</title> <title>ObjeeTrade</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/master.css' ) }}"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/master.css' ) }}">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico' ) }}" type="image/x-icon">
<script src="{{ url_for('static', filename='js/jquery.js' ) }}"></script> <script src="{{ url_for('static', filename='js/jquery.js' ) }}"></script>
<script src="{{ url_for('static', filename='js/notify.js' ) }}"></script> <script src="{{ url_for('static', filename='js/notify.js' ) }}"></script>
<script src="{{ url_for('static', filename='js/jquery-ui.min.js' ) }}"></script> <script src="{{ url_for('static', filename='js/jquery-ui.min.js' ) }}"></script>
@ -34,5 +35,9 @@
{% endblock %} {% endblock %}
<div style="position:fixed;bottom:10px;width:100%;text-align:center;color:rgba(0,0,0,.3);z-index: -5">
<small> This web application was developed solely by John Hammond</small>
<div>
</body> </body>
</html> </html>

View File

@ -2,8 +2,8 @@
<head></head> <head></head>
<body> <body>
<h2>You got someone's interest on <a href="http://uscgabearshop"> <h2>You got someone's interest on <a href="https://www.objeetrade.com">
BearShop!</a></h2> ObjeeTrade!</a></h2>
<p> <p>
{{name}} showed an interest in your product, "{{product_name}}". {{name}} showed an interest in your product, "{{product_name}}".
@ -19,7 +19,7 @@
</ul> </ul>
<p> <p>
Thanks for using <a href="http://uscgabearshop">BearShop!</a> I hope you are enjoying its services. If you have any questions, concerns, or comments, be sure to let me know! Thanks for using <a href="https://www.objeetrade.com/">ObjeeTrade!</a> I hope you are enjoying its services. If you have any questions, concerns, or comments, be sure to let me know!
</p> </p>

View File

@ -5,9 +5,9 @@
<div id="login_box_background"></div> <div id="login_box_background"></div>
<div id="login_box"> <div id="login_box">
<h1>Welcome the USCGA BearShop!</h1> <h1>Welcome to ObjeeTrade!</h1>
<p> <p>
Please login below with your EDU e-mail and your BearShop password. Please login below with your EDU e-mail and your ObjeeTrade password.
</p> </p>
<form method="POST"> <form method="POST">

View File

@ -3,7 +3,7 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title> Login -- USCGA BearShop</title> <title> Login -- ObjeeTrade</title>
<link rel="stylesheet" type="text/css" href="../static/css/master.css"> <link rel="stylesheet" type="text/css" href="../static/css/master.css">
</head> </head>
<body> <body>
@ -12,9 +12,9 @@
<div id="login_box_background"></div> <div id="login_box_background"></div>
<div id="login_box"> <div id="login_box">
<h1>Welcome the USCGA BearShop!</h1> <h1>Welcome to ObjeeTrade!</h1>
<p> <p>
Please login below with your EDU e-mail and your BearShop password. Please login below with your EDU e-mail and your ObjeeTrade password.
</p> </p>
<form> <form>

View File

@ -6,7 +6,7 @@
<h1>Register an Account</h1> <h1>Register an Account</h1>
<p> <p>
To register an account with BearShop, we'll need you to supply your EDU e-mail account and decide on a secure password. To register an account with ObjeeTrade, we'll need you to supply your EDU e-mail account and decide on a secure password.
</p> </p>
<form method="POST"> <form method="POST">
<input type="text" name="email" placeholder="E-mail" value="{{email}}"> <input type="text" name="email" placeholder="E-mail" value="{{email}}">

26
templates/rides.html Normal file
View File

@ -0,0 +1,26 @@
{% extends "base_page.html" %}
{% block content %}
<div id="vertical">
<div style="text-align:center">
{% if products|length == 0 %}
<h2 style="color:silver; text-align:center">
There are currently no rides available. :(
</h2>
{% else %}
{% for ride in rides %}
<a href="{{ url_for('ride', uuid=ride[5] )}}">
<div class="ride">
<h2> {{ ride[0] }} <span>to {{ ride[1] }} </span>.</h2>
{{ ride[2] }} passengers on {{ ride[3] }}
</div></a>
{% endfor %}
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -2,8 +2,12 @@
<head></head> <head></head>
<body> <body>
<h2>Thank you for registering with <a href="http://uscgabearshop"> <h1>Thank you for registering with <a href="https://www.objeetrade.com">
BearShop!</a></h2> ObjeeTrade!</a></h1>
<p>
<b> Hi {{name}}! </b>
</p>
<p> <p>
To complete your registraton, you must submit this verification code: To complete your registraton, you must submit this verification code:
@ -15,12 +19,12 @@
You can do this more quickly by simply clicking this link: You can do this more quickly by simply clicking this link:
</p> </p>
<p> <p>
<a href="http://uscgabearshop.com/verify?identifier={{identifier}}"> http://uscgabearshop.com/verify?identifier={{identifier}}</a> <a href="https://www.objeetrade.com/verify?identifier={{identifier}}"> https://www.objeetrade.com/verify?identifier={{identifier}}</a>
</p> </p>
<p> <p>
Thanks for registering, and I hope you enjoy <a href="http://uscgabearshop"> Thanks for registering, and I hope you enjoy <a href="https://www.objeetrade.com">
BearShop!</a> ObjeeTrade!</a>
</p> </p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB