USDT第三方支付API接口

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

sakuraの从零更先のIoT破绽挖掘系列(一): Western Digital My Cloud Pro系列PR4100 NAS认证前RCE破绽剖析与行使

简述

本文主要是对crowdstrike团队的pwn2own-tale-of-a-bug-found-and-lost-again文章举行学习,并梳理破绽模式和探讨破绽行使方式,由于笔者手上没有这款固件,若是有人手上有或者用qemu仿真出来了,可以自己调试一下。

FIRMWARE

首先下载有破绽的固件,该破绽从2.31.204版本更先,一直在5.04.114版本修复,跨度长达一年,照样十分值得学习的。
https://downloads.wdc.com/gpl/WDMyCloud_PR4100_GPL_v2.40.155_20200713.tar.gz

攻击面枚举

由于是从零更先的IoT破绽挖掘,从本篇更先我们首先讲述一下,在更先挖掘破绽之前,我们需要做什么。第一件事就是要枚举攻击面,即这个目的它起了哪些服务,然后哪些服务是从外网可以接见。
一样平常可以用Netstat来看这些器械。

  • netstat -tulpn
    • -t tcp
    • -u udp
    • -l listening, Show only listening sockets.
    • -n Show numerical addresses instead of trying to determine symbolic host, port or user names.
    • -p Show the PID and name of the program to which each socket belongs.
root@MyCloudPR4100 root , netstat -tulpn
Active Internet connections (only servers)
Proto Local Address           Foreign Address State  PID/Program name
tcp   0.0.0.0:443             0.0.0.0:*       LISTEN 3320/httpd         
tcp   127.0.0.1:4700          0.0.0.0:*       LISTEN 4131/cnid_metad
tcp   0.0.0.0:445             0.0.0.0:*       LISTEN 4073/ *** bd
tcp   192.168.178.31:49152    0.0.0.0:*       LISTEN 3746/upnp_nas_devic
tcp   0.0.0.0:548             0.0.0.0:*       LISTEN 4130/afpd
tcp   0.0.0.0:3306            0.0.0.0:*       LISTEN 3941/mysqld
tcp   0.0.0.0:139             0.0.0.0:*       LISTEN 4073/ *** bd
tcp   0.0.0.0:80              0.0.0.0:*       LISTEN 3320/httpd 
tcp   0.0.0.0:8181            0.0.0.0:*       LISTEN 1609/restsdk-server
tcp   0.0.0.0:22              0.0.0.0:*       LISTEN 2761/sshd
tcp6  :::445                  :::*            LISTEN 4073/ *** bd
tcp6  :::139                  :::*            LISTEN 4073/ *** bd
tcp6  :::22                   :::*            LISTEN 2761/sshd
udp   0.0.0.0:1900            0.0.0.0:*              3746/upnp_nas_devic
udp   0.0.0.0:24629           0.0.0.0:*              2076/mserver
udp   172.17.255.255:137      0.0.0.0:*              4077/nmbd
udp   172.17.42.1:137         0.0.0.0:*              4077/nmbd
udp   192.168.178.255:137     0.0.0.0:*              4077/nmbd
udp   192.168.178.31:137      0.0.0.0:*              4077/nmbd
udp   0.0.0.0:137             0.0.0.0:*              4077/nmbd
udp   172.17.255.255:138      0.0.0.0:*              4077/nmbd
udp   172.17.42.1:138         0.0.0.0:*              4077/nmbd
udp   192.168.178.255:138     0.0.0.0:*              4077/nmbd
udp   192.168.178.31:138      0.0.0.0:*              4077/nmbd
udp   0.0.0.0:138             0.0.0.0:*              4077/nmbd
udp   0.0.0.0:30958           0.0.0.0:*              3808/apkg
udp   0.0.0.0:514             0.0.0.0:*              1958/syslogd
udp   127.0.0.1:23457         0.0.0.0:*              3985/wdmcserver
udp   127.0.0.1:46058         0.0.0.0:*              3746/upnp_nas_devic
udp   0.0.0.0:48299           0.0.0.0:*              2481/avahi-daemon:
udp   0.0.0.0:5353            0.0.0.0:*              2481/avahi-daemon:

