Python을 사용하여 SQL 주입을 방지하는 방법

高洛峰
풀어 주다: 2017-03-16 16:14:26
원래의
1732명이 탐색했습니다.

서문

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


물론 다른 언어에서 sql 주입을 방지하는 방법에 대해 논의하고 싶지는 않습니다. 인터넷에는 Python의 방법이 있습니다. 실제로 비슷합니다. 여기 예를 들어 보겠습니다.

원인

취약점의 가장 흔한 원인은 문자열 스플라이싱입니다. 물론 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
로그인 후 복사

이 방법은 매우 간단합니다. 가장 일반적인 select

쿼리 문 중 하나는 가장 간단한 문자열 연결을 사용하여 SQL 문을 구성하는 매개변수 testUrl이 제어 가능하다는 점입니다. .인젝션 테스트를 하려면 testUrl 값 뒤에 작은따옴표만 추가하면 sql 인젝션 테스트가 가능하다는 것은 말할 필요도 없이 스크립트를 실행해서 결과를 확인하는 것입니다


(1064, "SQL 구문에 오류가 있습니다.

올바른 구문을 MariaDB 서버 버전에 해당하는 설명서를 확인하세요. 1행의 ''t.tips'' 근처에서 사용하려면")

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

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 구문에 오류가 있습니다. '' 근처에서 사용할 올바른 구문은 MariaDB 서버 버전에 해당하는 설명서를 확인하세요. t.tips' '' 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()
로그인 후 복사
여기서 실행이 실행될 때 두 개의 매개변수가 전달됩니다. 첫 번째는 매개변수화된 sql 문이고, 두 번째는 해당 문입니다. 실제 매개변수 값

은 SQL 주입을 방지하기 위해 들어오는 매개변수 값을 그에 맞게 처리합니다. 실제 사용되는 방법은


preUp

date

Sql = "UPDATE `article` SET title=%s,date=%s,mainbody=%s WHERE id=%s" mysql.insert(preUpdateSql , [제목, 날짜, 내용, 보조])

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

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

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