99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學院 頭像
蘋果6袋
6
麥子學院

Python 中如何防止sql注入?

發(fā)布時間:2017-03-02 14:06  回復:0  查看:1987   最后回復:2017-03-02 14:06  
大家應該都知道現(xiàn)在web 漏洞之首莫過于 sql 了,不管使用哪種語言進行 web 后端開發(fā),只要使用了關系型數(shù)據(jù)庫,可能都會遇到 sql 注入攻擊問題。那么在 Python web開發(fā) 的過程中sql 注入是怎么出現(xiàn)的呢,又是怎么去解決這個問題的 ?
  當然,我這里并不想討論其他語言是如何避免sql 注入的,網(wǎng)上關于 PHP( 博主注:據(jù)說是世界上最屌的語言 ) 防注入的各種方法都有, Python 的方法其實類似,這里我就舉例來說說。
   起因
  漏洞產(chǎn)生的原因最常見的就是字符串拼接了,當然,sql 注入并不只是拼接一種情況,還有像寬字節(jié)注入,特殊字符轉義等等很多種,這里就說說最常見的字符串拼接,這也是初級程序員最容易犯的錯誤。
  首先咱們定義一個類來處理mysql 的操作
   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)
  selfself.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 操作 mysql 數(shù)據(jù)庫的腳本我都會寫進去這個類,那么這個類有問題嗎 ?
  答案是:有!
  這個類是有缺陷的,很容易造成sql 注入,下面就說說為何會產(chǎn)生 sql 注入。
  為了驗證問題的真實性,這里就寫一個方法來調用上面的那個類里面的方法,如果出現(xiàn)錯誤會直接拋出異常。
   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 語句,很明顯傳入的參數(shù)  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")
  回顯報錯,很眼熟的錯誤,這里我傳入的測試參數(shù)是
  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  來代替要傳入的參數(shù),看起來是不是非常像預編譯的 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>  對傳入的參數(shù)進行編碼轉義
  2>  使用 Python MySQLdb 模塊自帶的方法
  第一種方案其實在很多PHP 的防注入方法里面都有,對特殊字符進行轉義或者過濾。
  第二種方案就是使用內部方法,類似于PHP 里面的 PDO ,這里對上面的數(shù)據(jù)庫類進行簡單的修改即可。
  修改后的代碼
   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)
  selfself.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  執(zhí)行的時候傳入兩個參數(shù),第一個是參數(shù)化的 sql 語句,第二個是對應的實際的參數(shù)值,函數(shù)內部會對傳入的參數(shù)值進行相應的處理防止 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 注入漏洞的代碼會慢慢改過來,好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助。
來源:51CTO

您還未登錄,請先登錄

熱門帖子

最新帖子

?