[PYTHON] Le débutant de la CTF a tenté de créer un serveur problématique (Web) [Problème]

introduction

Connaissez-vous CTF (Capture The Flag)? Grâce à CTF, vous pouvez apprendre tout en rencontrant des problèmes de sécurité. J'ai pensé que j'essaierais d'expliquer le problème en créant moi-même un serveur vulnérable. J'ai fait un serveur pour le problème élémentaire de CTF.

point important

En raison de sa nature, le serveur est vulnérable. Veuillez ne pas implémenter le contenu de cet article car il se trouve dans un environnement de production.

supposition

Qu'est-ce que CTF (Capture The Flag)?

Un concours pour trouver des drapeaux cachés dans les problèmes et gagner des points. Des questions seront posées sur divers problèmes liés à la sécurité informatique. Cette fois, nous nous concentrerons sur le domaine du Web concernant les vulnérabilités des applications Web.

Sélection de technologie

Règles sur ce serveur de problèmes

En d'autres termes, il y a 3 données sous la forme de myctf {flag} sur ce système Web, alors veuillez les trouver.

Construire un serveur

Docker Network Créez un réseau entre les conteneurs avec le réseau docker.

$ docker network create ctf-network

Docker Compose

docker-compose.yml


version: '3.3'
services:
  app-python:
    container_name: app-python
    build:
      context: ./python
      dockerfile: Dockerfile
    tty: true
    volumes:
      - ${PWD}/python/src:/app
    ports:
      - "80:8000"
    networks:
      - ctf-network    
  db1:
    container_name: mysql
    build:
      context: ./mysql
      dockerfile: Dockerfile
    environment:
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - ./mysql/mysql_conf:/etc/mysql/conf.d
      - ./mysql/initdb.d:/docker-entrypoint-initdb.d      
    networks:
      - ctf-network
networks:
  ctf-network:

Veuillez modifier correctement l'utilisateur et le mot de passe.

MySQL Il semble que SQLite soit abordable et souvent utilisé dans CTF, mais comme il est construit avec Docker, j'ai choisi MySQL.

DockerFile

mysql/Dockerfile


FROM mysql:8.0
ADD ./ctf/flag.md /var/ctf/flag.md
RUN mkdir /var/log/mysql
RUN chown mysql:adm /var/log/mysql

Fichier où le drapeau est décrit

Incorporez le drapeau dans / var / ctf / flag.md. S'il est résolu dans l'ordre, ce sera le dernier drapeau.

mysql/ctf/flag.md


## flag.md
myctf{mission_complete}

fichier de configuration

Ajoutez un fichier de configuration MySQL.

mysql/mysql_conf/custom.cnf


[mysqld]
default_authentication_plugin=mysql_native_password
character-set-server=utf8
collation-server=utf8_general_ci
general_log=ON
general_log_file=/var/log/mysql/query.log
secure-file-priv = ""

[client]
default-character-set=utf8

Ajoutez le paramètre secure-file-priv pour accéder au fichier.

Fichier SQL pour l'initialisation de la base de données

sql:mysql/initdb.d/init.sql


SET CHARSET UTF8;

DROP DATABASE IF EXISTS ctf_db;
CREATE DATABASE ctf_db;
USE ctf_db;
DROP TABLE IF EXISTS users;
 
CREATE TABLE users (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(30) NOT NULL,
    last_name VARCHAR(30) NOT NULL,
    job VARCHAR(30) NOT NULL,
    delete_flag BOOLEAN NOT NULL DEFAULT FALSE
)DEFAULT CHARACTER SET=utf8;
 
INSERT INTO users (first_name, last_name, job) 
    VALUES 
    ("Taro", "Yamada", "Ingénieur côté serveur"),
    ("Jiro", "Suzuki", "Ingénieur front-end"),
    ("Saburo", "Tanaka", "Ingénieur infrastructure"),
    ("Hanako", "Sato", "designer");
