Search
๐Ÿ›ก๏ธ

SQL Injection Hardening - Prepared Statements

Prepared Statements

Prepared Statements ์ง์—ญํ•˜๋ฉด โ€˜์‚ฌ์ „ ์„ ์–ธโ€™์œผ๋กœ ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ, SQL Injection์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
๊ธฐ๋ณธ์ ์œผ๋กœ ์ธ์ž ํ˜•์‹๊ณผ ๊ธธ์ด์— ๋Œ€ํ•ด ๊ฒ€์ฆ์„ ํ•˜๊ณ , ์•„๋ž˜ ๋งํฌ์™€ ๊ฐ™์ด SQL Escape ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ์‹์œผ๋กœ ๋ง‰์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ SQL Injection์„ ๊ณต๊ฒฉํ•˜๋Š” ๋ฐฉ์‹์€ ๋ฌด์ฒ™์ด๋‚˜ ๋‹ค์–‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— SQL ๊ตฌ์กฐ์ ์œผ๋กœ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹๋‹ค.

Statements vs Prepared Statements

๊ธฐ์กด ๋ฐฉ์‹ (Dynamic SQL Statements):

โ€ข
ํด๋ผ์ด์–ธํŠธ๋Š” SQL ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์„ ๋งŒ๋“ ๋‹ค. ์ด๋•Œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ์ง์ ‘ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์— ํฌํ•จ๋œ๋‹ค.
โ€ข
์™„์„ฑ๋œ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋กœ ์ „์†ก๋œ๋‹ค.
โ€ข
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์—์„œ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์„ ํŒŒ์‹ฑ, ์ตœ์ ํ™”, ์ปดํŒŒ์ผํ•œ ํ›„ ์‹คํ–‰ํ•œ๋‹ค.
์ด ๊ณผ์ •์—์„œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์— ์ง์ ‘ ํฌํ•จ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ณต๊ฒฉ์ž๊ฐ€ SQL ๊ตฌ๋ฌธ์„ ์กฐ์ž‘ํ•ด SQL Injection์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค.

Prepared Statements ๋ฐฉ์‹:

โ€ข
ํด๋ผ์ด์–ธํŠธ๋Š” ๋‘ ๋ถ€๋ถ„(์ฟผ๋ฆฌ ํ…œํ”Œ๋ฆฟ๊ณผ ๋ณ€์ˆ˜ ๊ฐ’)์œผ๋กœ ๋‚˜๋ˆ„์–ด์ง„ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
โ€ข
์ฟผ๋ฆฌ ํ…œํ”Œ๋ฆฟ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋กœ ์ „์†ก๋œ๋‹ค.
โ€ข
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์—์„œ ์ฟผ๋ฆฌ ํ…œํ”Œ๋ฆฟ์„ ํŒŒ์‹ฑ, ์ตœ์ ํ™”, ์ปดํŒŒ์ผํ•˜๊ณ , ์‹คํ–‰ ๊ณ„ํš์„ ์ €์žฅํ•ด ๋†“๋Š”๋‹ค.
โ€ข
ํด๋ผ์ด์–ธํŠธ๋Š” ๋ณ€์ˆ˜ ๊ฐ’(์‚ฌ์šฉ์ž ์ž…๋ ฅ)์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋กœ ์ „์†กํ•œ๋‹ค.
โ€ข
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์—์„œ ์ €์žฅ๋œ ์‹คํ–‰ ๊ณ„ํš์— ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•œ ํ›„, ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
Prepared Statements ๋ฐฉ์‹์—์„œ๋Š” ์ฟผ๋ฆฌ ํ…œํ”Œ๋ฆฟ๊ณผ ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ถ„๋ฆฌ๋˜์–ด ์ „์†ก๋˜๋ฏ€๋กœ, ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด SQL ๊ตฌ๋ฌธ์— ์ง์ ‘ ํฌํ•จ๋˜์ง€ ์•Š์•„ SQL ๋ฌธ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ธฐ์— SQL Injection์„ ํšจ๊ณผ์ ์œผ๋กœ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

