hroman9 8 gadus atpakaļ
revīzija
8976063317
6 mainītis faili ar 456 papildinājumiem un 0 dzēšanām
  1. 170
    0
      README.md
  2. 126
    0
      sql.py
  3. 36
    0
      sqlgen1.py
  4. 64
    0
      sqlgen2.py
  5. 33
    0
      templates/index.html
  6. 27
    0
      templates/phone.html

+ 170
- 0
README.md Parādīt failu

@@ -0,0 +1,170 @@
1
+# SQL Injection: Rompiendo Autenticación
2
+### Introducción
3
+En esta experiencia de laboratorio estaremos estudiando la inyección de SQL. La inyección de SQL es un método por el cual la data de una base de datos es alterada, borrada o robada con intenciones maliciosas por medio de la inserción de código SQL en una aplicación insegura. Cuando escucha en las noticias que la data de alguna compañía fue comprometida por un ataque cibernético, lo más probable significa que una o más de sus bases de datos fueron comprometidas por medio de una inyección de SQL. Cada vez se hace más difícil llevar a cabo este tipo de ataque dado que las librerías de programación que se usan para conectar con las bases de datos, cada vez implementan mejores métodos de seguridad para llevar a cabo transacciones con bases de datos. De todas maneras cuando se diseña una aplicación que hace uso de una base de datos, es necesario hacer validación de la entrada, como también asegurarse que se hace uso de la librería de conneción a la base de datos de la manera más segura posible, lo que significa desabilitar el uso de múltiples queries y usar queries parametrizados (queries preparados). En esta experiencia de laboratorio se va a demostrar como una aplicación de web insegura puede ser explotada usando inyección de SQL.  Se utiliza Flask para servir las páginas web en este laboratorio . La base de datos que se utiliza es MySQL server.
4
+### Setup Pre Laboratorio
5
+
6
+1. Necesita tener el interpretador de Python instalado en su computadora.  
7
+
8
+2. Flask necesita ser instalado. Refiérase a estas [instrucciones](http://flask.pocoo.org/docs/0.11/installation/).  
9
+
10
+3. Un servidor de MySQL necesita estar corriendo en su computadora. Necesita correr el servidor como el usuario **root**, la contraseña para el usuario root debe ser **python1234**, también necesita crear una base de datos llamada **sqlinjection** . Refiérase a estas [instrucciones](http://dev.mysql.com/doc/mysql-getting-started/en/#mysql-getting-started-installing) para la instalación.  
11
+
12
+4. Descarge el código fuente de este laboratorio.  
13
+
14
+
15
+### Parte I
16
+
17
+En esta parte estaremos demostrando algunas inyecciones utilizando una simple aplicación web que sirve para hacer búsqueda en una guía de teléfono.(con los nombre de algunos científicos de cómputos famosos)
18
+
19
+###### Instrucciones
20
+
21
+1. Localice el lugar donde almaceno el código fuente. Luego de asegurarse de tener Flask instalado al igual que el servidor de MySL con los parámetros requeridos, localice archivo de python **sqlgen1.py** y ejecute este script. El script preparará la base de datos para la primera parte de este laboratorio.  
22
+
23
+2. Ahora localice el archivo de python **sql.py** y ejecute este script. Este es el script que ejecuta la aplicación web para este laboratorio. Este script debe mantenerse corriendo por el resto de este laboratorio.  
24
+
25
+3. Vaya a su browser e ingrese **localhost:5000/phone** en la barra de URL. Esta es la aplicación de la guía de teléfono. Localhost significa que este pidiendo un documento que esta siendo servido en la misma computadora donde corre el browser y 5000 es el puerto default donde Flask sirve los documentos html.  
26
+
27
+4. Ingrese **Ada** en la caja de texto y presione **Search** para verificar como funciona la búsqueda.  
28
+
29
+5. En el paso anterior vio como pudo encontrar entradas que fueran igual al string ingresado en la caja de texto. En este paso utilizará una inyección de SQL para poder desplegar todas las entradas en la guía a la vez. El query que utiliza la aplicación web para buscar en la base de datos se contruye de la siguiente forma:  
30
+
31
+    
32
+        query = "select * from phonebook where name = '"  
33
+        query += name  
34
+        query += "';"
35
+
36
+    La variable **name** que la aplicación añade al string del query, corresponde a la entrada del usuario de la caja de texto. Como esta es una aplicación insegura donde no se hace validación de la entrada del usuario, el string del query se enviaba con cualquier inyección para interpretación en la base de datos. Ahora usara una inyección para mostrar todas las entradas de la base de datos a la a vez. Ingrese el string que sigue y pulse **Search**:  
37
+
38
+
39
+        randomText' or 1=1; --
40
+
41
+    **IMPORTANTE: Debe incluir un espacio después del doble guión.**  
42
+
43
+    Note que el string que se construye es **select * from phonebook where name = 'randomText' or 1=1;  --**
44
+    Note que esta añadiendo la condición 1=1 que hará que el query sea válido para cualquier fila en la tabla, por lo tanto todas las entradas se desplegarán en la página. **Tome un screenshot con todas las entradas.**  
45
+
46
+6. En este paso utilizará una inyección para borrar una entrada de la guía.(la entrada que usted quiera). Luego de borrar la entrada, muestre la guía completa de nuevo como hizo en el paso anterior y **tome un screenshot**. El string para la inyección debe lucir así:  
47
+
48
+    ```
49
+    randomText'; DELETE FROM phonebook where name = "chosenName"; --
50
+    ```  
51
+
52
+7. En este paso usted hará una inyección para borrar el contenido completo de la guía. Luego de borrar la guía usará una inyección para insertar dos estradas de su preferencia a la guía. Luego de hacer las inserciones **tome un screenshot**. Aquí están los strings de inyección que debe usar:  
53
+
54
+    
55
+        randomText'; DELETE FROM phonebook; --
56
+        randomText'; INSERT INTO phonebook (name, phone) VALUES ("someName", "123-456-7890"); --
57
+    
58
+    
59
+### Parte 2
60
+##### Instrucciones
61
+En esta parte romperá la autenticación de una muy simple e insegura aplicación web. El simple método de autenticación consiste en verificar si la combinación de nombre de usuario y contraseña está en la tabla de autenticación de la base de datos.
62
+
63
+1. En al código fuente, ejecute el script de python **sqlgen2.py** para preparar la base de datos para este ejercicio.  
64
+
65
+2. Navegue en su browser a **localhost:5000/auth**  
66
+
67
+3. En la primera parte del laboratorio se le proveyó el nombre de las tablas y las columnas que iba a alterar. En la vida real esta información es desconocida para un potencial atacante. Su tarea es determianr el nombre de la tabla de autenticacion en la base de datos por medio de verificar los mensajes de error en la aplicación al tratar de hacer una inyección con un nombre potencial para la tabla. Utilize la siguiente inyección, cambiando la palabra **tableName** por una de las siguientes: (authtentication , login) **tome screenshot** de ambos intentos y determine el nombre de la tabla.  
68
+
69
+    ```
70
+    randomText' select * from tableName; --
71
+    ```  
72
+
73
+4. En el siguiente paso su tarea es determinar los nombres de las columnas en la tabla de autenticación de la cual usted determinó el nombre en el paso anterior. Utilizará las siguientes 4 palabras (userid , password, username, passphrase) con la siguiente inyección para determinar los nombres correctos de las columnas. Permita que los errores le dejen saber los nombres correctos de las columnas y **tome a screenshot** de sus intentos.  
74
+
75
+    ```
76
+    randomText'; INSERT INTO tableNameStep2 (guessColumnName, guessColumnName) VALUES ("someValue", "someValue"); --
77
+    ```  
78
+
79
+5. Los aplicaciones web almacenan las contraseñas como hashes en las bases de datos. En el caso de este laboratorio, la contraseña se almacena como un hash de md5. Esta será su tarea final. Su meta debe ser poder autenticarse como el usuario **dbadmin** de la base de datos. Para lograr esto necesita hacer lo siguiente:
80
+    * Computar el md5 hash de algun string.
81
+    * Usar una inyección para modificar el hash en la base de datos de este usuario por el que usted computó.
82
+    * Autentíquese usando como username **dbadmin** y como contraseña el string al que le computó el hash usted. (La aplicación web hace hash al string que se ingrese en el campo de la contraseña)
83
+    * Luego de autenticar como **dbadmin** tome un screenshot de la página web y anote la inyección que utilizó.
84
+
85
+### Entregables
86
+> Entregue un documento PDF que inluya los screenshots que tomó y todas las inyecciones de codigo que utilizó.  
87
+
88
+
89
+
90
+# SQL Injection: Breaking Authentication
91
+
92
+### Introduction
93
+In this lab experience we will be studying SQL injection. SQL injection is a method by which data from a database is deleted, stolen, or altered with malicious intentions by inserting SQL code in an unsececure application. Whenever you hear that data from some company was compromised in the news, it most probably means that one or more of their databases were breached by some type of SQL injection. It is getting more difficult everytime to make these attacks since the programming languages libraries used to connect to databases implement methods to secure database transactions. Nevertheless when an application is designed that makes use of a database, input validation is very important, as well as making sure of using the database connection libraries in the most secure manner, which means disabling multiple queries and using parameterized statements(prepared statements). In this lab experience it will be shown how an unsecured web application can be exploited using SQL injection. Flask is used to serve the web pages for the lab. Also, MySQL is the database that is used.
94
+### Pre Lab Setup  
95
+
96
+1. You should have the Python interpreter installed in your computer.  
97
+
98
+2. Flask needs to be installed. Refer to these [instructions](http://flask.pocoo.org/docs/0.11/installation/).  
99
+
100
+3. A MySQL server needs to be running in your computer. You need to be running the server as the user **root**, the password for the root user should be **python1234**, you also need to create a database called **sqlinjection** . Refer to these [instructions](http://dev.mysql.com/doc/mysql-getting-started/en/#mysql-getting-started-installing) for installation.  
101
+
102
+4. Download the source code for the lab.  
103
+
104
+### Part I  
105
+
106
+In this part we will be demonstrating some injections using a simple phone book search web application. (with the first names of some famous computer scientists)  
107
+
108
+1. Navigate to the location where you stored the source code. After making sure that you have Flask installed as well as the MySQL server running with the required parameters locate the python file sqlgen1.py and execute the script. This script will set up the database for Part 1 of the lab.  
109
+
110
+2. Now locate the python file sql.py and execute the script. This will be the script that will run the web application for the lab. This script should be running for the remainder of the lab experience.  
111
+
112
+3. Go to your browser and enter **localhost:5000/phone** in the address bar. This is the phonebook app. Localhost means we are retrieving a web document in our same computer and 5000 is the default port on which Flask serves html documents.  
113
+
114
+4. Type **Ada** in the textbox and click **Search** to check how the phonebook works.  
115
+
116
+5. In the previous step you saw that you were able to find entries that matched the string you typed in the text box. In this step you will use an injection to show all entries in the phonebook. The query the web app is using to search the database is constructed like this:  
117
+
118
+        query = "select * from phonebook where name = '"
119
+        query += name
120
+        query += "';"  
121
+
122
+    The variable **name** that the app is appending to the query string, corresponds to the user input from the textbox. Since this is an unsecure application no input validation is done and the query string is sent directly to the database for interpretation. You will now use an injection to show all entries from the phonebook at once. Enter the following string in the textbox  and click **Search**  
123
+
124
+    ```
125
+    randomText' or 1=1; --
126
+    ```  
127
+
128
+    **IMPORTANT: You need to include a space after the double hyphens.**  
129
+
130
+    Notice that the string that is created is **select * from phonebook where name = 'randomText' or 1=1;  --** You are adding the condition 1=1 that will make the query valid for any row in the table and all entries will be shown in the webapage. **Take a screenshot with all the entries.**  
131
+
132
+6. For the next step you will use an injection to delete an entry from the phonebook (any name you like or don't like). After you delete an entry show the complete phonebook with the same injection used in the previous step and **take a screenshot**. The string for the injection should be like this:  
133
+
134
+    ```
135
+    randomText'; DELETE FROM phonebook where name = "chosenName"; --
136
+    ```  
137
+
138
+7. In this step you will make an injection to delete the whole contents of the phonebook. After you delete the phonebook you will use another injection to insert two entries of your choice into the phonebook. After you make the insertions **take a screenshot**. Here are the injection strings you should use:  
139
+
140
+        randomText'; DELETE FROM phonebook; --
141
+        randomText'; INSERT INTO phonebook (name, phone) VALUES ("someName", "123-456-7890"); --  
142
+
143
+    
144
+### Part 2
145
+In this part you will break the authentication of a very simple and unsecure web application. The simple method of authentication consists of checking if the username and the password combination is in the database authentication table.
146
+
147
+1. In the source folder, execute the python script sqlgen2.py to set up the database for this exercise.  
148
+
149
+2. Go to the address **localhost:5000/auth** in your browser.  
150
+
151
+3. In the first part of the lab you were given the name of the table and columns you wanted to alter. In real life this information is unknown to a potential attacker. Your job is to determine the name of the authentication table in the database by checking the error messages in the web page after doing an injection with a potential table name. Use the following code injection, exchanging the word **tableName** for each of the following: (authtentication , login) **take a screenshot** of both tries and determine the name of the table.  
152
+
153
+    ```
154
+    randomText' select * from tableName; --
155
+    ```  
156
+
157
+4. For the next step your job is determine what are the names of the columns in the table whose name you determined in the previous step. You will use the following 4 words (userid , password, username, passphrase) with the following injection to determine the correct column names. Let the errors help you determine the column names and **take a screenshot** of all your tries.  
158
+
159
+    ```
160
+    randomText'; INSERT INTO tableNameStep2 (guessColumnName, guessColumnName) VALUES ("someValue", "someValue"); --
161
+    ```  
162
+
163
+5. Web applications store user passwords as hashes in a database. In the case of the lab, the password is stored as an md5 hash. This will be your final task. Your goal is to be able to authenticate as the user in the database whose id is **dbadmin**. To accomplish this task you will need to do the following:
164
+    * Compute the md5 hash of some string.
165
+    * Use an injection to modify the stored hash for the user dbadmin with the hash you computed.
166
+    * Authenticate in the web app using as id **dbadmin** and as password the string whose hash you just computed. (The web app hashes all the input in the password field.)
167
+    * After you authenticate as **dbadmin** take a screenshot of the web page and write down the injection that you used to modify the hash in the db.
168
+
169
+### Deliverables
170
+> Hand in a PDF document with the screenshots you took and with all the injections you used.

+ 126
- 0
sql.py Parādīt failu

@@ -0,0 +1,126 @@
1
+from flask import Flask, render_template, request
2
+import mysql.connector
3
+import hashlib
4
+
5
+app = Flask(__name__)
6
+
7
+@app.route('/phone', methods=['GET' , 'POST'])
8
+def pbook():
9
+    if request.method == "POST":
10
+        name = request.form['name']
11
+
12
+        try:
13
+            db = mysql.connector.connect(host="localhost",
14
+                                         user="root",
15
+                                         passwd="python1234",
16
+                                         db="sqlinjection")
17
+
18
+            cursor = db.cursor()
19
+
20
+            query = "select * from phonebook where name = '"
21
+            query += name
22
+            query += "';"
23
+            print query
24
+
25
+            count = 0
26
+            login = False
27
+            for result in cursor.execute(query, multi=True):
28
+                if result.with_rows:
29
+                    print("Rows produced by statement '{}':".format(
30
+                        result.statement))
31
+                    ls = result.fetchall()
32
+                    print ls
33
+                    if len(ls) > 0 and count == 0:
34
+                        login = True
35
+                else:
36
+                    print("Number of rows affected by statement '{}': {}".format(
37
+                        result.statement, result.rowcount))
38
+
39
+                count += 1
40
+
41
+            db.commit()
42
+            cursor.close()
43
+            db.close()
44
+
45
+            if login:
46
+
47
+                returnString = "<h1>Results:</h1>"
48
+
49
+                for item in ls:
50
+                    returnString += '<h3>' + item[0] + " " + item[1] + '</h3>'
51
+
52
+                returnString += "<a href='http://localhost:5000/phone'>Back to Phone Book</a>"
53
+
54
+                return returnString
55
+            else:
56
+                return "<h1>Person Not Found</h1><a href='http://localhost:5000/phone'>Back to Phone Book</a>"
57
+        except Exception as e:
58
+            strval = str(e)
59
+            msg = "<h1>"
60
+            msg += strval
61
+            msg += "</h1><a href='http://localhost:5000/phone'>Back to Phone Book</a>"
62
+            return msg
63
+
64
+    else:
65
+        return render_template('phone.html')
66
+
67
+
68
+@app.route('/auth', methods=['GET' , 'POST'])
69
+def send():
70
+    if request.method == "POST":
71
+        user = request.form['user']
72
+        pwd = request.form['pwd']
73
+        pwd = hashlib.md5(pwd).hexdigest()
74
+
75
+
76
+        try:
77
+            db = mysql.connector.connect(host="localhost",
78
+                                         user="root",
79
+                                         passwd="python1234",
80
+                                         db="sqlinjection")
81
+
82
+            cursor = db.cursor()
83
+
84
+            query = "select * from login where password = '"
85
+            query += pwd
86
+            query += "' and username = '"
87
+            query += user
88
+            query += "';"
89
+            print query
90
+
91
+            count = 0
92
+            login = False
93
+            for result in cursor.execute(query, multi=True):
94
+                if result.with_rows:
95
+                    print("Rows produced by statement '{}':".format(
96
+                        result.statement))
97
+                    ls = result.fetchall()
98
+                    print ls
99
+                    if len(ls) > 0 and count == 0:
100
+                        login = True
101
+                else:
102
+                    print("Number of rows affected by statement '{}': {}".format(
103
+                        result.statement, result.rowcount))
104
+
105
+                count += 1
106
+
107
+            db.commit()
108
+            cursor.close()
109
+            db.close()
110
+
111
+            if login:
112
+                return '<h1>Authentication Succesful</h1><h1>Welcome Back, ' + user + "</h1><a href='http://localhost:5000/auth'>Back to Login</a>"
113
+            else:
114
+                return "<h1>Authentication Failed</h1><a href='http://localhost:5000/auth'>Back to Login</a>"
115
+        except Exception as e:
116
+            strval = str(e)
117
+            msg = "<h1>"
118
+            msg += strval
119
+            msg += "</h1><a href='http://localhost:5000/auth'>Back to Login</a>"
120
+            return msg
121
+
122
+    else:
123
+        return render_template('index.html')
124
+
125
+if __name__ == "__main__":
126
+    app.run(debug=True)

+ 36
- 0
sqlgen1.py Parādīt failu

@@ -0,0 +1,36 @@
1
+import mysql.connector
2
+from random import randint
3
+
4
+try:
5
+    db = mysql.connector.connect(host="localhost", user="root", passwd="python1234", db="sqlinjection")
6
+    cursor = db.cursor()
7
+
8
+    delTable = "DROP TABLE IF EXISTS phonebook;"
9
+
10
+    cursor.execute(delTable)
11
+
12
+    creTable = "CREATE TABLE phonebook (name VARCHAR(20) NOT NULL, phone VARCHAR(12) NOT NULL);"
13
+
14
+    cursor.execute(creTable)
15
+
16
+    entries = ["Alan", "Ada", "Donald", "Grace", "Claude", "Ken", "Dennis", "Tim", "Tony", "Vint"]
17
+
18
+    for i in range(len(entries)):
19
+        randphone = str(randint(100, 999)) + "-" + str(randint(100, 999)) + "-" + str(randint(1000, 9999))
20
+        insDB = "insert into phonebook (name, phone) VALUES ('"
21
+
22
+        insDB += entries[i]
23
+
24
+        insDB += "' , '"
25
+
26
+        insDB += randphone
27
+
28
+        insDB += "');"
29
+
30
+        cursor.execute(insDB)
31
+
32
+    db.commit()
33
+    cursor.close()
34
+    db.close()
35
+except Exception as e:
36
+    print e

+ 64
- 0
sqlgen2.py Parādīt failu

@@ -0,0 +1,64 @@
1
+import mysql.connector
2
+from random import randint
3
+import hashlib
4
+
5
+try:
6
+    db = mysql.connector.connect(host="localhost",
7
+                                 user="root",
8
+                                 passwd="python1234",
9
+                                 db="sqlinjection")
10
+
11
+    cursor = db.cursor()
12
+
13
+    delTable = "DROP TABLE IF EXISTS login;"
14
+
15
+    cursor.execute(delTable)
16
+
17
+    creTable = "CREATE TABLE login (username VARCHAR(20) NOT NULL, password VARCHAR(32) NOT NULL);"
18
+
19
+    cursor.execute(creTable)
20
+
21
+    # Crear una tabla de cuentas de usuarios con sus hashes de manera aleatoria con 50 usuarios
22
+    for t in range(50):
23
+
24
+        largoUser = randint(8, 16)
25
+        username = ""
26
+        for i in range(largoUser):
27
+            randChar = randint(48, 126)
28
+            if randChar == 92:
29
+                randChar += 1
30
+            username += str(unichr(randChar))
31
+
32
+        largoPass = randint(8, 20)
33
+        password = ""
34
+        for j in range(largoUser):
35
+            randChar = randint(48, 126)
36
+            if randChar == 92:
37
+                randChar += 1
38
+            password += str(unichr(randChar))
39
+
40
+        password = hashlib.md5(password).hexdigest()
41
+
42
+        insDB = "insert into login (username, password) VALUES ('"
43
+
44
+        insDB += username
45
+
46
+        insDB += "' , '"
47
+
48
+        insDB += password
49
+
50
+        insDB += "');"
51
+
52
+
53
+        cursor.execute(insDB)
54
+
55
+    insUser = "insert into login (username, password) VALUES ('dbadmin','64387b4b69baef645c388a6c3b812c52');"
56
+
57
+    cursor.execute(insUser)
58
+
59
+    db.commit()
60
+
61
+    cursor.close()
62
+    db.close()
63
+except Exception as e:
64
+    print e

+ 33
- 0
templates/index.html Parādīt failu

@@ -0,0 +1,33 @@
1
+<!DOCTYPE html>
2
+<html>
3
+    <head>
4
+        <meta name="viewport" content="width=device-width, initial-scale=1">
5
+        <meta charset="utf-8">
6
+        <!-- Latest compiled and minified CSS -->
7
+        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
8
+
9
+        <!-- jQuery library -->
10
+        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
11
+
12
+        <!-- Latest compiled JavaScript -->
13
+        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
14
+    </head>
15
+
16
+
17
+    <body>
18
+        <div class="container">
19
+            <h1>Login:</h1>
20
+            <form method="post">
21
+                <div class="form-group">
22
+                    <label for="user">Username:</label>
23
+                    <input type="text" class="form-control" id="user" name="user">
24
+                </div>
25
+                <div class="form-group">
26
+                    <label for="pwd">Password:</label>
27
+                    <input type="password" class="form-control" id="pwd" name="pwd">
28
+                </div>
29
+                <button type="submit" class="btn btn-default">Login:</button>
30
+            </form>
31
+        </div>
32
+    </body>
33
+</html>

+ 27
- 0
templates/phone.html Parādīt failu

@@ -0,0 +1,27 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+    <meta name="viewport" content="width=device-width, initial-scale=1">
5
+        <meta charset="utf-8">
6
+        <!-- Latest compiled and minified CSS -->
7
+        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
8
+
9
+        <!-- jQuery library -->
10
+        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
11
+
12
+        <!-- Latest compiled JavaScript -->
13
+        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
14
+</head>
15
+<body>
16
+    <div class="container">
17
+            <h1>Computer Scientists Phonebook</h1>
18
+            <form method="post">
19
+                <div class="form-group">
20
+                    <label for="name">Username:</label>
21
+                    <input type="text" class="form-control" id="name" name="name">
22
+                </div>
23
+                <button type="submit" class="btn btn-default">Search</button>
24
+            </form>
25
+        </div>
26
+</body>
27
+</html>