virusdefender 发布的文章

Django 生成的数据库表 id 字段溢出问题

某个系统,突然数据库插不进去数据,报错如下

[2017-04-22 23:17:55] - [ERROR] - [utils.api.api:146]  - integer out of range
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
psycopg2.DataError: integer out of range

然后表结构是这样的

user=# select * from acl_ip_data_id_seq;
   sequence_name    | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
--------------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
 acl_ip_data_id_seq | 2147550630 |           1 |            1 | 9223372036854775807 |         1 |           1 |       7 | f         | t
(1 row)

看到21亿这个数字很熟悉,是 int 最大值,怀疑是数据库 id 字段达到了最大值,无法继续增长了。

这个表是 Django ORM 生成的,看了下 migration,这个字段是AutoField,发现其实就是IntegerField

https://docs.djangoproject.com/en/1.9/ref/models/fields/#autofield

但是只有 Django 1.10 才支持更大的整形 ID 字段

https://docs.djangoproject.com/en/1.10/ref/models/fields/#bigautofield

前几天刚看了饿了么的技术一个故障分析,是一样的原因 http://efs.ele.me/?p=246 结果过了几天就遇见了。

前端MVVM框架可能出现的安全问题

这些年,AngularJS、React 和 Vue.js 算是前端框架中比较热门的,相对于 jQuery 等框架,有一些不太一样的可能出现问题的点,当然都是集中在 XSS 上。

模板注入

类似后端模板注入,前端模板注入也是存在的,被分析最多的还是 AngularJS,详见 https://docs.angularjs.org/guide/security

  • 后端直接生成前端模板,比如{{1+1}},然后AngularJS 去解析和执行。
  • 部分表达式和表达式 parser 的参数可以被控制,比如$watch(userContent, ...) $compile(userContent)

之前的 AngularJS 是有个沙箱的,隔离了部分 runtime context,但是最新版本中去除了,因为多次的被绕过,而且并没有真正的提升安全性。

在其他框架中也是存在类似的问题的、

直接插入 HTML

MVVM框架一般不需要关心 dom 操作,但是有时候还必须手动的插入和控制一些 HTML,框架也是提供了相关的方法的。

  • Vue.js 的{{{ data }}}v-html
  • AngularJS 的$sce.trustAsHtml
  • React 的dangerouslySetInnerHTML

这时候就应该认真检查用户输入的数据了。

我感觉 AngularJS 和 React 的函数名字设计的特别科学,你要知道 trust 那些 dangerous 的数据才可以,还比如 grpc 中,使用非 SSL 的时候,方法名是add_insecure_port

SSR

为了解决 SPA 页面的 SEO 问题的,主流框架也提供了 SSR 方案,但是 SSR 的时候就经常的忘记了转义和过滤,一个是说程序员的问题,使用了危险的函数,另外一个就是框架的漏洞了。

比如新版知乎页面使用了 SSR,会先把用户的问题输出到页面上,然后后续再执行 JS 做进一步的动作,然后估计是使用了dangerouslySetInnerHTML,导致用户问题中的 JS 被执行,导致了XSS。

请输入图片描述

Vue.js 在 SSR 的时候,默认会转义用户输入,但是在样式中忘记处理了,导致了 XSS。见下面的 demo

var Vue = require('vue')
var app = new Vue({
  data () {
    return {
        xss: '"><script>alert(1)</script>'
    }
  },
  render: function (h) {
    return h('a', {style: {color: this.xss}}, 'foo')
  }
})
var renderer = require('vue-server-renderer').createRenderer()
renderer.renderToString(app, function (error, html) {
  if (error) throw error
  console.log(html)
})

英语流利说-懂你英语使用感受

一个偶然的机会接触到了英语流利说,很惊喜,可以通过自动化的语音识别来标注发音情况。

根据一些资料,英语流利说是使用了离线的神经网络语音识别,因为已知正确的文本和发音,只需要将用户的发音尽量和已知文本上对齐就好了,也就是GOP算法。

英语流利说课程分两大部分,一个是独立的小课程,比如"排名前十的旅行问题"、"不做学霸做面霸",每个课程分为几十个关卡,每个关卡讲一个小问题,大约10分钟之内就可以搞定一个。另一部分就是懂你英语了,也是本文重点说的。

