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()
In 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)[0]
# 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.