本次分享的目的,重点在于,让大家对常见的 Web 攻击有一个直观的认知。
当你知道,黑客是通过什么样的漏洞来攻击你的时候,你就更容易理解为什么要通过这样的方式来防范黑客攻击
本次分享不会过多涉及概念、防范的细节、千奇百怪的攻击方式。
有兴趣的同学,可以去找 谷G 同学请教。
演示地址
用户端 (SourceCode)
Hack 端 (SourceCode)
高版本 Chrome 会自动识别部分 XSS 攻击,并禁止你的访问
1 2
| /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --disable-xss-auditor
|
XSS
后端在入库前应该选择不相信任何前端数据,将所有的字段统一进行转义处理。
前端在渲染页面 DOM 的时候应该选择不相信任何后端数据,任何字段都需要做转义处理。
攻击原理
浏览器可以动态加载、渲染页面 DOM,并执行 JS 脚本。
In Practice
Demo - 公开课案例
那么在我们的项目中,是怎么来防范 XSS 攻击的呢?
因为我们已经完全实现了前后端分离,所以我们重点关注服务器端的实现。
在我们的 Web 应用中,没有直接渲染页面的部分,所以,输出过滤也没有;只针对 API 参数的输入做了 XSS 的过滤。
Show The Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public abstract class AskBaseController extends RootController {
public boolean isAntiXssEnabled() { return true; } @InitBinder public void commonInitBinder(final WebDataBinder binder) { if (isAntiXssEnabled()) { binder.registerCustomEditor(String.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { setValue(WebUtil.escapeHtml(text)); }
@Override public String getAsText() { return ObjectUtil.nullToDefault(getValue(), StringConsts.EMPTY).toString(); } }); } } }
public class WebUtil { public static String escapeHtml(String source) { if (StringUtils.isNotEmpty(source)) { StringBuilder buff = new StringBuilder((int)((double)source.length() * 1.3D));
for(int i = 0; i < source.length(); ++i) { char _char = source.charAt(i); switch(_char) { case '"': buff.append("""); break; case '&': if(url) { buff.append(_char); } else { buff.append("&"); } break; case '\'': buff.append("'"); break; case '<': buff.append("<"); break; case '>': buff.append(">"); break; default: buff.append(_char); } } return buff.toString(); } return source; }
|
缺陷
- 以 Controller 为单位,如果设置为关闭,该 Controller 下的所有接口默认都会取消 XSS 的输入过滤
- 依赖于 Spring MVC 容器实现,如果引入其他 MVC 框架,需要重新实现。
CSRF
在服务器端接收到的请求后,去校验这个请求是可信任的
攻击原理