开始购买了一个月的懂你英语,之后购买了半年。价格是单月购买99元,半年499元。因为是机器语音识别,感觉利润率还是挺高的。

在课程结束的时候,如果你的学习效率和平均得分达到90,总计学习时间达到90小时,是可以全额退还学费的。我一开始学习的时候,学习效率是60,目前已经达到了80多。平均得分倒一直是90多分左右,两个月内学习时间是57个小时。

IMG_1945.PNG

优点

  • 比免费的课程要质量高一些,更系统一些。
  • 有一个学习群,有班主任,每天提出一个话题来讨论,同时公布前一天大家的学习情况,有竞争的感觉。而且有时候会有活动,比如三个人连续三天都学习超过半小时,可以延长课程时间或者赠送付费课程等。
  • 卡片式任务,已经有不少app使用这种设计了,将一个整体划分为系统性的小任务,每天都会有清晰的目标。一个Level一般包括4个Unit,每个Unit包括4个卡片,每个卡片上有6个Lesson。包括Listening,Vocabulary,Dialogue,Reading,Matching, Grammar,Speaking,Dictation等类型。基本上一个Lesson认真的学习要花费一个小时左右的时间(部分练习性质的除外),包括逐句的录音和完成Lesson中的题目。

IMG_1180.PNG

  • 打卡,数据统计等对于安排学习和了解学习效果很有帮助。
  • 确实有"沉浸式的英语学习体验"
  • 难度控制的不错,我从Level 3开始学的,现在在准备Level 4的考试。通过考试才能进入下一个Level。总体来说,难度有所增加,但是变化很平缓。

要吐槽的也有一些

  • iOS app bug有点多,集中在各种奇怪的加载失败,进度不同步,切换动画卡死。拼写题在搜狗输入法下完全不能用,正确的填写也是提示错误,而且各种卡顿和输入法跳来跳去,使用原生输入法才可以。有些计时录音的句子,录出来的丢头丢尾。
  • 班主任之间差别也非常大,有的班主任感觉对我们特别好,每天在群里比较活跃,交流很多东西,有时候间隔几天没有学习也会主动的来找你问。而有的个班主任,每天就是简单的公布一下学习情况和讨论话题就基本结束了,也不是经常参与我们的讨论。
  • 班主任发的每日一句之类的并没有什么用处。
  • 对于Level 4,Speaking需要拿到至少三星,其他必须满分四星(得分率大于95%)才能参加考试。这个还是挺有难度的。虽然个别情况下也可以找班主任解锁参加考试,但是对于我来说,我真的不是特别追求每个Lesson都非常完美,否则花费的时间就太多了。
  • 金币兑换模块实在是太low了,帮助各种垃圾app做推广,还好不太显眼,一般不会点进去。看看人家扇贝商城,至少还是些有用的东西。https://shop108363553.taobao.com/

疑惑

  • 免费课程是照着句子读,然后显示纠正结果,但是懂你英语的理念是无文本,没有字幕的,虽然可以跟读和录音,读的好可以拿到一个金币,但是并看不到哪里读的不好。有些句子在后面跟读练习的时候可以看到文本,但是看不到的而且实在听不出来的就只能放弃。同时这里的拿到一个金币与后面练习中的录音拿到90+的门槛差别太大了。也直接影响了每个Lesson的得分。建议是句子跟读超过五遍就应该显示文本了。(目前4.4版本增加了单词功能,该问题略有改善)

  • 怎么去评价学习了懂你英语之后的效果?因为学习的时候,练习和口语水平测试都是课程中的句子,这样会不会让人的思维限制在了已有的课程上?

  • 流利说对于简单单词匹配的特别严格,比如anthe之类的,而对已长一些的单词,有时候读的有个别错误也没有发现。感觉是训练数据的问题,简单单词训练的比较多。比如下图。而且怀疑部分数字类型的数据标注的位置不太对,比如1%或者1960s这种,怎么读就是标红。

IMG_1178.PNG

收获

  • 英语水平肯定是有提高的,但是具体提高了多少,怎么去衡量,就是"疑惑"中的第二个问题
  • 认识了五个小伙伴,组成一个小群。从大学生到工作党到家庭主妇,共同的特点就是都学习非常努力,有的是工作压力,有的是为了给孩子树立榜样同时教孩子学习。群里每天至少学习打卡半小时,否则要发红包的。有时候也会聊学习经验,生活等等各种话题。
  • 购买了梦想板课程,虽然略贵,但是有收获就是值得的~

