网站中的基础安全问题

前两天用flask写了个在线聊天室,写完之后把网址发到了群中,没过几分钟群内大佬就把我网站攻破了。于是请教了一下大佬,又查了查资料,稍稍了解了几种网站的攻击方法,下面记录一下

XSS注入

昨天大佬用的就是这个方法,聊天室中必然有一个聊天输入框,在框中输入<script>alert("xss");</script>,由于我当时毫无防护,这条语句会经历这几个步骤,最终实现攻击效果:

  1. 进入html的form中,并当按下提交按钮时,被编入url中,被get到python后端接口上
  2. 后端接口收到并解析出此content,不做校验,直接编入sql语句中,提交至mysql
  3. 当有人访问查询此房间历史聊天记录接口时,python将此数据从mysql中取出,返回给前端js
  4. js将此语句编入html中
  5. html识别到script标签,将此语句作为代码段运行,浏览器跳出弹窗‘xss’

根据文档,应该定义csp来防止内嵌js代码运行。但是我html中本身就有js代码,禁止运行后我的代码都不运行了,打开f12看到有一串hash,根据网上的指示将hash填入csp设置中后(这个hash应该是对我的js代码校验值),我的代码可以正常运行了,正当我感觉解决问题的时候,我发现:每新开一个房间,这个hash值都是不一样的!因为我不可能对所有页面添加对应的hash,此方法无法解决问题

然后又看到一个方案,将js代码写到另一个.js文件中,html中只放一个script标签指向此js文件,但我一个菜鸡将他们分离后发现js报错

于是,我只能在csp中加上'unsafe-inline'来允许内嵌js代码,但不允许从网站外部加载js文件,并对输入的script标签进行识别且转义:

xss_pattern=re.compile(r'<script>(.*?)</script>',re.IGNORECASE) #忽略大小写
matches = re.search(xss_pattern, content).group(1) #获取中间部分
content = re.sub(xss_pattern, '<script>%s</script>'%matches, content) #替换与拼接

这样,script标签会变为普通字符,无法被js解释。不过经实验后,若连续两个标签嵌套,会导致只显示一个script,后面内容全部无法显示,但不会正确执行js

SQL注入

虽然大佬没有使用此方法来攻击,但是昨天有人尝试打出i'm xxx的时候,发现数据无法提交,并反馈给了我。我查了下系统日志,发现它引发了一个sql错误。我的sql语句是拼接字符串得来,若字符串中包含引号,则会导致它参与了sql语句组成,引发安全问题。查询后得知,拼接字符串的sql是应该禁止的,python中的execute提供参数化变量方法,只需这么做即可:

args = (id, name)
sql = "select id, name from test where id=%s and name=%s"
cursor.execute(sql, args)

不过这里让我困扰了一会儿,因为我的sql语句太多,我写了两个函数来简化语句实现,在改动过程中,我将sql与args传入这两个函数执行,但是由于不一定有args参数(我的某些sql语句无变量),所以将args定义为可选参数,在传递过程中,导致了列表外围又嵌套了一层列表,始终无法得到正确结果,最后打印看了一下才发现,将传递过来的*args再次提取即可

还有一个问题,使用这个方法后,%d要全部变为%s,而且%s外面不需要引号,并将数据库中对应列的类型给为text(若不改可以正常运行,但每次操作都会有一条警告)

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注