說(shuō)明
- 語(yǔ)言python
- 代碼基于 tornado框架
- 數(shù)據(jù)庫(kù)是用Navicat操作的
- 引入python操作SQL的模塊 pymysql
代碼展示
服務(wù)端代碼:
#聚霜!/usr/bin/env python#! -*- coding:utf-8 -*-
import tornado.ioloop
import tornado.web
import pymysql
class MainHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.render("login.html")
def post(self, *args, **kwargs):
name = self.get_argument("user")
pwd = self.get_argument("pwd")
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='day39')
cursor = conn.cursor()
temp = "select name from login where name='%s' and password='%s'" % (name, pwd)
cursor.execute(temp)
ret = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
if ret:
self.write("登陸成功")
else:
self.write("登陸失敗")
settings = {
"template_path": "views",
"static_path": "static",
}
application = tornado.web.Application([
(r"/login", MainHandler),
], **settings)
if __name__ == "__main__":
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
客戶端代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交">
</form>
</body>
</html>
數(shù)據(jù)庫(kù):
分析:
上面的代碼在檢測(cè)用戶登陸的時(shí)候囊颅,只是用了用戶名去檢測(cè)的炉峰,只是在數(shù)據(jù)庫(kù)中篩選的時(shí)候畏妖,對(duì)密碼加了判斷。
注入測(cè)試
因?yàn)橹饕玫氖莕ame疼阔,where后面的只是判斷戒劫;分析:如果我們能將where后面密碼判斷讓其無(wú)效的話半夷,那么只要用戶名對(duì)了,不也可以登陸嗎迅细?
我們?cè)囍斎耄?/p>
結(jié)果:
很是奇特巫橄!
我們看看服務(wù)端我們獲取的temp組合完之后,是個(gè)什么樣的結(jié)果:
分析:
在SQL中 " -- " ;表示是注釋茵典。
當(dāng)我們輸入一個(gè)單引號(hào)" ' "的時(shí)候;它會(huì)讓前面的name閉合湘换,然后 " -- "形成單獨(dú)的字符,傳入數(shù)據(jù)庫(kù)的時(shí)候统阿,數(shù)據(jù)庫(kù)會(huì)解析字符彩倚,遇到" -- "便會(huì)將后面的內(nèi)容注釋。
此時(shí)的結(jié)果相當(dāng)于之判斷了name砂吞,密碼根本沒(méi)用署恍。
換個(gè)思路,where是一個(gè)判斷蜻直,如果我讓其前面的name判斷的也失效的話盯质,即,這個(gè)where對(duì)名字的限制不起作用概而。那么這段SQL語(yǔ)句的效果就變成:
select name from login
即:只要數(shù)據(jù)庫(kù)對(duì)應(yīng)的表里面有name數(shù)據(jù)呼巷,則就能獲取數(shù)據(jù),結(jié)果就為 true赎瑰。
結(jié)果永遠(yuǎn)登陸成功王悍!
驗(yàn)證上面的分析:
結(jié)果:
服務(wù)端獲取的temp:
說(shuō)明:
密碼判斷配注釋,前面的那么餐曼,判斷的時(shí)候压储,應(yīng)為有 or ;or的意思源譬,它前后判斷條件有一個(gè)為true集惋,結(jié)果就為true。
總結(jié):
字符串的拼接踩娘,在很多語(yǔ)言里面都有這樣的情況刮刑。
解決上面代碼的注入問(wèn)題
python的pymysql模塊,內(nèi)處理了這樣的問(wèn)題养渴,在pymysql中要求我們?cè)谳斎隨QL語(yǔ)句的時(shí)候不要提出來(lái)使用占位符的方式(即 % 方式)雷绢,拼接數(shù)據(jù)。
而是直接輸入 excute 后面的括號(hào)理卑。
修改服務(wù)端代碼:
說(shuō)明:
這里用的圖片展示服務(wù)端代碼修改的地方翘紊;其他地方都沒(méi)變化。
再次測(cè)試:
我們?cè)谳斎胫暗拇a藐唠,結(jié)果:
看看代碼報(bào)錯(cuò)霞溪!
語(yǔ)法報(bào)錯(cuò)孵滞;并將我們輸入的" ' ";進(jìn)行了處理鸯匹。
這樣,只有正確的輸入才能登陸泄伪。其他輸入都會(huì)報(bào)錯(cuò)殴蓬!