邮件模板预览接口把用户填的标题直接交给 render_template_string,标题写 {{7*7}} 返回 49,写 {{config}} 直接把 SECRET_KEY 打印在页面上。日志里能对上时间点,这种反而好排。
模板引擎把输入当成模板源码解析,双花括号里的表达式会被求值。上下文里还能摸到 config 和内置函数,顺着调用链能读到文件甚至执行命令。模板和数据混在了一起。这一点先确认清楚,后面就不用反复试。
render_template('mail/preview.html', title=user_title)
这次卡住的地方就在「模板注入 SSTI」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
处理上按这个顺序:模板字符串只从固定目录加载 不接收用户给的模板体;用户内容通过变量传入 由模板自己决定怎么展示;关闭模板的沙箱外能力 或换用逻辑更少的模板;预览接口加输入长度和字符白名单。
结果对不对很好判断,标题再填 {{7*7}} 页面原样显示这七个字符 不再出现 49 和配置项。