一样平常看到httpd就可以确定这可能是使用了apache来做的服务端,以是再搜一下conf设置文件,一样平常以我的习惯会把每个conf文件都读一下,不外这里我们主要关注一下alias.confrewrite.conf

sakura@sakuradeMacBook-Pro:~/Desktop/WDMyCloud_PR4100_GPL_v2.40.155_20200713$ find . -name "*.conf"
./firmware/ramdisk/root/etc/mdev.conf
./firmware/ramdisk/root/etc/ez-ipupdate.conf
./firmware/ramdisk/root/etc/alert_email.conf
./firmware/ramdisk/root/etc/ld.so.conf
./firmware/ramdisk/root/etc/avahi/avahi-daemon.conf
./firmware/ramdisk/root/etc/netatalk/extmap.conf
./firmware/ramdisk/root/etc/nsswitch.conf
./firmware/module/crfs/web/config/default_lighttpd.conf
./firmware/module/crfs/web/config/php-fpm.conf
./firmware/module/crfs/web/apache2_dav/conf/httpd.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-languages.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-dav.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-autoindex.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-manual.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-multilang-errordoc.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-vhosts.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-userdir.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-info.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-ssl.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-default.conf
./firmware/module/crfs/web/apache2_dav/conf/extra/httpd-mpm.conf
./firmware/module/crfs/web/apache2/certconf/wdnas-rest-api.conf
./firmware/module/crfs/web/apache2/certconf/wdnas-rest-api-trusted.conf
./firmware/module/crfs/web/apache2/conf/sites-enabled/restsdk.conf
./firmware/module/crfs/web/apache2/conf/sites-enabled/wdnas-ui.conf
./firmware/module/crfs/web/apache2/conf/httpd.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-languages.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-dav.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-autoindex.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-manual.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-multilang-errordoc.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-vhosts.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-userdir.conf
./firmware/module/crfs/web/apache2/conf/extra/available/httpd-info.conf
./firmware/module/crfs/web/apache2/conf/extra/ports.conf
./firmware/module/crfs/web/apache2/conf/extra/httpd-default.conf
./firmware/module/crfs/web/apache2/conf/extra/wdapp_web.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/mime.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/flvx.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/env.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/dav_fs.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/unixd.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/autoindex.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/mime_magic.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/log_config.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/dir.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/rewrite.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/alpha_custom.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/security2.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/actions.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/cgi.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/deflate.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/alias.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/mpm_prefork.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/negotiation.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/logio.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/setenvif.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/ssl.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/headers.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/php5.conf
./firmware/module/crfs/web/apache2/conf/mods-enabled/xsendfile.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/modsecurity.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-910-IP-REPUTATION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-901-INITIALIZATION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-950-DATA-LEAKAGES.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-921-PROTOCOL-ATTACK.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-913-SCANNER-DETECTION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-912-DOS-PROTECTION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/RESPONSE-980-CORRELATION.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
./firmware/module/crfs/web/apache2/conf/modsecurity/crs-setup.conf
./firmware/module/crfs/dbus-1/system.d/avahi-dbus.conf
./firmware/module/crfs/dbus-1/system.conf
./firmware/module/crfs/etc/ *** tp.conf
./firmware/module/crfs/etc/nas/wdnotifier.conf
./firmware/module/crfs/etc/nas/notify.d/wdmcserver.conf
./firmware/module/crfs/etc/nas/notify.d/wddispatcher.conf
./firmware/module/crfs/etc/apache2/sites-available/wdnas-rest-api.conf
./firmware/module/crfs/etc/apache2/sites-available/wdnas-ui.conf
./firmware/module/crfs/etc/apache2/sites-available/wdnas-rest-api-trusted.conf
./firmware/module/crfs/etc/apache2/conf.d/orionversion.conf
./firmware/module/crfs/etc/rsyslog.d/wdlog.conf
./firmware/module/crfs/etc/rsyslog.d/wddispatcher.conf
./firmware/module/crfs/default/syslog.conf
./firmware/module/crfs/default/mt-daapd.conf
./firmware/module/crfs/default/wdlog.conf
./firmware/module/crfs/default/dhcp6c.conf
./firmware/module/crfs/default/udhcpd.conf
./firmware/module/crfs/default/resolv.conf
./firmware/module/crfs/default/routeap.conf
./firmware/module/crfs/default/s3.conf
./firmware/module/crfs/default/snmpd.conf
./firmware/module/crfs/default/gogoc.conf
./firmware/module/crfs/apache2/sites-available/wdnas-rest-api.conf
./firmware/module/crfs/apache2/sites-available/wdnas-ui.conf
./firmware/module/crfs/apache2/conf.d/orionversion.conf
./firmware/module/crfs/files/ups/upsd.conf
./firmware/module/crfs/files/ups/upssched.conf
./firmware/module/crfs/files/ups/up *** on.conf
./firmware/module/crfs/files/ups/ups.conf
./firmware/module/crfs/files/syslog_rotate.conf
./firmware/module/crfs/files/mke2fs.conf
./firmware/module/crfs/files/syslog_dai
  • alias.conf
    https://www.docs4dev.com/docs/zh/apache/2.4/reference/mod-mod_alias.html

    ScriptAlias /cgi-bin/ /var/www/cgi-bin/

    这句设置的寄义是把web请求的url中,若是它接见的目录是/cgi-bin/,就重定向到/var/www/cgi-bin/目录下。

  • rewrite.conf
    https://www.jianshu.com/p/103742cccaff

