*文章原创作者:傻傻傻傻傻子,本文属于FreeBuf原创奖励计划,未经许可禁止转载
webpack用于编译JavaScript模块。关注javascript技术的同学一定知道,在CommonJS和ES6中,为了支持模块化,而引入了export/require/import这类东西,模块化可以降低开发的复杂度,用于支撑前端的复杂功能,但是模块化后,也带来了许多问题,比如老版本的浏览器不支持ES6/JSX语法,开发和线上不能保持一致,这就为WebPack类的自动化代码转换工具的出现提供了需求。
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。按照官网的说法,webpack可以打包一切资源/图片/样式/依赖等等,webpack默认只支持js模块打包,对于其他文件就需要用loader解析器,比如在vue中,直观的效果就是使用webpack可以将使用的vue,css,图片等打包成一个js。
随着前后端分离架构的大众化 ,越来越多的开发团队采用这种开发模式。前后端的交互越来越多是通过API完成,而不再依赖页面刷新,众多的后端的框架也把自己定位成一个API框架,如thinkphp5等。通过分析前端js代码,找到前后端交互的接口,对接口进行测试变得越来越重要,比如在某些没权限的场景下,我们无法完整显示页面,可以通过分析前端js中的ajax接口进行测试。
这里我就拿几个案例说说:
1.某次挖漏洞过程中,登陆后显示账号没有权限,页面显示403 forbiden,f12 sources 发现前端使用VUE框架,分析源码对一ajax接口进行测试发现存在越权。
2.某次挖漏洞过程中,通过分析前端js代码,发现存在一段代码,代码逻辑是在debugMode下,会setCookie,尝试使用该Cookie,成功进入后台并且是管理员权限。
在VUE/REACT开发场景下 ,前端开发会引入如模块化等诸多新特性,前端开发不再是几个简单的js文件,开发完成后会通过webpack等打包工具打包生成部署使用的js文件,但是如果我们直接分析该编译的js,很难看懂。比如我这个demo:https://blog.donot.me/assets/demo/index.html,页面下的app.bundle.js反正我是看不懂写的是啥,这个js文件就是webpack打包后的结果,但是由于我是开启了source-map调试模式,如果你是用chrome浏览器打开的,打开devtools-sources,应该可以看到一个webpack://,这个就是chrome对source-map调试的支持,点开src目录下就可以看到js代码源文件。
webpack目前支持很多种调试模式,每种模式的区别是编译后的代码和源码的映射方式不同,具体的体现是源码通过什么方式呈现,有的模式会生产一个.map文件,有的模式会通过注释,有的模式会使用DataUrl的方式。
模式 | 解释 |
---|---|
(none) | 不生成 |
eval | 每个module会封装到eval里包裹起来执行,并且会在末尾追加注释 //# sourceURL=webpack:///./src/index.js |
source-map | 生成一个SourceMap文件.并在末尾添加注释。 |
hidden-source-map | 和 source-map 一样,但不会在 bundle 末尾追加注释. |
inline-source-map | 生成一个DataUrl形式的 SourceMap 文件. |
eval-source-map | 每个module会通过eval()来执行,并且生成一个DataUrl形式的SourceMap. |
cheap-source-map | 生成一个没有列信息(column-mappings)的SourceMaps文件,不包含loader的sourcemap(譬如 babel 的 sourcemap) |
cheap-module-source-map | 生成一个没有列信息(column-mappings)的SourceMaps文件,同时loader的sourcemap也被简化为只包含对应行的。 |
webpack不仅支持这8种,而且它们还是可以任意组合上面的eval、inline、hidden关键字,就如文档所说,你可以设置souremap选项为cheap-module-inline-source-map。这里为啥要搞这么多模式我也不懂,nodejs作者也表示自己看不懂,但是作为一个研究安全问题的同学来说,我可以不关心具体使用了哪种模式,任何一种开启了source-map的情况下,chrome开发者工具会帮我们处理好,而我们只需要通过开发者工具下的webpack://查看即可。
上面提到,在开启了source-map的情况下,可以直接分析原始代码,那如果没有开启,该怎么处理呢,除了webpack打包工具外,相信你还听过WebAssembly,WebAssembly是一个主要为了解决js的性能问题而诞生的,其运作方式与java类似,将高级语言编译成字节码然后在WebAssembly虚拟机中运行,支持编译成WebAssembly字节码的语言有AssemblyScript/C/C++/Rust/Golang等,有了WebAssembly,我们的浏览器将会同时加载和运行两种类型的代码——JavaScript和WebAssembly,这两种代码可以通过WebAssembly所提供的js api实现互相调用,可以认为WebAssembly模块是一个“高性能的JS函数” ,比如大家可能遇到需要在前端进行md5等加密签名功能的实现,就很适合使用WebAssembly来完成,这里很重要的问题是WebAssembly不是用来取代Javascript的。这里有一个简单的demo可以感受一下WebAssembly代码结构是什么样的WebAssembly_test_demo:
WebAssembly is designed to maintain the versionless, feature-tested, and backwards-compatible nature of the web. WebAssembly modules will be able to call into and out of the JavaScript context and access browser functionality through the same Web APIs accessible from JavaScript. WebAssembly also supports non-web embeddings.
回到本节的主题,当前端使用Webpack打包,还很不幸未开启Source-map的情况下,以及WebAssembly场景下,当我们需要深入分析代码时,需要使用反编译工具,针对webpack打包,笔者发现了一个反编译工具,https://www.npmjs.com/package/debundle,但是经过测试,反编译webpack打包的项目效果并不好,笔者并未成功反编译成功自己的demo项目,目前在这方面开源工具还是比较缺少的状态。如果有同学使用该工具比较成功的反编译了webpack打包项目欢迎交流。针对WebAssembly有比较成熟的工具包WABT工具包用于反编译,除了该工具包外,也有使用IDA插件进行反编译的方法FLARE脚本系列:使用idawasm IDA Pro插件逆向WebAssembly(Wasm)模块,由于 篇幅和主题限制,本文不再具体介绍这些工具的使用,感兴趣的读者可以自行尝试。
随着前端开发的不断演进,越来越多的开发技术/开发框架诞生,了解他才能更好的去hack it。
*文章原创作者:傻傻傻傻傻子,本文属于FreeBuf原创奖励计划,未经许可禁止转载