INSERT INTO users (first_name, last_name, job, delete_flag)
    VALUES ("Ichiro", "Watanabe", "myctf{scf_sql_injection_flag}", TRUE); /*1er drapeau(Même tableau) */

DROP TABLE IF EXISTS flag;

CREATE TABLE flag (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    flag VARCHAR(60) NOT NULL,
    create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)DEFAULT CHARACTER SET=utf8;

INSERT INTO flag (flag)
    VALUES ("myctf{next_flag_[/var/ctf/flag.md]}"); /*Deuxième drapeau(Une autre table) */

Deux indicateurs sont intégrés dans la base de données. Le premier indicateur est que la table users est une table de suppression logique utilisant delete_flag, qui est incorporée dans les données censées être supprimées. Le deuxième indicateur est intégré dans la table des indicateurs, qui n'est pas référencée sur ce système.

Python

PHP est principalement utilisé pour les problèmes Web CTF, mais comme l'environnement back-end au travail est Python, je l'ai implémenté en Python. C'était sobre et difficile. (Je l'ai d'abord fait à partir du système PHP) Je pense que Python est souvent utilisé dans le CTF réel, comme les scripts automatisés pour l'acquisition de drapeaux.

Lors de la création d'une application web avec Python, ce sera difficile si vous n'utilisez pas de frameworks tels que Django et Flask, mais afin de créer des vulnérabilités, je vais créer autant que possible sans compter sur des frameworks.

DockerFile

python/Dockerfile


FROM python:3.8
WORKDIR /app
CMD bash -c "pip install -r ./requirements.txt && python app.py"
EXPOSE 8000

Requirements Files

Certains utilisent des bibliothèques externes. Décrivez le Lyle Rally à installer dans les fichiers d'exigences.

python/src/requirements.txt


Jinja2~=2.10
PyMySQL~=0.9

Il était difficile de coder en dur la syntaxe HTML avec python, je vais donc utiliser Jinja2 comme moteur de modèle.

Dossier d'exécution

python/src/app.py


import socketserver
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs

import pymysql.cursors
from jinja2 import Template, Environment, FileSystemLoader

PORT = 8000

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        conn = pymysql.connect(host='mysql',
                    user='root',
                    password='password',
                    db='ctf_db',
                    charset='utf8',
                    autocommit=True,
                    cursorclass=pymysql.cursors.DictCursor)
        try:
            url = urlparse(self.path)

            if url.path == '/':
                params = parse_qs(url.query)
                query = params.get('q', [''])[0]
                
                with conn.cursor() as cursor:
                    sql = f"SELECT * FROM users WHERE delete_flag=FALSE AND job LIKE '%{query}%';"
                    cursor.execute(sql)
                    users = cursor.fetchall()

                env = Environment(loader=FileSystemLoader('.'))
                template = env.get_template('index.html')
                
                data = {
                    'query': query,
                    'users': users
                }
                disp_text = template.render(data)

                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                
                self.wfile.write(disp_text.encode('utf-8'))
            else:
                self.send_response(404)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
        except Exception as e:
            print(e)

            self.send_response(500)
            self.send_header('Content-type', 'text/html')
            self.end_headers()

            self.wfile.write(str(e).encode('utf-8'))
        finally:
            conn.close()

with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

Veuillez corriger l'utilisateur et le mot de passe en fonction des valeurs modifiées par Docker Compose. Dans la génération de l'instruction SQL, le jugement de delete_flag = FALSE est inclus car il s'agit d'une suppression logique.

fichier de modèle jinja2

python/src/index.html