DB๋ณ„ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์˜ˆ๋ฅผ ๋“ค๋ฉด SQL๋ฌธ ์•ˆ์— ? (๋ฌผ์Œํ‘œ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋ฌผ์Œํ‘œ์™€ ์ธ์ž๋ฅผ ๋งค์นญ์‹œํ‚ค๋Š” Placeholder ๋ฐฉ์‹์„ ํ†ตํ•ด ๋ฐ”์ธ๋”ฉ ๋ณ€์ˆ˜๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๊ตฌ์กฐ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.
๊ฐ„๋‹จํžˆ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
1.
PHP
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->execute([$username, $password]);
PHP
๋ณต์‚ฌ
2.
Python
cursor.execute('SELECT * FROM users WHERE username = %s AND password = %s', (username, password))
Python
๋ณต์‚ฌ
3.
Java
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?"); pstmt.setString(1, username); pstmt.setString(2, password); ResultSet rs = pstmt.executeQuery();
Java
๋ณต์‚ฌ
4.
Ruby
stmt = conn.prepare('SELECT * FROM users WHERE username = ? AND password = ?') stmt.execute(username, password)
Ruby
๋ณต์‚ฌ
5.
Node.js
db.query('SELECT * FROM users WHERE username = ? AND password = ?', [username, password], (err, result) => { // handle result or error });
JavaScript
๋ณต์‚ฌ
์ด๋ฅผ ๋‹ค์Œ 4๊ฐœ DB์— ๋Œ€ํ•ด Python, JS, PHP ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ •๋ฆฌํ–ˆ๋‹ค.
๋Œ€๋ถ€๋ถ„ import ๋ฐฉ์‹๋งŒ ๋‹ค๋ฅผ ๋ฟ ๊ฑฐ์˜ ๋™์ผํ•œ ํ˜•ํƒœ๋ฅผ ๋ˆ๋‹ค.
โ€ข
MySQL
โ€ข
postgresql
โ€ข
oracle
โ€ข
mariadb

1. MySQL

python

import MySQLdb conn = MySQLdb.connect(host=host, user=user, passwd=passwd, db=db) cursor = conn.cursor() query = "SELECT * FROM mytable WHERE column1 = %s AND column2 = %s" params = ("value1", "value2") cursor.execute(query, params) result = cursor.fetchall()
Python
๋ณต์‚ฌ

javascript(node.js)

const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'mydb' }); const query = 'SELECT * FROM mytable WHERE column1 = ? AND column2 = ?'; const values = ['value1', 'value2']; connection.query(query, values, function (error, results, fields) { if (error) throw error; console.log('The result is: ', results); });
JavaScript
๋ณต์‚ฌ

PHP

PHP์—์„œ MySQL Prepared Statements๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” mysqli๋˜๋Š” PDOํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค
๋Œ€์ฒด๋กœ PDO ํด๋ž˜์Šค๊ฐ€ ๋Œ€๋ถ€๋ถ„์˜ DB์—์„œ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— PDO๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
mysqli
$servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; // Create connection $conn = mysqli_connect($servername, $username, $password, $dbname); // Prepare statement $stmt = mysqli_prepare($conn, "SELECT * FROM mytable WHERE column1 = ? AND column2 = ?"); // Bind parameters mysqli_stmt_bind_param($stmt, "ss", $value1, $value2); // Set parameters and execute $value1 = "value1"; $value2 = "value2"; mysqli_stmt_execute($stmt); // Fetch results $result = mysqli_stmt_get_result($stmt); $data = mysqli_fetch_all($result, MYSQLI_ASSOC);
PHP
๋ณต์‚ฌ
PDO (PHP Data Objects)
$servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; // Create connection $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // Prepare statement $stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2"); // Bind parameters $stmt->bindParam(':value1', $value1); $stmt->bindParam(':value2', $value2); // Set parameters and execute $value1 = 'value1'; $value2 = 'value2'; $stmt->execute(); // Fetch results $result = $stmt->fetchAll();
PHP
๋ณต์‚ฌ

2. PostgreSQL

python

import psycopg2 conn = psycopg2.connect(host=host, user=user, password=password, dbname=dbname) cursor = conn.cursor() query = "SELECT * FROM mytable WHERE column1 = %s AND column2 = %s" params = ("value1", "value2") cursor.execute(query, params) result = cursor.fetchall()
Python
๋ณต์‚ฌ

javascript(node.js)

const { Pool } = require('pg'); const pool = new Pool({ user: 'username', host: 'localhost', database: 'mydb', password: 'password', port: 5432 }); const query = { text: 'SELECT * FROM mytable WHERE column1 = $1 AND column2 = $2', values: ['value1', 'value2'], }; pool.query(query, (err, res) => { if (err) { console.error(err); return; } console.log(res.rows); pool.end(); });
JavaScript
๋ณต์‚ฌ

PHP

$servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; // Create connection $conn = new PDO("pgsql:host=$servername;dbname=$dbname", $username, $password); // Prepare statement $stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2"); // Bind parameters $stmt->bindParam(':value1', $value1); $stmt->bindParam(':value2', $value2); // Set parameters and execute $value1 = 'value1'; $value2 = 'value2'; $stmt->execute(); // Fetch results $result = $stmt->fetchAll();
PHP
๋ณต์‚ฌ

3. Oracle

python

import cx_Oracle conn = cx_Oracle.connect(user, password, dsn) cursor = conn.cursor() query = "SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2" params = {"value1": "value1", "value2": "value2"} cursor.execute(query, params) result = cursor.fetchall()
Python
๋ณต์‚ฌ

javascript(node.js)

const oracledb = require('oracledb'); async function run() { let connection; try { connection = await oracledb.getConnection({ user: 'hr', password: 'welcome', connectString: 'localhost/orcl' }); const result = await connection.execute( `SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2`, ['value1', 'value2'] ); console.log(result.rows); } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } run();
JavaScript
๋ณต์‚ฌ

PHP

$servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; // Create connection $conn = new PDO("oci:host=$servername;dbname=$dbname", $username, $password); // Prepare statement $stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = :value1 AND column2 = :value2"); // Bind parameters $stmt->bindParam(':value1', $value1); $stmt->bindParam(':value2', $value2); // Set parameters and execute $value1 = "value1"; $value2 = "value2"; $stmt->execute(); // Fetch results $result = $stmt->fetchAll();
PHP
๋ณต์‚ฌ

4. MariaDB

python

import mysql.connector cnx = mysql.connector.connect( host="localhost", user="username", password="password", database="mydb" ) cursor = cnx.cursor(prepared=True) stmt = "SELECT * FROM mytable WHERE column1 = ? AND column2 = ?" params = ("value1", "value2") cursor.execute(stmt, params) result = cursor.fetchall() for row in result: print(row) cursor.close() cnx.close()
Python
๋ณต์‚ฌ

javascript(node.js)

const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'username', password: 'password', database: 'mydb' }); const query = 'SELECT * FROM mytable WHERE column1 = ? AND column2 = ?'; const values = ['value1', 'value2']; connection.query(query, values, function (error, results, fields) { if (error) throw error; console.log('The result is: ', results); });
JavaScript
๋ณต์‚ฌ

