>  기사  >  백엔드 개발  >  SQL 인젝션 방지를 위한 Python의 방법 소개

SQL 인젝션 방지를 위한 Python의 방법 소개

巴扎黑
巴扎黑원래의
2017-08-18 17:05:561600검색

머리말

가장 큰 웹 취약점은 다름 아닌 SQL입니다. 웹 백엔드 개발에 어떤 언어를 사용하더라도 관계형 데이터베이스를 사용하는 한 SQL 주입 공격에 직면할 수 있습니다. 그렇다면 Python 웹 개발 중에 SQL 주입은 어떻게 나타나고, 이 문제를 해결하는 방법은 무엇일까요?

물론, 다른 언어에서 SQL 주입을 방지하는 방법에 대해 논의하고 싶지는 않습니다. PHP 주입 방지에 대한 다양한 방법이 있습니다. 여기서는 실제로 유사한 예를 들겠습니다.

원인

취약점의 가장 일반적인 원인은 스트링 스플라이싱입니다. 물론 SQL 인젝션은 단순히 스플라이싱만 하는 것이 아니고, 여기에 언급된 와이드 바이트 인젝션, 특수 문자 이스케이프 등 다른 유형도 많습니다. 가장 일반적인 문자열 연결에 대해 말하면 이는 주니어 프로그래머에게 가장 흔한 실수이기도 합니다.

먼저 mysql 작업을 처리하는 클래스를 정의합니다

class Database:
    hostname = '127.0.0.1'
    user = 'root'
    password = 'root'
    db = 'pythontab'
    charset = 'utf8'
    def __init__(self):
        self.connection = MySQLdb.connect(self.hostname, self.user, self.password, self.db, charset=self.charset)
        self.cursor = self.connection.cursor()
    def insert(self, query):
        try:
            self.cursor.execute(query)
            self.connection.commit()
        except Exception, e:
            print e
            self.connection.rollback()
    def query(self, query):
        cursor = self.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute(query)
        return cursor.fetchall()
    def __del__(self):
        self.connection.close()

이 클래스에 문제가 있나요?

답은: 그렇습니다!

이 클래스는 결함이 있어 SQL 주입이 쉽게 발생하는 이유에 대해 이야기해 보겠습니다.

문제의 진위 여부를 확인하기 위해 위 클래스의 메서드를 호출하는 메서드는 다음과 같습니다. 오류가 발생하면 예외가 직접 발생합니다.

def test_query(testUrl):
    mysql = Database()
    try:
        querySql = "SELECT * FROM `article` WHERE url='" + testUrl + "'"
        chanels = mysql.query(querySql)
        return chanels
    except Exception, e:
        print e

이 방법은 매우 간단합니다. 가장 일반적인 선택 쿼리 문 중 하나는 가장 간단한 문자열 연결을 사용하여 SQL 문을 형성합니다. 전달된 testUrl 매개변수를 제어할 수 있다는 것은 분명합니다. testUrl에만 추가하면 됩니다. 값 뒤에 작은따옴표를 추가하면 SQL 주입 테스트를 수행할 수 있습니다. 말할 것도 없이 스크립트를 실행하여 결과를 확인하세요

(1064, " SQL 구문에 오류가 있습니다. 1번째 줄의 ''t.tips''' 근처에서 사용할 올바른 구문을 보려면 MariaDB 서버 버전에 해당하는 설명서를 확인하세요.)

오류 메시지가 반복됩니다. 매우 친숙한 오류입니다. .여기에 전달한 테스트 매개변수는

t.tips'

위 방법을 살짝 수정한 후

def test_query(testUrl):
    mysql = Database()
    try:
        querySql = ("SELECT * FROM `article` WHERE url='%s'" % testUrl)
        chanels = mysql.query(querySql)
        return chanels
    except Exception, e:
        print e

이 방법은 문자열 접합을 직접 사용하지 않고 %s를 사용하여 주입됩니다. 전달될 매개변수를 바꾸십시오. 미리 컴파일된 SQL과 매우 유사한 것 같습니까? 이런 방식으로 작성하면 SQL 삽입을 막을 수 있나요? 테스트해 보면 응답은 다음과 같습니다.

(1064, "SQL 구문에 오류가 있습니다. ''t.tips 근처에서 사용할 올바른 구문은 MariaDB 서버 버전에 해당하는 설명서를 확인하세요. ''' at line 1")

테스트 결과는 위와 동일하므로 이 방법은 불가능하며, 이 방법은 미리 컴파일된 sql 문도 아닙니다. 그렇다면 sql 주입을 방지하려면 어떻게 해야 할까요?

솔루션

두 가지 솔루션

1> 들어오는 매개변수를 인코딩하고 이스케이프합니다

2> Python의 MySQLdb 모듈과 함께 제공되는 방법을 사용하세요

첫 번째 솔루션은 실제로 많은 PHP 주입 방지 방법에 사용됩니다. 예, 특수 문자는 가능합니다. 이스케이프되거나 필터링됩니다.

두 번째 옵션은 PHP의 PDO와 유사한 내부 메서드를 사용하는 것입니다. 여기서는 위의 데이터베이스 클래스를 간단히 수정할 수 있습니다.

수정된 코드

class Database:
    hostname = '127.0.0.1'
    user = 'root'
    password = 'root'
    db = 'pythontab'
    charset = 'utf8'
    def __init__(self):
        self.connection = MySQLdb.connect(self.hostname, self.user, self.password, self.db, charset=self.charset)
        self.cursor = self.connection.cursor()
    def insert(self, query, params):
        try:
            self.cursor.execute(query, params)
            self.connection.commit()
        except Exception, e:
            print e
            self.connection.rollback()
    def query(self, query, params):
        cursor = self.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute(query, params)
        return cursor.fetchall()
    def __del__(self):
        self.connection.close()

execute가 실행되면 두 개의 매개변수가 전달됩니다. 첫 번째는 매개변수화된 sql 문이고, 두 번째는 전달된 매개변수 값이 함수 내부에서 처리됩니다. SQL 삽입 방지를 위해 해당 처리를 수행합니다. 실제 사용되는 방법은 다음과 같습니다

preUpdateSql = "UPDATE `article` SET title=%s,date=%s,mainbody=%s WHERE id=%s"

mysql. insert(preUpdateSql , [title, date, content,aid])

이것은 SQL 주입을 방지할 수 있습니다. 목록을 전달한 후 MySQLdb 모듈은 목록을 내부적으로 튜플로 직렬화한 다음 이스케이프 작업을 수행합니다.

위 내용은 SQL 인젝션 방지를 위한 Python의 방법 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.