对于rewrite.conf,主要读懂RewriteCond和RewriteRule两个关键字的寄义就行了。

RewriteCond起到的是过滤作用
RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1$这句为例,若是%{REMOTE_ADDR}!^127\.0\.0\.1$正则匹配,即REMOTE_ADDR不是来自localhost的话,就使用紧邻着的下一句RewriteRule来重定向web请求。
RewriteRule ^(\w*).cgi$ /web/cgi_api.php?cgi_name=$1&%{QUERY_STRING} [L]这句为例,就是把所有接见xx.cgi文件的请求,都重定向到/web/cgi_api.php?cgi_name=xxx,即用cgi_api.php来分发请求,若是鉴权不通过,就不能接见该cgi文件。

这里的鉴权主要指的就是攻击者是否有普通用户登录的权限,也就是一样平常说的pre-auth和after-auth了。

我们主要关注的都是pre-auth的rce,以是从这个设置文件和从cgi_api.php里的逻辑可以看出,认证前能够接见的cgi文件只有webpipe.cgilogin_mgr.cgi,而前者内部也有鉴权,以是主要关注login_mgr.cgi

至此为止我们就剖析出了攻击者易达的攻击面,若是要深挖的话还需要再读一下其他的设置文件,和ps -ef看看还开了哪些历程,能否通过httpd路由到。

<IfModule rewrite_module>
    RewriteEngine on
    RewriteCond expr "%{REQUEST_URI} != '/xml/english.xml'"
    RewriteCond expr "%{REQUEST_URI} != '/xml/lang.xml'"
    RewriteRule ^/xml/(.*) /cgi-bin/webpipe.cgi
    ,RewriteRule /api/[0-9.]+/rest/(.*)\?(.*)$ /htdocs/api/rest/index.php?$2
    ,RewriteRule /api/[0-9.]+/rest/(.*)  /htdocs/api/rest/index.php

    RewriteCond %{HTTP_HOST} ^(.*)\.(:\d+)?$
    RewriteRule ^(.*)$ http://%1%2$1 [L,R=301]

    <Directory "/var/www/cgi-bin/">
        RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1$
        RewriteCond $1 !^abFiles$
        RewriteRule ^(\w*).cgi$ /web/cgi_api.php?cgi_name=$1&%{QUERY_STRING} [L]
    </Directory>
</IfModule>

破绽剖析

首先抓包看一下正常的请求包是什么样的,可以看出用户输入的密码实在是被base64之后再发往server端处置的

POST /cgi-bin/login_mgr.cgi HTTP/1.1
...
Cookie: PHPSESSID=058d44781ddc0be98f15233c8853476f; local_login=1
cmd=wd_login&username=admin&pwd=YWRtaW4%3D&port=

入口函数在cgiMain,该函数凭据post请求里的cmd参数来选择使用哪个函数,这里我们主要看的就是wd_login函数

cgiMain