PHP

$servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; // Create connection $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // Prepare statement $stmt = $conn->prepare("SELECT * FROM mytable WHERE column1 = ? AND column2 = ?"); // Bind parameters $stmt->bindParam(1, $value1); $stmt->bindParam(2, $value2); // Set parameters and execute $value1 = "value1"; $value2 = "value2"; $stmt->execute(); // Fetch results $result = $stmt->fetchAll();
PHP
๋ณต์‚ฌ

โœ“ ๋‹ค๋ฅธ [์ •๋ฆฌ] ํฌ์ŠคํŠธ

๋ฒ ํŠธ๋‚จ ํ™˜์ „ ์™œ ํ•œ๊ตญ์—์„œ ํ•˜๋ฉด ์•ˆ๋ ๊นŒ? (ํ•œ๊ตญ vs ๊ณตํ•ญ vs ๊ธˆ์€๋ฐฉ)
Travel
๋ฒ ํŠธ๋‚จ ํ™˜์ „ ์™œ ํ•œ๊ตญ์—์„œ ํ•˜๋ฉด ์•ˆ๋ ๊นŒ? (ํ•œ๊ตญ vs ๊ณตํ•ญ vs ๊ธˆ์€๋ฐฉ)
Travel
Load more
๏ธŽ ๋” ๋งŽ์€ ๊ฒŒ์‹œ๋ฌผ์„ ๋ณด๋ ค๋ฉด
๏ธŽ ์ž‘์„ฑ์ž๊ฐ€ ๊ถ๊ธˆํ•˜๋ฉด?
ย 2023.ย Absolroot all rights reserved.