diff --git a/README.md b/README.md index 602439a..12358ed 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,16 @@ # Secure Coding with Python. -## Chapter 2: SQL Injection -### Fix part 3 -An even better approach is to use an ORM, in this case we set up SQLAlchemy, by using the standard methods the ORM will do the sanitization so we don't need to worry about it. +## Chapter 3: Weak Password Storage +### Requirement +Now that we know our DB is working, it's time to start creating some users. We should have a signup account that create the user. -**Note**: Most ORMs in some special use cases can still allow SQL Injections to happen, if you are using non-standard methods, review the ORMs security guidelines and test your application. +### Development +We create a signup page, a user model and start taking in new users. -**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/3.1-weak-password-storage/code)** +### Vulnerability +Since we are not thoughtful on what we are doing, we are storing the passwords in plain text. Meaning anyone with access to our DB, or exploiting an SQL injection, as shown in previous chapter, can easily get any user password. + +**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/3.1-weak-password-storage/fix)** ## Index ### 1. Vulnerable Components diff --git a/marketplace/__init__.py b/marketplace/__init__.py index 3b1896e..d4a8872 100644 --- a/marketplace/__init__.py +++ b/marketplace/__init__.py @@ -25,7 +25,8 @@ def create_app(test_config=None): db.init_app(app) migrate.init_app(app, db) - from . import listings + from . import listings, users app.register_blueprint(listings.bp) + app.register_blueprint(users.bp) return app \ No newline at end of file diff --git a/marketplace/models.py b/marketplace/models.py index f234b22..1161df4 100644 --- a/marketplace/models.py +++ b/marketplace/models.py @@ -1,5 +1,12 @@ from . import db +class User(db.Model): + __tablename__ = 'users' + id = db.Column(db.Integer, primary_key=True) + full_name = db.Column(db.String(100)) + email = db.Column(db.String(100)) + password = db.Column(db.String(100)) + class Listing(db.Model): __tablename__ = 'listings' diff --git a/marketplace/templates/users/signup.html b/marketplace/templates/users/signup.html new file mode 100644 index 0000000..0e7d108 --- /dev/null +++ b/marketplace/templates/users/signup.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% block header %} +

{% block title %}Create new user{% endblock %}

+{% endblock %} + +{% block content %} +
+ + + + + + + +
+{% endblock %} \ No newline at end of file diff --git a/marketplace/templates/users/signup_success.html b/marketplace/templates/users/signup_success.html new file mode 100644 index 0000000..d61c5ac --- /dev/null +++ b/marketplace/templates/users/signup_success.html @@ -0,0 +1,9 @@ +{% extends 'base.html' %} + +{% block header %} +

{% block title %}Successful user creation{% endblock %}

+{% endblock %} + +{% block content %} + Successfully created user for {{ user.full_name }} with email {{ user.email }} +{% endblock %} \ No newline at end of file diff --git a/marketplace/users.py b/marketplace/users.py new file mode 100644 index 0000000..3d7e54f --- /dev/null +++ b/marketplace/users.py @@ -0,0 +1,20 @@ +from flask import Blueprint, request, render_template + +from . import db +from .models import User + +bp = Blueprint('users', __name__, url_prefix='/user') + +@bp.route('/signup', methods=('GET', 'POST')) +def sign_up(): + if request.method == 'POST': + user = User( + full_name=request.form['full_name'], + email=request.form['email'], + password=request.form['password'], + ) + db.session.add(user) + db.session.commit() + + return render_template('users/signup_success.html', user=user) + return render_template('users/signup.html') \ No newline at end of file diff --git a/migrations/versions/67168ab4efaa_.py b/migrations/versions/67168ab4efaa_.py new file mode 100644 index 0000000..0249bb8 --- /dev/null +++ b/migrations/versions/67168ab4efaa_.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: 67168ab4efaa +Revises: d018d799acf7 +Create Date: 2019-07-19 12:26:57.013800 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '67168ab4efaa' +down_revision = 'd018d799acf7' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('users', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('full_name', sa.String(length=100), nullable=True), + sa.Column('email', sa.String(length=100), nullable=True), + sa.Column('password', sa.String(length=100), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('users') + # ### end Alembic commands ###