Python 에서 sql 주입 을 방지 하 는 방법 에 대한 상세 한 설명

5193 단어 pythonsql 주입
머리말
현재 웹 구멍 의 첫 번 째 는 sql 입 니 다.어떤 언어 로 웹 백 엔 드 개발 을 하 든 관계 형 데이터 베 이 스 를 사용 하면 sql 주입 공격 문 제 를 만 날 수 있 습 니 다.그렇다면 Python 웹 개발 과정 에서 sql 주입 은 어떻게 발생 했 습 니까?이 문 제 를 어떻게 해결 하 였 습 니까?
물론,나 는 다른 언어 가 sql 주입 을 어떻게 피 하 는 지 에 대해 토론 하고 싶 지 않다.ǘ파 이 썬 을 추가 하 는 방법 은 사실 유사 하 다.여기 서 나 는 예 를 들 어 말 하 겠 다.
원인
구멍 이 생 긴 원인 중 가장 흔히 볼 수 있 는 것 은 문자열 연결 입 니 다.물론 sql 주입 은 하나의 상황 만 이 아니 라 넓 은 바이트 주입,특수 문자 전의 등 여러 가지 가 있 습 니 다.여기 서 가장 흔히 볼 수 있 는 문자열 연결 을 말 하 는 것 도 초급 프로그래머 가 가장 쉽게 범 하 는 오류 입 니 다.
우선 my sql 작업 을 처리 할 클래스 를 정의 합 니 다.

class Database:
 aurl = '127.0.0.1'
 user = 'root'
 password = 'root'
 db = 'testdb'
 charset = 'utf8'

 def __init__(self):
  self.connection = MySQLdb.connect(self.aurl, 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()
이 코드 는 제 가 이전에 많은 스 크 립 트 에서 볼 수 있 었 습 니 다.Python 이 my sql 데이터 베 이 스 를 조작 하 는 스 크 립 트 와 관련 된 스 크 립 트 를 저 는 모두 이런 종류 에 썼 습 니 다.그러면 이런 종류 에 문제 가 있 습 니까?
정 답 은 있다!
이 종 류 는 결함 이 있어 서 sql 주입 을 쉽게 만 들 수 있 습 니 다.다음은 왜 sql 주입 이 생 겼 는 지 말씀 드 리 겠 습 니 다.
문제 의 진실성 을 검증 하기 위해 서 는 위의 그 종류의 방법 을 사용 하 는 방법 을 쓰 고 오류 가 발생 하면 바로 이상 을 던 집 니 다.

def test_query(articleurl):
 mysql = Database()
 try:
  querySql = "SELECT * FROM `article` WHERE url='" + articleurl + "'"
  chanels = mysql.query(querySql)
  return chanels
 except Exception, e:
  print e
이 방법 은 매우 간단 합 니 다.가장 흔히 볼 수 있 는 select 조회 문 구 는 가장 간단 한 문자열 을 사용 하여 sql 문 구 를 구성 합 니 다.들 어 오 는 매개 변수 인 articleurl 을 제어 할 수 있 습 니 다.주입 테스트 를 하려 면 articleurl 의 값 뒤에 작은 따옴표 만 추가 하면 sql 주입 테스트 를 할 수 있 습 니 다.이것 은 말 할 것 도 없 이 구멍 이 있 을 것 입 니 다.스 크 립 트 를 한 번 뛰 어 볼 수 있 습 니 다.어떤 결 과 를 보다

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''t.tips''' at line 1")
리 턴 오류,낯 익 은 오류,여기 제 가 들 어 온 테스트 매개 변 수 는?

t.tips'
다음은 주입 을 초래 하 는 상황 을 다시 한 번 말씀 드 리 지만 위의 방법 을 약간 수정 한 후

def test_query(articleurl):
 mysql = Database()
 try:
  querySql = ("SELECT * FROM `article` WHERE url='%s'" % articleurl)
  chanels = mysql.query(querySql)
  return chanels
 except Exception, e:
  print e
이 방법 은 문자열 을 직접 사용 하지 않 고 들 어 올 인 자 를%s 로 대체 합 니 다.미리 컴 파일 된 sql 처럼 보이 지 않 습 니까?그럼 이런 표기 법 은 sql 주입 을 방지 할 수 있 습 니까?테스트 해 보면 다음 과 같다 는 것 을 알 수 있다.

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''t.tips''' at line 1")
위의 테스트 결과 와 마찬가지 로 이런 방법 도 안 됩 니 다.그리고 이런 방법 은 sql 문 구 를 미리 컴 파일 하 는 것 이 아 닙 니 다.그러면 어떻게 해 야 sql 주입 을 방지 할 수 있 습 니까?
해결 하 다.
두 가지 방안
     1>들 어 오 는 매개 변 수 를 인 코딩 하여 의 미 를 바 꿉 니 다.
     2>Python 의 MySQLdb 모듈 을 사용 하여 자체 적 으로 가 져 오 는 방법
첫 번 째 방안 은 사실 많은 PHP 의 주입 방지 방법 에 특수 문 자 를 전의 하거나 여과 하 는 것 이 있다.
두 번 째 방안 은 내부 방법 을 사용 하 는 것 입 니 다.PHP 에 있 는 PDO 와 유사 합 니 다.여기 서 위의 데이터 베이스 류 를 간단하게 수정 하면 됩 니 다.
수 정 된 코드

class Database:
 aurl = '127.0.0.1'
 user = 'root'
 password = 'root'
 db = 'testdb'
 charset = 'utf8'

 def __init__(self):
  self.connection = MySQLdb.connect(self.aurl, 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 모듈 내부 에서 목록 을 원 그룹 으로 정렬 한 다음 에 escape 작업 을 할 수 있 습 니 다.
총결산
제 가 예전 에 스 크 립 트 에서 sql 주입 구멍 이 있 는 코드 를 사 용 했 습 니 다.자,이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 주 십시오.

좋은 웹페이지 즐겨찾기