The McAfee Labs Advanced Threat Research team is committed to uncovering security issues in both software and hardware to help developers provide safer products for businesses and consumers. We recently investigated software installed on computers used in K-12 school districts. The focus of this blog is on Netop Vision Pro produced by Netop. Our research into this software led to the discovery of four previously unreported critical issues, identified by CVE-2021-27192, CVE-2021-27193, CVE-2021-27194 and CVE-2021-27195. These findings allow for elevation of privileges and ultimately remote code execution, which could be used by a malicious attacker, within the same network, to gain full control over students’ computers. We reported this research to Netop on December 11, 2020 and we were thrilled that Netop was able to deliver an updated version in February of 2021, effectively patching many of the critical vulnerabilities.
Netop Vision Pro is a student monitoring system for teachers to facilitate student learning while using school computers. Netop Vision Pro allows teachers to perform tasks remotely on the students’ computers, such as locking their computers, blocking web access, remotely controlling their desktops, running applications, and sharing documents. Netop Vision Pro is mainly used to manage a classroom or a computer lab in a K-12 environment and is not primarily targeted for eLearning or personal devices. In other words, the Netop Vision Pro Software should never be accessible from the internet in the standard configuration. However, as a result of these abnormal times, computers are being loaned to students to continue distance learning, resulting in schooling software being connected to a wide array of networks increasing the attack surface.
Netop provides all software as a free trial on its website, which makes it easy for anyone to download and analyze it. Within a few minutes of downloading the software, we were able to have it configured and running without any complications.
We began by setting up the Netop software in a normal configuration and environment. We placed four virtual machines on a local network; three were set up as students and one was set up as a teacher. The three student machines were configured with non-administrator accounts in our attempt to emulate a normal installation. The teacher first creates a “classroom” which then can choose which student PCs should connect. The teacher has full control and gets to choose which “classroom” the student connects to without the student’s input. Once a classroom has been setup, the teacher can start a class which kicks off the session by pinging each student to connect to the classroom. The students have no input if they want to connect or not as it is enforced by the teacher. Once the students have connected to the classroom the teacher can perform a handful of actions to the entire class or individual students.
During this setup we also took note of the permission levels of each component. The student installation needs to be tamperproof and persistent to prevent students from disabling the service. This is achieved by installing the Netop agent as a system service that is automatically started at boot. The teacher install executes as a normal user and does not start at boot. This difference in execution context and start up behavior led us to target the student installs, as an attacker would have a higher chance of gaining elevated system permissions if it was compromised. Additionally, the ratio of students to teachers in a normal school environment would ensure any vulnerabilities found on the student machines would be wider spread.
With the initial install complete, we took a network capture on the local network and took note of the traffic between the teacher and student. An overview of the first few network packets can been seen in Figure 1 below and how the teacher, student transaction begins.
Figure 1: Captured network traffic between teacher and student
Our first observation, now classified as CVE-2021-27194, was that all network traffic was unencrypted with no option to turn encryption on during configuration. We noticed that even information normally considered sensitive, such as Windows credentials (Figure 2) and screenshots (Figure 4), were all sent in plaintext. Windows credentials were observed on the network when a teacher would issue a “Log on” command to the student. This could be used by the teacher or admin to install software or simply help a student log in.
Figure 2: Windows credentials passed in plaintext
Additionally, we observed interesting default behavior where a student connecting to a classroom immediately began to send screen captures to the classroom’s teacher. This allows the teacher to monitor all the students in real time, as shown in Figure 3.
Figure 3: Teacher viewing all student machines via screenshots
Since there is no encryption, these images were sent in the clear. Anyone on the local network could eavesdrop on these images and view the contents of the students’ screens remotely. A new screenshot was sent every few seconds, providing the teacher and any eavesdroppers a near-real time stream of each student’s computer. To capture and view these images, all we had to do was set our network card to promiscuous mode (https://www.computertechreviews.com/definition/promiscuous-mode/) and use a tool like Driftnet (https://github.com/deiv/driftnet). These two steps allowed us to capture the images passed over the network and view every student screen while they were connected to a classroom. The image in Figure 4 is showing a screenshot captured from Driftnet. This led us to file our first vulnerability disclosed as CVE-2021-27194, referencing “CWE-319: Cleartext Transmission of Sensitive Information” for this finding. As pointed out earlier, the teacher and the student clients will communicate directly over the local network. The only way an eavesdropper could access the unencrypted data would be by sniffing the traffic on the same local network as the students.
Figure 4: Image of student’s desktop captured from Driftnet over the network
Fuzzing the Broadcast Messages
With the goal of remote code execution on the students’ computers, we began to dissect the first network packet, which the teacher sends to the students, telling them to connect to the classroom. This was a UDP message sent from the teacher to all the students and can be seen in Figure 5.
Figure 5: Wireshark capture of teacher’s UDP message
The purpose of this packet is to let the student client software know where to find the teacher computer on the network. Because this UDP message is sent to all students in a broadcast style and requires no handshake or setup like TCP, this was a good place to start poking at.
We created a custom Scapy layer (https://scapy.readthedocs.io/en/latest/api/scapy.layers.html) (Figure 6) from the UDP message seen in Figure 5 to begin dissecting each field and crafting our own packets. After a few days of fuzzing with UDP packets, we were able to identify two things. First, we observed a lack of length checks on strings and second, random values sent by the fuzzer were being written directly to the Windows registry. The effect of these tests can easily be seen in Figure 7.
Figure 6: UDP broadcast message from teacher
Even with these malformed entries in the registry (Figure 7) we never observed the application crashing or responding unexpectedly. This means that even though the application wasn’t handling our mutated packet properly, we never overwrote anything of importance or crossed a string buffer boundary.
Figure 7: Un-sanitized characters being written to the Registry
To go further we needed to send the next few packets that we observed from our network capture (Figure 8). After the first UDP message, all subsequent packets were TCP. The TCP messages would negotiate a connection between the student and the teacher and would keep the socket open for the duration of the classroom connection. This TCP negotiation exchange was a transfer of 11 packets, which we will call the handshake.
Figure 8: Wireshark capture of a teacher starting class
Reversing the Network Protocol
To respond appropriately to the TCP connection request, we needed to emulate how a valid teacher would respond to the handshake; otherwise, the student would drop the connection. We began reverse engineering the TCP network traffic and attempted to emulate actual “teacher” traffic. After capturing a handful of packets, the payloads started to conform to roughly the same format. Each started with the size of the packet and the string “T125”. There were three packets in the handshake that contained fields that were changing between each classroom connection. In total, four changing fields were identified.
The first field was the session_id, which we identified in IDA and is shown in the UDP packet from Figure 6. From our fuzzing exercise with the UDP packet, we learned if the same session_id was reused multiple times, the student would still respond normally, even though the actual network traffic we captured would often have a unique session_id.
This left us three remaining dynamic fields which we identified as a teacher token, student token, and a unique unknown DWORD (8 bytes). We identified two of these fields by setting up multiple classrooms with different teacher and student computers and monitoring these values. The teacher token was static and unique to each teacher. We discovered the same was true with the student token. This left us with the unique DWORD field that was dynamic in each handshake. This last field at first seemed random but was always in the same relative range. We labeled this as “Token3” for much of our research, as seen in Figure 9 below.
Figure 9: Python script output identifying “Token3”
Eventually, while using WinDbg to perform dynamic analysis, the value of Token3 started to look familiar. We noticed it matched the range of memory being allocated for the heap. This can be seen in Figure 10.
Figure 10: WinDbg address space analysis from a student PC
By combining our previous understanding of the UDP broadcast traffic with our ability to respond appropriately to the TCP packets with dynamic fields, we were able to successfully emulate a teacher’s workstation. We demonstrated this by modifying our Python script with this new information and sending a request to connect with the student. When a student connects to a teacher it displays a message indicating a successful connection has been made. Below are two images showing a teacher connecting (Figure 11) and our Python script connecting (Figure 12). Purely for demonstration purposes, we have named our attack machine “hacker”, and our classroom “hacker-room.”
Figure 11: Emulation of a teacher successful
Figure 12: Emulated teacher connection from Python script
To understand the process of reverse engineering the network traffic in more detail, McAfee researchers Douglas McKee and Ismael Valenzuela have released an in-depth talk on how to hack proprietary protocols like the one used by Netop. Their webinar goes into far more detail than this blog and can be viewed here.
Replaying a Command Action
Since we have successfully emulated a teacher’s connection using Python, for clarity we will refer to ourselves as the attacker and a legitimate connection made through Netop as the teacher.
Next, we began to look at some of the actions that teachers can perform and how we could take advantage of them. One of the actions that a teacher can perform is starting applications on the remote students’ PCs. In the teacher suite, the teacher is prompted with the familiar Windows Run prompt, and any applications or commands set to run are executed on the student machines (Figure 13).
Figure 13: The teacher “Run Application” prompt
Looking at the network traffic (shown in Figure 14), we were hoping to find a field in the packet that could allow us to deviate from what was possible using the teacher client. As we mentioned earlier, everything is in plaintext, making it quite easy to identify which packets were being sent to execute applications on the remote systems by searching within Wireshark.
Figure 14: Run “calc” packet
Before we started to modify the packet that runs applications on the student machines, we first wanted to see if we could replay this traffic successfully. As you can see in the video below, our Python script was able to run PowerShell followed by Windows Calculator on each of the student endpoints. This is showcasing that even valid teacher actions can still be useful to attackers.
The ability for an attacker to emulate a teacher and execute arbitrary commands on the students’ machines brings us to our second CVE. CVE-2021-27195 was filed for “CWE-863: Incorrect Authorization” since we were able to replay modified local network traffic.
When the teacher sends a command to the student, the client would drop privileges to that of the logged-in student and not keep the original System privileges. This meant that if an attacker wanted unrestricted access to the remote system, they could not simply replay normal traffic, but instead would have to modify each field in the traffic and observe the results.
In an attempt to find a way around the privilege reduction during command execution, we continued fuzzing all fields located within the “run command” packet. This proved unsuccessful as we were unable to find a packet structure that would prevent the command from lowering privileges. This required a deeper dive into the code in handling the remote command execution processed on the student endpoint. By tracing the execution path within IDA, we discovered there was in fact a path that allows remote commands to execute without dropping privileges, but it required a special case, as shown in Figure 15.
Figure 15: IDA graph view showing alternate paths of code execution
Figure 16: Zoomed in image of the ShellExecute code path
The code path that bypasses the privilege reduction and goes directly to “ShellExecute” was checking a variable that had its value set during startup. We were not able to find any other code paths that updated this value after the software started. Our theory is this value may be used during installation or uninstallation, but we were not able to legitimately force execution to the “ShellExecute” path.
This code path to “ShellExecute” made us wonder if there were other similar branches like this that could be reached. We began searching the disassembled code in IDA for calls not wrapped with code resulting in lower privileges. We found four cases where the privileges were not reduced, however none of them were accessible over the network. Regardless, they still could potentially be useful, so we investigated each. The first one was used when opening Internet Explorer (IE) with a prefilled URL. This turned out to be related to the support system. Examining the user interface on the student machine, we discovered a “Technical Support” button which was found in the Netop “about” menu.
When the user clicks on the support button, it opens IE directly into a support web form. The issue, however, is privileges are never dropped, resulting in the IE process being run as System because the Netop student client is also run as System. This can be seen in Figure 11. We filed this issue as our third CVE, CVE-2021-27192 referencing “CWE-269: Incorrect Privilege Assignment”.
Figure 17: Internet Explorer running as System
There are a handful of well-documented ways to get a local elevation of privilege (LPE) using only the mouse when the user has access to an application running with higher privileges. We used an old technique which uses the “Save as” button to navigate to the folder where cmd.exe is located and execute it. The resulting CMD process inherits the System privileges of the parent process, giving the user a System-level shell.
While this LPE was exciting, we still wanted to find something with a remote attack vector and utilize our Python script to emulate teacher traffic. We decided to take a deeper dive into the network traffic to see what we could find. Simulating an attacker, we successfully emulated the following:
- Remote CMD execution
- Screen blank the student
- Restart Netop
- Shutdown the computer
- Block web access to individual websites
- Unlock the Netop properties (on student computer)
During the emulation of all the above actions we performed some rudimentary fuzzing on various fields of each and discovered six crashes which caused the Netop student install to crash and restart. We were able to find two execution violations, two read violations, one write exception, and one kernel exception. After investigation, we determined these crashes were not easily exploitable and therefore a lower priority for deeper investigation. Regardless, we reported them to Netop along with all other findings.
Netop Vision Pro comes with a handful of plugins installed by default, which are used to separate different functionality from the main Netop executable. For example, to enable the ability for the teacher and student to instant message (IM) each other, the MChat.exe plugin is used. With a similar paradigm to the main executable, the students should not be able to stop these plugins, so they too run as System, making them worth exploring.
Mimicking our previous approach, we started to look for “ShellExecute” calls within the plugins and eventually discovered three more privilege escalations, each of which were conducted in a comparable way using only the mouse and bypassing restrictive file filters within the “Save as” windows. The MChat.exe, SSView.exe (Screen Shot Viewer), and the About page’s “System Information” windows all had a similar “Save as” button, each resulting in simple LPEs with no code or exploit required. We added each of these plugins under the affected versions field on our third CVE, CVE-2021-27192, mentioned above.
We were still searching for a method to achieve remote code execution and none of the “ShellExecute” calls used for the LPEs were accessible over the network. We started to narrow down the plugins that pass user supplied data over the network. This directed our attention back to the MChat plugin. As part of our initial recon for research projects, we reviewed change logs looking for any relevant security changes. During this review we noted an interesting log pertaining to the MChat client as seen in Figure 13.
Figure 18: Change log from Netop.com
The Chat function runs as System, like all the plugins, and can send text or files to the remote student computer. An attacker can always use this functionality to their advantage by either overwriting existing files or enticing a victim to click on a dropped executable. Investigating how the chat function works and specifically how files are sent, we discovered that the files are pushed to the student computers without any user interaction from the student. Any files pushed by a teacher are stored in a “work directory”, which the student can open from the IM window. Prior to the latest release it would have been opened as System; this was fixed as referenced in Figure 18. Delving deeper into the functionality of the chat application, we found that the teacher also has the ability to read files in the student’s “work directory” and delete files within it. Due to our findings demonstrated with CVE-2021-27195, we can leverage our emulation code as an attacker to write, read, and delete files within this “work directory” from a remote attack vector on the same local network. This ability to read and write files accounted for the last CVE that we filed, CVE-2021-27193 referencing “CWE-276: Incorrect Default Permissions,” with the overall highest CVSS score of 9.5.
In order to determine if the MChat plugin would potentially give us System-level access, we needed to investigate if the plugin’s file operations were restricted to the student’s permissions or if the plugin inherited the System privileges from the running context. Examining the disassembled code of the MChat plugin, as displayed in Figure 14, we learned that all file actions on the student computer are executed with System privileges. Only after the file operation finishes will the permissions be set to allow access for everyone, essentially the effect of using the Linux “chmod 777” command, to make the files universally read/writable.
Figure 19: IDA screenshot of MChat file operations changing access to everyone
To validate this, we created several test files using an admin account and restricted the permissions to disallow the student from modifying or reading the test files. We proceeded to load the teacher suite, and through an MChat session confirmed we were able to read, write, and delete these files. This was an exciting discovery; however, if the attacker is limited to the predetermined “work directory” they would be limited in the effect they could have on the remote target. To investigate if we could change the “work directory” we began digging around in the teacher suite. Hidden in a few layers of menus (Figure 20) we found that a teacher can indeed set the remote student’s “work directory” and update this remotely. Knowing we can easily emulate any teacher’s command means that we could modify the “work directory” anywhere on the student system. Based on this, an attacker leveraging this flaw could have System access to modify any file on the remote PC.
Figure 20: Changing the remote student path from a teacher’s client
Reversing MChat Network Traffic
Now that we knew that the teacher could overwrite any file on the system, including system executables, we wanted to automate this attack and add it to our Python script. By automating this we want to showcase how attackers can use issues like this to create tools and scripts that have real world impacts. For a chat session to begin, we had to initiate the 11-packet handshake we previously discussed. Once the student connected to our attack machine, we needed to send a request to start a chat session with the target student. This request would make the student respond using TCP, yet this time, on a separate port, initiating an MChat seven-packet handshake. This required us to reverse engineer this new handshake format in a similar approach as described earlier. Unlike the first handshake, the MChat handshake had a single unique identifier for each session, and after testing, it was determined that the ID could be hardcoded with a static value without any negative effects.
Finally, we wanted to overwrite a file that we could ensure would be executed with System privileges. With the successful MChat handshake complete we needed to send a packet that would change the “work directory” to that of our choosing. Figure 21 shows the packet as a Scapy layer used to change the work directory on the student’s PC. The Netop plugin directory was a perfect target directory to change to since anything executed from this directory would be executed as System.
Figure 21: Change working directory on the student PC
The last step in gaining System-level execution was to overwrite and execute one of the plugins with a “malicious” binary. Through testing we discovered that if the file already exists in the same directory, the chat application is smart enough to not overwrite it, but instead adds a number to the filename. This is not what we wanted since the original plugin would get executed instead of our “malicious” one. This meant that we had to also reverse engineer a packet containing commands that are used to delete files. The Scapy layer used to delete a file and save a new one is shown in Figure 22.
Figure 22: Python Scapy layers to “delete” (MChatPktDeleteFile) and “write” (MChatPkt6) files
With these Scapy layers we were able to replace the target plugin with a binary of our choosing, keeping the same name as the original plugin. We chose the “SSView.exe” plugin, which is a plugin used to show screenshots on the student’s computer. To help visualize this entire process please reference Figure 23.
Figure 23: An attack flow using the MChat plugin to overwrite an executable
Now that the SSView.exe plugin has been overwritten, triggering this plugin will execute our attacker-supplied code. This execution will inherit the Netop System privileges, and all can be conducted from an unauthenticated remote attack vector.
It is not hard to imagine a scenario where a culmination of these issues can lead to several negative outcomes. The largest impact being remote code execution of arbitrary code with System privileges from any device on the local network. This scenario has the potential to be wormable, meaning that the arbitrary binary that we run could be designed to seek out other devices and further the spread. In addition, if the “Open Enrollment” option for a classroom is configured, the Netop Vision Pro student client broadcasts its presence on the network every few seconds. This can be used to an attacker’s advantage to determine the IP addresses of all the students connected on the local network. As seen in Figure 24, our Python script sniffed for student broadcast messages for 5 seconds and found all three student computers on the same network. Because these broadcast messages are sent out to the entire local network, this could very well scale to an entire school system.
Figure 24: Finding all students on the local network.
With a list of computers running the student software, an attacker can then issue commands to each one individually to run arbitrary code with System privileges. In the context of hybrid and e-learning it is important to remember that this software on the student’s computer doesn’t get turned off. Because it is always running, even when not in use, this software assumes every network the device connects to could have a teacher on it and begins broadcasting its presence. An attacker doesn’t have to compromise the school network; all they need is to find any network where this software is accessible, such as a library, coffee shop, or home network. It doesn’t matter where one of these student’s PCs gets compromised as a well-designed malware could lay dormant and scan each network the infected PC connects to, until it finds other vulnerable instances of Netop Vision Pro to further propagate the infection.
Once these machines have been compromised the remote attacker has full control of the system since they inherit the System privileges. Nothing at this point could stop an attacker running as System from accessing any files, terminating any process, or reaping havoc on the compromised machine. To elaborate on the effects of these issues we can propose a few scenarios. An attacker could use the discoverability of these machines to deploy ransomware to all the school computers on the network, bringing the school or entire school district to a standstill. A stealthier attacker could silently install keylogging software and monitor screenshots of the students which could lead to social media or financial accounts being compromised. Lastly, an attacker could monitor webcams of the students, bridging the gap from compromised software to the physical realm. As a proof of concept, the video below will show how an attacker can put CVE-2021-27195 and CVE-2021-27193 together to find, exploit, and monitor the webcams of each computer running Netop Vision Pro.
Secure adaptation of software is much easier to achieve when security is baked in from the beginning, rather than an afterthought. It is easy to recognize when software is built for “safe” environments. While Netop Vision Pro was never intended to be internet-facing or be brought off a managed school network, it is still important to implement basic security features like encryption. While designing software one should not assume what will be commonplace in the future. For instance, when this software was originally developed the concept of remote learning or hybrid learning was a far-out idea but now seems like it will be a norm. When security decisions are integrated from inception, software can adapt to new environments while keeping users better protected from future threats.
Disclosure and Recommended Mitigations
We disclosed all these findings to Netop on December 11, 2020 and heard back from them shortly after. Our disclosure included recommendations for implementing encryption of all network traffic, adding authentication, and verification of teachers to students, and more precise packet parsing filters. In Netop Vision Pro 9.7.2, released in late February, Netop has fixed the local privilege escalations, encrypted formerly plaintext Windows credentials, and mitigated the arbitrary read/writes on the remote filesystem within the MChat client. The local privilege escalations were fixed by running all plugins as the student and no longer as System. This way, the “Save as” buttons are limited to the student’s account. The Windows credentials are now encrypted using RC4 before being sent over the network, preventing eavesdroppers from gathering account credentials. Lastly, since all the plugins are running as the student, the MChat client can no longer delete and replace system executables which successfully mitigates the attack shown in the impact section. The network traffic is still unencrypted, including the screenshots of the student computers but Netop has assured us it is working on implementing encryption on all network traffic for a future update. We’d like to recognize Netop’s outstanding response and rapid development and release of a more secure software version and encourage industry vendors to take note of this as a standard for responding to responsible disclosures from industry researchers.