__int64 cgiMain()
{
  bool v0; // zf
  const char *v1; // rdi
  signed __int64 v2; // rcx
  char *v3; // rsi
  const char *v4; // rdi
  signed __int64 v5; // rcx
  char *v6; // rsi
  bool v7; // zf
  const char *v8; // rdi
  signed __int64 v9; // rcx
  char *v10; // rsi
  const char *v11; // rdi
  signed __int64 v12; // rcx
  char *v13; // rsi
  const char *v14; // rdi
  signed __int64 v15; // rcx
  char *v16; // rsi
  __int64 result; // rax
  char v18; // [rsp+0h] [rbp-28h]

  cgiFormString("cmd", &v18, 32LL);
  v0 = memcmp(&v18, "wd_login", 9uLL) == 0;
  if ( v0 )
  {
    wd_login();
    result = 0LL;
  }
  else
  {
    v1 = "ui_check_wto";
    v2 = 13LL;
    v3 = &v18;
    do
    {
      if ( !v2 )
        break;
      v0 = *v3++ == *v1++;
      --v2;

wd_login

在我简朴的处置了一下符号之后的伪代码如下。

int wd_login()
{
  char *pos_dbl_slash; // r14
  char *v1; // rsi
  char *v2; // rdx
  unsigned int login_successful; // er15
  FILE *v4; // rax
  FILE *v5; // r14
  int v6; // ecx
  unsigned int v7; // eax
  bool v8; // zf
  __int64 v9; // r14
  char *v10; // rsi
  FILE *v11; // rax
  FILE *v12; // r13
  __int64 v13; // r12
  __int64 v14; // rdx
  signed int v15; // er13
  unsigned int v16; // er12
  FILE *v17; // rax
  FILE *v18; // r12
  _BOOL4 v19; // ST10_4
  _BOOL4 v20; // ST08_4
  FILE *v21; // rbp
  _BOOL4 v22; // er8
  _BOOL4 v23; // er9
  struct passwd *v24; // rax
  signed __int64 v25; // rdx
  __int64 v26; // rdx
  FILE *v27; // rbp
  struct passwd *v28; // r14
  int v29; // er14
  FILE *v30; // r12
  FILE *v31; // rdi
  time_t v33; // [rsp+8h] [rbp-1200h]
  _BOOL4 v34; // [rsp+8h] [rbp-1200h]
  __int64 v35; // [rsp+10h] [rbp-11F8h]
  _BOOL4 v36; // [rsp+10h] [rbp-11F8h]
  __int64 v37; // [rsp+18h] [rbp-11F0h]
  __int64 v38; // [rsp+20h] [rbp-11E8h]
  __int64 v39; // [rsp+28h] [rbp-11E0h]
  char src[8]; // [rsp+30h] [rbp-11D8h]
  char dest[8]; // [rsp+40h] [rbp-11C8h]
  char username[8]; // [rsp+50h] [rbp-11B8h]
  __int64 v43; // [rsp+58h] [rbp-11B0h]
  __int64 v44; // [rsp+60h] [rbp-11A8h]
  __int64 v45; // [rsp+68h] [rbp-11A0h]
  __int64 v46; // [rsp+70h] [rbp-1198h]
  __int64 v47; // [rsp+78h] [rbp-1190h]
  __int64 v48; // [rsp+80h] [rbp-1188h]
  __int64 v49; // [rsp+88h] [rbp-1180h]
  char pwd_decoded[64]; // [rsp+90h] [rbp-1178h]
  char pwd_b64[256]; // [rsp+D0h] [rbp-1138h]
  char v52; // [rsp+1D0h] [rbp-1038h]
  int v53; // [rsp+260h] [rbp-FA8h]
  char v54; // [rsp+264h] [rbp-FA4h]
  char v55; // [rsp+3CFh] [rbp-E39h]
  char v56; // [rsp+3D0h] [rbp-E38h]
  char v57; // [rsp+5CFh] [rbp-C39h]
  char v58; // [rsp+5D0h] [rbp-C38h]
  char v59; // [rsp+7CFh] [rbp-A39h]
  char v60; // [rsp+7D0h] [rbp-A38h]
  char v61; // [rsp+9D0h] [rbp-838h]
  char v62; // [rsp+BD0h] [rbp-638h]
  char v63; // [rsp+DCFh] [rbp-439h]
  char s; // [rsp+DD0h] [rbp-438h]
  char v65; // [rsp+FCFh] [rbp-239h]
  char v66; // [rsp+FD0h] [rbp-238h]

  memset(pwd_b64, 0, sizeof(pwd_b64));
  memset(pwd_decoded, 0, sizeof(pwd_decoded));
  memset(&v52, 0, 0x200uLL);
  memset(&v56, 0, 0x200uLL);
  memset(&v58, 0, 0x200uLL);
  *(_QWORD *)username = 0LL;
  memset(&v60, 0, 0x200uLL);
  memset(&v61, 0, 0x200uLL);
  memset(&v62, 0, 0x200uLL);
  memset(&s, 0, 0x200uLL);
  memset(&v66, 0, 0x200uLL);
  v43 = 0LL;
  v44 = 0LL;
  v45 = 0LL;
  *(_QWORD *)src = 0LL;
  *(_QWORD *)dest = 0LL;
  v46 = 0LL;
  v47 = 0LL;
  v48 = 0LL;
  v49 = 0LL;
  v33 = time(0LL);
  cgiFormString("username", username, 32LL);
  cgiFormString("pwd", pwd_b64, 256LL);
  base64decode((u_char *)pwd_decoded, pwd_b64, 256);
  pos_dbl_slash = index(username, '\\');
  if ( !pos_dbl_slash )
  {
    if ( (unsigned int)is_username_allowed(username) )
    {
      login_successful = check_login(username, pwd_decoded);
      v15 = 0;
      v16 = 0;
    }
  • 首先读取用户输入的username到username数组里,更大读取32个字节,读取pwd到pwd_b64数组里,更大读取256个字节
  • base64decode解密pwd_b64,将效果保存在pwd_decoded数组里,更大写入256个字节,但问题是pwd_decoded数组的size是64字节,以是会越界写入到pwd_b64数组里,但在这里不会影响程序的逻辑,由于pwd_b64在解密后就不会被用到。
  • is_username_allowed校验输入的用户名是否正当,该函数先将用户名里的大写字母转成小写,然后和一个全局字符串数组里的每个字符串对照,若是有任何一个匹配就返回0,代表非法,否则返回1,代表正当。
    • 之以是这样对照是由于它将所有注册的用户的账号密码都写入到了/etc/shadow文件里,而这个文件里的root, anonymous...等用户是linux系统使用的,而不是给注册用户使用的。
  • 然后将被溢出的数组pwd_decoded传给check_login函数。

check_login

__int64 __fastcall check_login(const char *username, const char *pwd_decoded)
{
  FILE *v2; // rbp
  struct passwd *v3; // rax
  struct passwd *v4; // rbx
  const char *v6; // rax
  char password_copy_shadow[80]; // [rsp+0h] [rbp-C8h]
  char password_copy_input[88]; // [rsp+50h] [rbp-78h]

  v2 = fopen64("/etc/shadow", "r");
  while ( 1 )
  {
    v3 = fgetpwent(v2);
    v4 = v3;
    if ( !v3 )
      break;
    if ( !strcmp(v3->pw_name, username) )
    {
      strcpy(password_copy_shadow, v4->pw_passwd);
      fclose(v2);
      strcpy(password_copy_input, pwd_decoded);
  • 按行读取/etc/shadow里的数据,并剖析成passwd结构体。
  • 拷贝pw_passwd字段到栈上变量password_copy_shadow数组里
  • 拷贝pwd_decoded到栈上变量password_copy_input数组里,由于pwd_decoded是一个写入溢出的字符串,其长度更大是192字节(base64算法,更大解密出来就是输入字符串的3/4长度),而password_copy_input数组的size是88,以是在这个栈布局里就可以溢出到返回地址了。

如下是ida的stack layout视图,r代表返回地址,如图可以看到从password_copy_input数组到返回地址,一共是120个字节,而我们可以写入192个字节,以是可以挟制返回地址。

,

Usdt第三方支付接口

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

,
-00000000000000C8 ; D/A/*   : change type (data/ascii/array)
-00000000000000C8 ; N       : rename
-00000000000000C8 ; U       : undefine
-00000000000000C8 ; Use data definition commands to create local variables and function arguments.
-00000000000000C8 ; Two special fields " r" and " s" represent return address and saved registers.
-00000000000000C8 ; Frame size: C8; Saved regs: 0; Purge: 0
-00000000000000C8 ;
-00000000000000C8
-00000000000000C8 password_copy_shadow db 80 dup(?)
-0000000000000078 password_copy_input db 120 dup(?)
+0000000000000000  r              db 8 dup(?)
+0000000000000008
+0000000000000008 ; end of stack variables

破绽模式

这个破绽的模式就是写入的数据超出了数组自己的巨细导致的写入越界,但现实造成栈溢出的地方是在更后面的strcpy的地方,相对来说实在对照隐藏,strcpy这个函数会从源地址向目的地址拷贝数据,一直到遇到\0住手。

正常来说在往字符数组写入一个字符串的时刻,都会把最后一个字节设置\0,但由于写入的越界,导致\0出现在了数组越界后的位置。

最终导致前面base64decode函数造成的写入越界向后流传,最终在某次strcpy的时刻造成了栈溢出。

破绽行使

正常来说栈溢出的破绽行使只需要rop组织gadaget即可,然则对于64位架构的栈溢出来说,由于程序的装载基地址是0x400000,以是不思量return to libc等情形,直接在程序体内来找合适的gadaget地址的话,不可避免的在写入地址的时刻会遇到\x00,好比0000000000401D00这个地址,它的高位都是0。

以是在strcpy的时刻,遇到高位的\x00就会被截断,以是在溢出的时刻,最多就只能笼罩到返回地址,写入一个想到挟制到的地址,不能向后继续写入了。

如图可以看出,只管我们溢出password_copy_input由于截断只能写到返回地址谁人位置,举行一次gadaget。

然则我们可以寻找lea rsp, [rsp+??] ; retn这样的gadaget来抬升栈,通过stack pivot来将rsp指到wd_login栈上的pwd_decoded字符串里,而这个字符串的值显然是我们可以随便控制,而且不受\x00截断影响,它是base64解出来的。

以是到这里我们就可以举行多次gadaget了。

即我们要让pwd_decoded字符串里的内容形如,即可

AAAAA * ? + p64(gadaget_addr1) + 需要的pop的寄存器值 + p64(gadaget_addr2) + 需要的pop的寄存器值 + p64(gadaget_addr3)...

然后由于一样平常的cgi程序里实在都会调许多system函数,以是我们只要再通过多次gadaget通报我们需要的下令到挪用system函数的地方,最终执行该代码就可以反弹shell了。

但这个cgi程序里有个异常有趣的地方,就是00000000004039B7这个地址,它既有栈抬升,又有call system。

以是我们需要的payload就是A * 120 + p64(0x4039B7) + system_cmd_str即可。

解释一下,在溢出笼罩返回地址后,会跳到00000000004039B7去call一次无效的system下令,然后lea rsp, [rsp+108h]栈抬升,此时rsp指向我们在pwd_decoded里的p64(0x4039B7) + system_cmd_str字符串。

然后再retn,弹出p64返回地址,再次跳回到00000000004039B7执行,此时rsp指向的就是要执行的反弹shell字符串,并传给rdi,作为system的参数执行,此时就乐成的反弹shell了。

.text:00000000004039B7                 lea     rdi, [rsp]
.text:00000000004039BB                 call    _system
.text:00000000004039C0                 xor     eax, eax
.text:00000000004039C2                 lea     rsp, [rsp+108h]
.text:00000000004039CA                 retn

详细的调试就留给读者权做演习了。

总结一下,iot的栈溢出,找gadaget的要点就是

  • 栈抬升
    • lea rsp, [rsp+?]
  • 找system,传参挟制已往。

参考链接

  • https://www.crowdstrike.com/blog/pwn2own-tale-of-a-bug-found-and-lost-again/
usdt跑分网声明:该文看法仅代表作者自己,与本平台无关。转载请注明:choi baccarat:sakuraの从零开始のIoT破绽挖掘系列(一): Western Digital My Cloud Pro系列PR4100 NAS认证前RCE破绽剖析与行使
发布评论

分享到:

baccarat:乔治伤情若何?赛后亲自作出回应 情形与想象中不一样!
2 条回复
  1. Allbet代理
    Allbet代理
    (2021-02-25 00:04:08) 1#

    葱花花卷的做法:还好,改进一点

  2. 卡利代理
    卡利代理
    (2021-04-17 00:08:57) 2#

    有甜有苦,很真

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。