Update:

  • 4.12 博主已经成功的退学费。最后效率不太够,我疯狂学习了几天 Level 1 和 2 的课程,然后成长量超高,就很快达标了。
  • 4.15 新更新的5.0版本真是丑爆了,首页太杂乱

Python 模板字符串与模板注入

这几年比较火的一个漏洞就是jinjia2之类的模板引擎的注入,通过注入模板引擎的一些特定的指令格式,比如{{1+1}}而返回了2得知漏洞存在。实际类似的问题在Python原生字符串中就存在,尤其是Python 3.6新增f字符串后,虽然利用还不明确,但是应该引起注意。

最原始的%

userdata = {"user" : "jdoe", "password" : "secret" }
passwd  = raw_input("Password: ")

if passwd != userdata["password"]:
    print ("Password " + passwd + " is wrong for user %(user)s") % userdata

如果用户输入%(password)s那就可以获取用户的真实密码了。

format方法相关

https://docs.python.org/3/library/functions.html#format

除了上面的payload改写为print ("Password " + passwd + " is wrong for user {user}").format(**userdata)之外,还可以

>>> import os
>>> '{0.system}'.format(os)
'<built-in function system>'

会先把0替换为format中的参数,然后继续获取相关的属性。

但是貌似只能获取属性,不能执行方法?但是也可以获取一些敏感信息了。

例子: http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/

CONFIG = {
    'SECRET_KEY': 'super secret key'
}

class Event(object):
    def __init__(self, id, level, message):
        self.id = id
        self.level = level
        self.message = message

def format_event(format_string, event):
    return format_string.format(event=event)

如果format_string{event.__init__.__globals__[CONFIG][SECRET_KEY]}就可以泄露敏感信息。

理论上,可以通过类的各种继承关系找到想要的信息,比如在Django中的思路为 https://xianzhi.aliyun.com/forum/read/615.html

Python 3.6中的f字符串

这个字符串非常厉害,和Javascript ES6中的模板字符串类似,有了获取当前context下变量的能力。

https://docs.python.org/3/reference/lexical_analysis.html#f-strings

>>> a = "Hello"
>>> b = f"{a} World"
>>> b
'Hello World'

而且不仅仅限制为属性了,代码可以执行了。

>>> import os
>>> f"{os.system('ls')}"
bin      etc      lib      media    proc     run      srv      tmp      var
dev      home     linuxrc  mnt      root     sbin     sys      usr
'0'

>>> f"{(lambda x: x - 10)(100)}"
'90'

但是貌似没有把一个普通字符串转换为f字符串的方法,也就是说用户很可能无法控制一个f字符串,可能无法利用,还需要继续查一下。

2017

2015年经历的太多,而又不想写出来。

2016年看似风平浪静,其实可能还有更大的考验在等着。

2016年“重大”事件记录

  • 6月份之前,借助之前的一个开源项目写了毕业论文,顺便当做说明书用。第一次用$\LaTeX$,一个让人又爱又恨的语言。当然答辩之类的都是小意思,水水就过了。
  • 毕业,离开青岛的日子,最怀念的还是青岛的环境和空气,还有大海。

psb (13).jpg

D71BFAC1CAF195E807612573F8B6E0CB.jpg

(刚毕业就两个结婚的了,2333,羡慕和祝福)

  • 考驾照,用时不到两个月,科目一是90多分,其他都是满分。
  • 正式入职长亭,一家年轻有活力的公司。作为公司最弱最水的程序员,要向各位师傅大佬们学习才行。
  • 去看了五月天音乐会,没错,就是上面的照片上最右边的家伙天天在宿舍用五月天的歌弹吉他,才让我喜欢上的。总结帖 https://virusdefender.net/index.php/archives/752/
  • 第一次合租,第一次去xx地方玩,第一次接触xx技术就略而不谈了

2017 展望

  • 计划拿出2W+的钱重点学习英语和撩妹技巧弹琴,除了写代码也得多接触一些其他行业的人和事情。
  • 学习数学和一切还不会的计算机知识(以后会有更详细的规划)
  • 培养更强的思维能力
  • 锻炼身体

夫夷以近,则游者众;险以远,则至者少。而世之奇伟、瑰怪,非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也。

Hello, 2017~