<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Expérience CTF</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
  <div class="container">
    <form class="form-inline my-3">
      <div class="form-group mb-2">
        <input type="text" name="q" class="form-control" placeholder="Recherche de type d'emploi" value="{{ query }}">
      </div>
      <button type="submit" class="btn btn-primary mb-2 mx-sm-4">Chercher</button>
    </form>
    {% if query != '' %}
      <p><span class="text-danger">{{ query }}</span>Résultats de recherche</p>
    {% endif %}

    <table class="table table-bordered">
      <thead>
        <tr>
          <th scope="col">ID</th>
          <th scope="col">Nom de famille</th>
          <th scope="col">Nom</th>
          <th scope="col">Occupation</th>
        </tr>
      </thead>
      <tbody>
        {% for user in users %}
          <tr>
            <td>{{ user.id }}</td>
            <td>{{ user.last_name }}</td>
            <td>{{ user.first_name }}</td>
            <td>{{ user.job }}</td>
          </tr>  
        {% endfor %}
      </tbody>
    </table>
  </div>
</body>
</html>

Commencer et vérifier

C'est la structure du répertoire.

├─ docker-compose.yml
├─ mysql
│   ├─ Dockerfile
│   ├─ ctf
│   │   └─ flag.md
│   ├─ initdb.d
│   │   └─ init.sql
│   └─ mysql_conf
│       └─ custom.cnf
└─ python
    ├─ Dockerfile
    └─ src
        ├─ app.py
        ├─ index.html
        └─ requirements.txt

Exécuter

$ docker-compose up -d

Une fois le conteneur démarré, accédez à http: // localhost à partir d'un navigateur Web.

2019-12-04 12.06.27 localhost e3de80904c2e.png

Vous devriez voir une page qui ressemble à l'image.

Entrez «ingénieur» dans la zone de texte de recherche d'emploi et cliquez sur le bouton «rechercher».

2019-12-04 12.06.52 localhost c4217ceed7b3.png

Il aurait dû être fouillé.

Autre

Cette fois, c’est juste un problème d’injection SQL, Il existe également des scripts intersites Web classiques et de nombreuses autres vulnérabilités. Au contraire, il est plein de vulnérabilités, et du côté de la résolution de problèmes, il peut ne pas être clair par quoi commencer. Si j'en ai envie, j'essaierai de créer un problème de script intersite.

finalement

