没啥好说的,题目已经把几个关键点给出来了,flask,sql注入,还给了源码
那么就是源码审计,这题sql注入的点属实是有点多,普通的也有,难的也有,也难怪他是个九分题
干就完了,下载源码,第一个注入点是routes.py里面的index路由项
res = mysql.Add("post", ['NULL', "'%s'" % form.post.data,
"'%s'" % current_user.id, "'%s'" % now()])
直接了Add操作,那么这个函数的原型在哪呢,打开pycharm,查找他的原型
发现在others里
def Add(self, tablename, values):
sql = "insert into " + tablename + " "
sql += "values ("
sql += "".join(i + "," for i in values)[:-1]
sql += ")"
try:
self.db_session.execute(sql)
self.db_session.commit()
return 1
except:
return 0
是的,你没有看错,没有任何过滤,他就把sql语句传进数据库了,从调用链来看应该是从__init__.py里面的mysql对象直接调用
routes.py然后再到others.py,也就是这条分链上说没有任何的过滤机制
对照原型,tablename是post,values就是我们[‘NULL’, “’%s’” % form.post.data,"’%s’" % current_user.id, “’%s’” % now()]
其中我们可控的是%form.post.data,是由我们前端post过去的
那么post.data是哪里来的呢,我们在forms.py里面找到了PostForm类,结合之前的东西,我们可以猜出,这就是主页里的留言板
class PostForm(FlaskForm):
post = StringField('Say something', validators=[DataRequired()])
submit = SubmitField('Submit')
总的逻辑都走完了,留言板这块是一点过滤都没有,这也就是最简单的一块,随便注
下面我们要找的是回显逻辑
current_user调用followed_posts方法,找原型,定位到models.py里的
def followed_posts(self):
followedid = mysql.All(
'followers', {
"follower_id": self.id}, ['followed_id'])
tmp = ""