
Практическая часть
Задание 1.
Защита от SQL инъекций
Используя функции для защиты от SQL инъекций, повторите пример из теоретической части и убедитесь в том, что она работает.
CREATE ROLE "SAB" WITH
LOGIN
SUPERUSER
CREATEDB
CONNECTION LIMIT -1
PASSWORD '123456';
Sudo apt install plocate
gcc main.c -o main -I<путь_к_libpq-fe.h> -lpq
gcc main.c -o main -I/usr/include/postgresql -lpq
надо изменить файл tasks.json
ошибка
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc сборка активного файла",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"-I/usr/include/postgresql", // добавлен путь к заголовочным файлам
"-lpq" // добавлена PostgreSQL библиотека
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "компилятор: /usr/bin/gcc"
}
]
}
+ исправление этой ошибки
сonnection to database failed: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "SAB"
[1] + Done "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-ebzwb0pp.m0g" 1>"/tmp/Microsoft-MIEngine-Out-rqu55n31.pal"
student@ru01wks00u20:~/Desktop/qwert$
sudo nano /etc/postgresql/<version>/main/pg_hba.conf
local all all md5
(Замените peer на md5, чтобы получить😊)
sudo systemctl restart postgresql
(исправил код из методички)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libpq-fe.h>
/* Функция выхода из программы с сообщением об ошибке. */
void err_exit(PGconn *conn) {
PQfinish(conn);
exit(1);
}
/* Функция печати результата запроса на экран */
void print_query(PGconn *conn, char* query){
PGresult *res = PQexec(conn, query);
int rows = PQntuples(res);
int cols = PQnfields(res);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
printf("No data retrieved\n");
PQclear(res);
err_exit(conn);
}
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
printf("%s ", PQgetvalue(res, i, j));
}
printf("\n");
}
PQclear(res);
}
/*
* Функция поиска и вывода на экран информации о студенте по номеру его студенческого билета и названию дисциплины.
*/
void find_students_by_ID(PGconn *conn, int st_id, char* f_name) {
// Создание динамического массива для помещения в него запроса
char* query = (char*)malloc(512 * sizeof(char));
int pos = strlen(f_name) - 1;
if (f_name[pos] == '\n') {
f_name[pos] = '\0'; // Удаление символа окончания строки
}
// Запрос, возвращающий ФИО, название дисциплины и оценку студента
sprintf(query,
"SELECT last_name, first_name, field_name, mark "
"FROM students S "
"JOIN PUBLIC.field_comprehensions F_C ON S.student_id = F_C.student_id "
"JOIN PUBLIC.fields F ON F.field_ID = F_C.field "
"WHERE S.student_id = %d AND F.field_name = '%s'", st_id, f_name);
PGresult *res = PQexec(conn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
printf("No data retrieved\n");
PQclear(res);
err_exit(conn);
}
int rows = PQntuples(res);
int cols = PQnfields(res);
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
printf("%s ", PQgetvalue(res, i, j));
}
printf("\n");
}
PQclear(res);
free(query);
}
int main() {
// Подключение к серверу базы данных
PGconn *conn = PQconnectdb("user=SAB password=123456 dbname=postgres");
// Проверка статуса подключения
if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
err_exit(conn);
}
int st_id;
printf("Enter student ID number: \n");
scanf("%d", &st_id);
getchar();
char f_name[256];
printf("Enter field name: \n");
fgets(f_name, 256, stdin);
// Вызов функции поиска студента по ID и дисциплине
find_students_by_ID(conn, st_id, f_name);
PQfinish(conn);
return 0;
}
Теперь добавляю защиту SQL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libpq-fe.h>
/* Функция выхода из программы с сообщением об ошибке. */
void err_exit(PGconn *conn) {
PQfinish(conn);
exit(1);
}
/* Функция печати результата запроса на экран */
void print_query(PGconn *conn, char* query){
PGresult *res = PQexec(conn, query);
int rows = PQntuples(res);
int cols = PQnfields(res);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
printf("No data retrieved\n");
PQclear(res);
err_exit(conn);
}
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
printf("%s ", PQgetvalue(res, i, j));
}
printf("\n");
}
PQclear(res);
}
/*
* Функция поиска и вывода на экран информации о студенте по номеру его студенческого билета и названию дисциплины.
*/
void find_students_by_ID(PGconn *conn, int st_id, char* f_name) {
// Создание динамического массива для помещения в него запроса
char* query = (char*)malloc(512 * sizeof(char));
int pos = strlen(f_name) - 1;
if (f_name[pos] == '\n') {
f_name[pos] = '\0'; // Удаление символа окончания строки
}
// Запрос, возвращающий ФИО, название дисциплины и оценку студента
sprintf(query,
"SELECT last_name, first_name, field_name, mark "
"FROM students S "
"JOIN PUBLIC.field_comprehensions F_C ON S.student_id = F_C.student_id "
"JOIN PUBLIC.fields F ON F.field_ID = F_C.field "
"WHERE S.student_id = %d AND F.field_name = '%s'", st_id, f_name);
PGresult *res = PQexec(conn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
printf("No data retrieved\n");
PQclear(res);
err_exit(conn);
}
int rows = PQntuples(res);
int cols = PQnfields(res);
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
printf("%s ", PQgetvalue(res, i, j));
}
printf("\n");
}
PQclear(res);
free(query);
}
int main() {
// Подключение к серверу базы данных
PGconn *conn = PQconnectdb("user=SAB password=123456 dbname=postgres");
// Проверка статуса подключения
if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
err_exit(conn);
}
int st_id;
printf("Enter student ID number: \n");
scanf("%d", &st_id);
getchar();
char f_name[256];
printf("Enter field name: \n");
fgets(f_name, 256, stdin);
// Вызов функции поиска студента по ID и дисциплине
find_students_by_ID(conn, st_id, f_name);
PQfinish(conn);
return 0;
}
/*
Функция изменения символа апострофа
*query -> текст запроса
*/
void correct_apostrof(char* query){
for(int i = 0; i < strlen(query); ++i)
if(query[i] == '\'')
query[i] = '`';
}
Все работает и данные не меняются