La session d'étude de sécurité peut devenir un "crime lié aux enregistrements électromagnétiques de commande frauduleuse" Bien qu'il ait parfois été annulé (http://ozuma.sakura.ne.jp/sumida/2019/03/15/77/), Cet article lui-même, pour expliquer la vulnérabilité, Je prie pour que vous ne soyez pas une "infraction pénale concernant les enregistrements électromagnétiques de commande illégale".

Le référentiel complété est ici La version PHP du référentiel qui a été créé en parallèle est ici Cliquez ici pour le référentiel créé avec go language + PostgreSQL (https://github.com/fiotto/ctf-server-web-for-golang) Comme le langage go est un langage typé statiquement, il est difficile de deviner la définition de la table car une erreur se produira si vous UNION avec le mauvais type.

Pour la méthode de réponse de cette question, voir Les débutants de la CTF ont essayé de créer un serveur de questions (Web) [Réponse].

Recommended Posts

Le débutant de la CTF a tenté de créer un serveur problématique (Web) [Problème]
Configurons un serveur WEB avec Chromebook
J'ai créé une API Web
J'ai essayé de créer une méthode de super résolution / ESPCN
J'ai essayé de créer une méthode de super résolution / SRCNN ①
J'ai essayé de créer une méthode de super résolution / SRCNN ③
J'ai essayé de créer une méthode de super résolution / SRCNN ②
Les débutants ont essayé de créer une application Web native pour le cloud à l'aide de Datastore / GAE
[Débutant] [Python / Django] Un ingénieur Web débutant a essayé un didacticiel Django - Partie 1-
[Débutant] [Python / Django] Un ingénieur Web débutant a essayé un didacticiel Django - Partie 2
[Débutant] [Python / Django] Un ingénieur web débutant a essayé un didacticiel Django - Partie 0-
[Débutant] [Python / Django] Un ingénieur Web débutant a essayé un tutoriel Django - Partie 5
[Partie 2] Construisons un serveur Web avec EC2 Linux
[Go + Gin] J'ai essayé de créer un environnement Docker
[Débutant] [Python / Django] Un ingénieur Web débutant a essayé un didacticiel Django - Partie 4
[Débutant] [Python / Django] Un ingénieur Web débutant a essayé un didacticiel Django - Partie 3
Source compile Apache2.4 (httpd 2.4.43) + PHP7.4 sous Linux pour construire un serveur Web --3 MySQL 8.0 introduction
Mémo Un débutant a essayé de créer un environnement Java et de le traduire en japonais sur Ubuntu 18.04.2 LTS.
Créez un serveur Web API à une vitesse explosive en utilisant HUG
J'ai essayé de résoudre le problème d'optimisation des combinaisons avec Qiskit
Créez un serveur API Web ultra-rapide avec Falcon
[Introduction à AWS] Mémorandum de création d'un serveur Web sur AWS
Un débutant en python a essayé de faire un stage dans une entreprise informatique
J'ai essayé de créer un environnement serveur qui fonctionne sous Windows 10
Comment créer un nœud NEM (version actuelle) (NIS1: NEM Infrastructure Server)
J'ai créé un serveur Web avec Razpai pour regarder des anime
Créer une application Web avec Django
J'ai essayé de créer une configuration RAID logicielle SATA qui démarre le système d'exploitation sur Ubuntu Server
J'ai essayé de communiquer avec un serveur distant par communication Socket avec Python.
J'ai essayé de créer un environnement de développement Mac Python avec pythonz + direnv
Démarrez un serveur Web en utilisant Bottle et Flask (j'ai également essayé d'utiliser Apache)
J'ai essayé de créer un linebot (implémentation)
Construire un serveur de cache Pypi sur QNAP
Vous voulez résoudre un problème de classification simple?
Comment créer mon propre serveur Linux
Créez facilement un serveur DNS en utilisant Twisted
Comment créer un environnement de traduction sphinx
J'ai essayé de créer un linebot (préparation)
Construisez un serveur WebDAV simple sur Linux
Je veux créer un environnement Python
Construire un serveur Samba sur Arch Linux
[Django-Extensions] Les débutants en développement Web ont essayé de résumer Django-Extensions
J'ai essayé de comparer le cadre d'application Web
Le programmeur s'est efforcé de construire un serveur pour le surmonter, disant que l'infrastructure semble être difficile. Édition du serveur WebAP
Un débutant en python a tenté de faire un stage dans une entreprise informatique [Enquête sur le chatbot jour 2]
Atcoder Beginner Contest A, B Résumé d'entrée qui a tendance à être un problème Python
Un débutant en python a tenté de faire un stage dans une entreprise informatique [Processus de développement du jour 1]
Un débutant en programmation a essayé de vérifier le temps d'exécution du tri, etc.
Source compilez Apache2.4 + PHP7.4 avec Raspberry Pi et construisez un serveur Web --2 introduction PHP
Source compilez Apache2.4 + PHP7.4 avec Raspberry Pi et créez un serveur Web ―― 1. Introduction à Apache
Source compilez Apache2.4 (httpd 2.4.43) + PHP7.4 sous Linux pour construire un serveur Web ―― 1. Introduction à Apache
Un débutant en apprentissage automatique a tenté de créer une IA de jugement Sheltie en un jour
[Python] Comment créer un environnement de serveur Web local avec SimpleHTTPServer et CGIHTTPServer
Source compile Apache2.4 (httpd 2.4.43) + PHP7.4 sous Linux pour construire un serveur Web --2 introduction PHP
Envoyer un message de Slack à un serveur Python
Créer un serveur local avec une commande sur une seule ligne [Mac]
J'ai essayé Web Scraping pour analyser les paroles.
Calculons en fait le problème statistique avec Python
Comment ouvrir un navigateur Web à partir de python
Livre mis à jour: Évolution vers un "serveur Web décent"