Not long ago I published a post about facial recognition and how to evade it, because I was working with it due to a CTF. I'm playing with the same library in order to create a 2nd login page that requires a picture of the administrator. I wanted a simple POC, so I used a simple Flask structure for it. First we need a basic login setup in python, for regular application you should probably use a decent DB managing, you guys know more about that. For know let's see the scratch, first of all we are going to need a lot of things to make this work:
#app.py from flask import Flask from flask import Flask, flash, redirect, render_template, request, session, abort from flask import redirect import face_recognition from PIL import Image, ImageDraw import numpy as np import os ...
Now let's define routes
@app.route('/') def home(): if not session.get('logged_in'): return render_template('login.html') else: #this is a dummy page for my trials :) return render_template('dashboard.html') @app.route('/login', methods=['POST']) def do_admin_login(): #me: I work in security. #also me: if request.form['password'] == 'password' and request.form['username'] == 'user': #this is going to be our first change, #we are using an image-upload page in between return render_template('showmethatprettyface.html') else: return home()
showmethatprettyface.html we are using a simple image upload setup
<div class="container"> <div class="row"> <div class="col"> <h1>Upload an image</h1> <hr> <form action="/showmethatprettyface" method="POST" enctype="multipart/form-data"> <div class="form-group"> <label>Select image</label> <div class="custom-file"> <input type="file" class="custom-file-input" name="image" id="image"> <label class="custom-file-label" for="image">Select image...</label> </div> </div> <button type="submit" class="btn btn-primary">Upload</button> </form> </div> </div> </div>
This way back in our app.py we can retrieve the uploaded picture using a new route
@app.route("/showmethatprettyface", methods=["GET", "POST"]) def upload_image(): if request.method == "POST": if request.files: picture = request.files["image"]
Now, the funny part is using this
picture for face recognition. For that, we need known pictures, first.
import stuff blah blah ... # Load a second sample picture and learn how to recognize it. salita_image = face_recognition.load_image_file("salita.jpg") salita_face_encoding = face_recognition.face_encodings(salita_image) # Create arrays of known face encodings and their names known_face_encodings = [ salita_face_encoding ] known_face_names = [ "Salita" ]
Salita's gonna be our known user. Now again in our route we do the rest of the logic which, in fact, is explained here.
@app.route("/showmethatprettyface", methods=["GET", "POST"]) ... # Load an image with an unknown face unknown_image = face_recognition.load_image_file(foto) # Find all the faces and face encodings in the unknown image face_locations = face_recognition.face_locations(unknown_image) face_encodings = face_recognition.face_encodings(unknown_image, face_locations) # Convert the image to a PIL-format image pil_image = Image.fromarray(unknown_image) # Create a Pillow ImageDraw Draw instance to draw with draw = ImageDraw.Draw(pil_image) # Loop through each face found in the unknown image for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings): # See if the face is a match for the known face(s) matches = face_recognition.compare_faces(known_face_encodings, face_encoding) if True in matches: return render_template('successfulldummypage.html') else: return render_template('booodummypage.html')
So if in the picture the user uploads in the page appears Salita the
successfulldummypage.html will load and either way
booodummypage.html. If I was Salita I would be very careful of the pictures of me in social networks. Anyway very super disclaimer: This is for fun, don't trust it for serious business! also pretty insecure!
It's a lot of fun to try, tho.