Categories
Security Research

Virus harvesting Czech eID card identities

This research was conducted in cooperation with WardenSec.

This research was presented at QuBit Prague 2020. Video of the talk is available on YouTube.

Popis zranitelnosti v češtině je k dispozici zde.

Introduction

Czech government started issuing new electronical identity cards (further referred to by its Czech name eObčanka) back in July 2018. Those shall provide secure online authentication towards government ICT systems including social security account, online medical prescriptions, land registry, tax returns and more. Assuming eObčanka is well received by public, this Single sign-on (SSO) system could be expected to facilitate further use-cases in the future, possibly also including online voting. Due to the fact that successful theft of those identities might have wide-ranging consequences it is necessary to properly secure them.

eObčanka is implementation of proprietary government PKI system. Authentication key pair is generated and distributed with each eObčanka card and cannot be easily extracted. Usage of private key is protected by PIN known only to the card holder. At first glance this architecture seems to provide adequate security for given use-case.

Nevertheless, we have identified serious design flaw in the authentication workflow which allowed those identities to be stolen at bulk in simple malware campaign. Potential remote attacker could steal those guaranteed citizen identities without victim’s awareness. Our attack assumes that victim’s computer is infected with simple malware. Not citizen nor authentication backend was able to detect such identity theft at the time of our responsible disclosure to National Cyber and Information Security Agency.

Given the information security awareness of an average citizen, we argue that security of the system cannot rely on premise that citizens are not trying to authenticate from devices which are infected with malware or otherwise doctored. Czech eObčanka system was therefore facing serious risk of being targeted by malware campaign. Motivation for such campaign could be twofold – foreign geopolitical power trying to affect potential future online elections or cybercriminals filling in fake tax returns to steal tax refunds.

Throughout this article we would like to introduce you to the eObčanka system, explain how the authentication procedure could be broken and demonstrate proof-of-concept virus covertly stealing guaranteed online identities of fully unaware citizens, demonstrating this attack is not only theoretical, but practical indeed. Lastly, we discuss why it was close to impossible to identify the attack on users side and also why it was not being detected on backend side.

Usual authentication workflow

This section describes standard eObčanka authentication workflow against ePortal of Czech Social Security Administration (it is important to note that this detail is not relevant – security flaw lies in SSO functionality – once SSO identity is stolen, attacker can login to all government systems available under this SSO). Authentication workflow is also severely simplified and we only describe details necessary to understand our attack. The following steps are taken in order to login (see also figure 1 with detailed login diagram):

  1. Citizen navigates to the ePortal of Czech Social Security Administration website: https://eportal.cssz.cz and selects authentication using National Identity Authority (NIA)
  2. Citizen is redirected to SSO portal of NIA (frontend) https://eop.eidentita.cz and selects authentication using eObčanka
  3. NIA frontend initiates the authentication session by generating transaction identifier (mwId) in the uniqueidentifier format and asks user’s browser to open the following URL: czeeopauth://mwid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where Xs represent given uniqueidentifier.
  4. Triggering URL from step 3 leads to independent application eObčanka Identifikace being opened on user’s computer with mwId being its second parameter (argv[1] for those familiar with C development).
  5. Program eObčanka Identifikace securely authenticates citizen against NIA backend (https://mweop.eidentita.cz). During this process, citizen needs to enter PIN code by which private authentication key is protected inside eObčanka. Upon successful completion, citizen’s identity is bound to given transaction ID (mwId).
  6. All infrastructure components – NIA backend, NIA frontend and ePortal of Czech Social Security Administration – are communicating together. Therefore, ePortal now knows the citizen’s identity which is proven by ownership of eObčanka and knowledge of PIN. Citizen is therefore successfully logged in (this part is significantly simplified).
Figure 1: Schema of standard login procedure

Theory behind our attack

Chain is unfortunately only as strong as it weakest link. In case of the login procedure described in the previous section it is step 4 in which browser initiates desktop application eObčanka Identifikace from the browser and passes mwId as application parameter. Computer of average citizen might be infected with malware, which might change the authentication workflow to the following:

  1. Citizen navigates to the ePortal of Czech Social Security Administration website: https://eportal.cssz.cz and selects authentication using National Identity Authority (NIA)
  2. Citizen is redirected to SSO portal of NIA (frontend) https://eop.eidentita.cz and selects authentication using eObčanka
  3. NIA frontend initiates the authentication session by generating transaction identifier (mwId) in the uniqueidentifier format and asks user’s browser to open the following URL: czeeopauth://mwid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where Xs represent given uniqueidentifier.
  4. Triggering URL from step 3 leads to independent application eObčanka Identifikace being opened on user’s computer with mwId being its first parameter (argv[1] for those familiar with C development). At this point, however, malware intercepts this call.
  5. Malware which intercepted this call immediately connects to the attacker’s backend (command & control server).
  6. Attacker’s backend requests its own login transaction identifier (mwId) in the following format: czeeopauth://mwid=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY. Note that this mwId is unrelated to the original mwId requested by user.
  7. Malware swaps the transaction id of the user czeeopauth://mwid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX for the transaction id of the attacker czeeopauth://mwid=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY in the program memory of eObčanka Identifikace.
  8. Program eObčanka Identifikace securely authenticates user against NIA backend (https://mweop.eidentita.cz), but this time using transaction ID of the attacker. Upon successful completion of this process, citizens identity is bound to attackers transaction ID YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY instead of user’s transaction ID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX!
  9. At this point, attacker successfully completed identity theft and fully controls user’s government guaranteed identity. As NIA is SSO portal, attacker is able to login to all systems connected to it (including ePortal of Czech Social Security Administration) and act in the name of the user.
  10. Legitimate user’s login attempt times out with inconclusive error. User has no chance to find out his identity was just stolen.
Figure 2: Schema of theoretical attack against standard login procedure

Practical implementation

Attack might seem complex to implement, but it is in fact surprisingly trivial to implement and carry out. Program eObčanka Identifikace does not rely on system openssl library and it is instead installed with its own openssl version.

Figure 3: Bash script initiating eObčanka Identifikace with its own openssl library

Let us assume that some citizens use compromised computers with malware (virus) which infected this openssl library. Library can be easily modified so that upon its initialization it executes steps 5-7 of the theoretical attack described in the previous section.

Openssl must be initialized when program starts and prior any communication between eObčanka Identifikace application and NIA backend can be done. We can therefore modify openssl initialization call to trigger our virus as follows.

Figure 4: Malware planted in openssl library SSL_new() function

Actual attack is then carried out within spoof_MWID() function as follows.

Figure 5: spoof_MWID() function which swaps transaction IDs

Malicious function simply calculates position of argv array (arguments with which program was started) on the program stack (this value is constant across different program executions) and replaces argument holding legitimate mwId with attacker’s mwId.

We have successfully tested proof-of-concept of this attack on Linux version of eObčanka Identifikace. There is no indication that similar attack would not be possible on other OS versions including Windows and Mac. Following shows video of working proof-of-concept attack.

What is the potential impact?

In case of successful identity theft, eObčanka Identifikace program and NIA frontend leaves user no chance to recognize that anything malicious happened. The only difference between successful login attempt and the one that has been stolen is the login attempt timeout with generic error message. It is fair to assume that no user would find that suspicious, instead they would try to login again.

In theory NIA backend shall be able to partially detect and prevent this attack, but to our surprise it did not detect it even in the most obvious forms. Even the most naive implementation of this attack – with login attempts starting from browser at IP address 1 and certain geolocation and completing from eObčanka Identifikace program at IP address 2 and totally different geolocation succeeded.

We believe this security flaw constitutes significant security risk for the whole system of eObčanka. We do not believe that someone would be motivated to misuse it in order to steal single identity. There is, however, significant risk that someone might be motivated to mount malware campaign against Czech users trying to steal those identities en mass. Motivation to orchestrate such attack would only grow with eObčanka growing adoption rates. Ideal motivation for such attack might be attempts of foreign geopolitical force to influence future online elections at Czech Republic or simple motivation of cybercriminals to steal tax returns submitted online using eObčanka.

Responsible disclosure

We have initially identified this issue in the first half of 2019. We have reported it to responsible people, but we were not properly informed on the countermeasures . Therefore, we presented the issue at QuBIT conference in Prague 2020 and released this article to public scrutiny.

Responsible disclosure timeline:

  • 19th&20th January 2019: Hackathon eObčanka in Paralelní Polis
  • 14th August 2019: Issue reported to NÚKIB (National Cyber and Information Security Agency of Czech Republic)
  • August – November 2019: No progress despite several reminders and status inquiries. NÚKIB stopped communicating with us.
  • Spring 2020: We noticed first visible countermeasure. mwId is now displayed in eObčanka Identifikace as well as on the web, so user can at least manually compare them.
  • 27th August 2020: Shared presentation slides from our upcoming talk at QuBIT conference with NÚKIB. We received no response nor comment.
  • September 2020: Public disclosure at QuBIT conference in Prague 2020. It is more than 1 year since we initially reported the issue. We are not aware of any other countermeasures taken.
Figure 6: The only countermeasure that was (to the best of our knowledge) implemented

Categories
Automotive Security Testing

How to carry out a successful penetration test?

Penetration testing became de-facto standardized service that companies either use or plan to use as integral component of security operations. However, many companies still struggle with the same challenges. What shall we test? How to adequately scope the penetration testing project? How to utilize penetration testing in order to measurably improve security in long run? How to set reasonable budget? Is it really going to improve our security posture or is it going to be just another checkbox ticked?

Our company has been active in penetration testing and security auditing since 2015 and we would like to answer some of those fundamental questions in this article. We will especially focus on the following:

  1. Penetration test objectives
  2. Setting the right scope / budget
  3. Finding the right resources
  4. Optimal timing for penetration test
  5. Outcome of the penetration test

We hope this information provides you with requisite confidence to successfully embed penetration testing into your operations. If after reading this article you still have questions how to properly carry out penetration test in your specific case, please feel free to reach out to us via our contact details and one of our consultants would be happy to discuss it with you.

Penetration test objectives

There are several types of penetration tests that a company might need, depending on what you are trying to achieve. For that reason there are several objectives that have to be analyzed and discussed in order to find the right one for you:

  1. Infrastructure penetration test – Are you ICT manager responsible for company infrastructure? Then you shall be interested in conducting penetration test examining whether your entire ICT infrastructure is resilient against malicious actors. Depending on assets you manage, you might be interested in an internal, external infrastructure penetration tests or combination of both.
    • External penetration test tests resilience of your publicly exposed infrastructure (web, mail, VPN server etc) against omnipresent malicious actors on the Internet. Ultimate goal of the test is to evaluate whether it is possible to gain unauthorized access from the Internet into your internal network.
    • Internal penetration test tests resilience of assets which are only hosted internally (ERP system, internal file servers, versioning servers etc). Objective of such test is to see whether unprivileged local user would be able to access or modify systems which shall not be accessible to him, i.e. disgruntled employee or external contractor gaining access to your accounting, intellectual property etc.
    • Combination of both. Our usual customers typically have both external as well as internal infrastructure. In that case, it is advisable to do both starting with external penetration test following internal one. Using this approach allows to first verify if external attacker can get foothold in the company via your public IPs, which is then followed by internal test verifying how far such attacker would get internally. If there is strict budget limitation, either of them shall be selected based on your risk profile or testing shall be distributed across multiple budgeting periods.
  2. Product penetration test – Are you product manager or development lead? In this case you would be rather interested in how would your product withstand malicious attacks. No matter if you are responsible for web application, desktop application or hardware appliance – product penetration test done early in the development life cycle will assist your development team in building inherently more robust and secure system.
    • Web application / API test. Your web application is assessed against complete OWASP Top 10 (API against OWASP API Security Top 10). De-facto, industry best practice web application security standard.
    • Desktop / mobile application test. Penetration test evaluating your application against the most common application security issues – depending on the platform (Windows/UNIX/mobile). It demonstrates how such issues can be misused and also avoided in the future.
    • Hardware appliance test. Are you developing your own hardware together with software? We have extensive experiences testing Linux, Android and custom-based automotive ECUs, aerospace units as well as custom military ICT equipment. Situation with custom appliances is very specific case which in itself would allow for several stand-alone article. If you are considering such test please reach out to us. We will assess your situation on case-by-case basis and provide necessary advise.

Automated vulnerability scan vs manual penetration test

Nowadays, there are many great automated vulnerability scanning solutions on the market. Those include among others Tenable, Rapid7, Qualys. Both automated vulnerability scanners and manual penetration tests are there to uncover vulnerabilities. Both have, however, very different use-cases. Automated vulnerability scans are great to periodically uncover the most obvious security issues on large ever-changing infrastructures (default credentials, missing OS security patch). Automated vulnerability scanners are great for instance to periodically scan whole enterprise ICT infrastructure for such fundamental security errors.

On the other hand, manual penetration test is there to uncover specific high profile vulnerabilities in limited set of systems (vulnerability in custom build application, guessable admin password based on user behavior observed elsewhere). Manual penetration test is therefore great fit for custom build applications, products or heavily customized infrastructures where automated scanning would fail to achieve expected results.

It is always important to understand which of those bring you greater security value and if the decision is made for manual penetration test, you must ensure that given penetration tester has sufficient qualification to indeed conduct manual penetration test. After all, what are you paying for during penetration test is the human expertise to find vulnerabilities which would be missed by automated vulnerability scanner. You do not want to end up paying for someone to run vulnerability scanner on your behalf. See section “Finding the right resources” for more information how to select right person to do the penetration testing job.

Setting the right scope / budget

Setting the right scope for penetration test is not as easy as it might seem. It shall take into consideration risk profile of your company / product as well as your budget limitations and security expectations. In order to take the most out of the penetration test, there must be clear and specific scope prior commencing. Following are just a few questions which must be answered:

  • (infrastructure) Which assets shall be tested?
  • (product) Which product interfaces / components shall be tested?
  • Are they publicly facing or only for internal use?
  • What would be the impact if such system gets hacked?
  • How much can they be affected by downtime?
  • How many users or employees rely on the normal and daily use of this system?

We understand that each customer has a specific needs. Penetration test shall always start with kick off meeting to clearly define the scope of the future testing. We always advise on how to make the testing most appropriate to you as end customer from both budget and risk profile perspective.

Penetration tests are scoped by amount of man-days which are utilized for the test. Just to give you some high level idea the following are the average scopes some of the typical scenarios:

  • External penetration test of single publicly facing IP – 1 MD
  • Custom medium-sized web application – 5MDs
  • Internal penetration test of 200 assets – 7 MDs
  • Complex desktop application connected to backend API – 10 MDs
  • Automotive head unit – 40 MDs

Finding the right resources

As everywhere, quality (penetration tester skills and experiences) is much more important than quantity (amount of man-days invested). Finding the right tester / company for the job is not always a straightforward job. There are many companies that sell “penetration tests” and at the end deliver only ready made reports exported from automated vulnerability scanning tools. On the other hand, there are specialized companies that dig deeper and are more focused on security research. To overcome this you can search for the right indicators when choosing the company that will perform the penetration test.

Look for certifications. Although certifications are not everything, they prove that their holder must have gone through exam which verifies certain baseline proficiency on the topic. Offensive Security for instance provides great certifications testing hands-on penetration testing skills. Their most popular certification – Offensive Security Certified Professional (OSCP) – verifies candidate skills in 24-hour long real-world penetration testing exam. Experienced penetration tester of your choice shall have proven technical background with at least certifications equivalent to OSCP.

Consider past projects of the company. There are many successful and good companies that provide cyber security services but not all might be suitable for you. We recommend to check their portfolio and verify whether they have experience with similar sized projects from the past.

Consider company security research. Security is about uncovering the unknown and unexpected. Good security company shall be conducting its own security research, finding its own vulnerabilities and developing its own tooling. We have proven track record for both – finding our own 0day vulnerabilities (flaws in software that are unknown to creator / vendor themselves) as well as developing our own open source projects which we use during our penetration testing projects.

Optimal timing for penetration test

So at this point you know the objective, scope and you have right person / company to kick it off so why not to start immediately? It is important to note that penetration test is simulated attack against your systems and as a such can cause unexpected business disruption. It is therefore crucial to plan it well. Here are just some of the consideration:

  • Can the penetration test be done on staging instead of production environment?
  • In an unlikely event that any system crashes, will there be anyone on call to restore its functionality without undue delay?
  • Shall any critical systems be tested out-of-business hours?
  • Shall any critical system be tested in less aggressive way (i.e. not running memory corrupting exploits)?
  • Shall we do the test on finalized product or early in development life cycle?

Answering such questions and planning the test accordingly is highly appropriate during kickoff workshop prior penetration test commences.

Outcome of the penetration test

The outcome of the penetration test should always be a detailed penetration testing report divided in several sections. First of all, an executive summary discussing all the identified findings together with severity in manner which is understandable to the technical as well as management teams. Secondly, there shall be detailed explanation of all the issues found in the technical detail which would be sufficient for engineering team to replicate those issues. Finally, there should be section describing optimal mitigation strategy for all identified issues together with next steps. Next steps might include re-testing once fixes are applied to confirm that fixes are effective.

Apart from the report we always recommend to also arrange a closing presentation (workshop) to present all identified issues, demonstrate how they can be misused by potential attacker and have a discussion with stakeholders how to fix those issues. It is always good to involve various stakeholders in such presentation – both managerial and technical – to join the presentation and ask their questions.

Finally, optional training can be arranged for the developers / ICT admins as an advanced benefit of the penetration testing project. Goal of the training is to provide necessary guidance and best practices which if followed would allow to prevent similar security issues from re-occurring in the future. In the end we all need to learn from the past security mistakes in order not to repeat them in the future.

Penetration testing is a process of securing your assets which became more or less a must have in the digital age. We hope this article would help you establish or improve penetration testing inside your organization. If you have any further questions or comments please feel free to reach out to us.

Categories
Security Research

CANdy – an automated CAN bus message mapping framework

Check out CANdy demo

When I was offered to write a bachelor thesis on the topic of CAN bus message mapping, I had no idea how crucial and fascinating such an area actually is and I would like to share with you what I learned and created during the past six months.

First thing first, what exactly is that CAN bus we are talking about? CAN stands for Controller Area Network, a communication protocol usually used in real-time systems to enable data exchange between each controller and electrical devices (engine sensors, brake systems, air conditioning, etc.). We can find it in many industrial domains but most importantly – transportation. CAN bus is a communication backbone of your vehicle’s internal systems and its importance has risen since every new car model is equipped with more electrical controllers and sensors than the previous one. For instance, CAN provides an efficient and cheap way to send data from engine sensors to the automobile dashboard to show you information about the car’s speed or RPM. However, the protocol only tells how each unit should talk to the other, but does not specify the “language” they ought to use. In other words, there are no general rules imposed on the data payload format. What is more, only car manufacturers are in charge of creating the definitions, which are not publicly available. As a result, we cannot simply connect to the bus and send messages or understand what exactly happens in the car. Such a state provides a certain level of security, that can prevent others from modifying the car internals or injecting malicious messages to its CAN network unless they are given some message definitions. This principle is also known as a “security by obscurity” and is generally considered as an insufficient method for securing any system or application.

Therefore, things can go wrong really easily. Lack of encryption or authentication allows us to forge any message we want and send it to the bus. Let’s say we have the format of the message carrying data from a proximity sensor and the car model uses a really advanced driving assistant, which can automatically detect if you are getting too close behind another car and slow down the car to avoid a possible crash. Now, what could happen when made up data were sent to the bus? With the right data, the driving assistant might slow down the car even if there is no vehicle around and vice-versa. In addition, CAN protocol is susceptible to DoS attacks as there is no mechanism preventing an attacker from flooding the bus with messages. As a result, blocking the whole bus can inflict major damage to the car and put the passengers in danger. Scenarios like these illustrate how easily we can affect the behavior of the car only with access to the CAN bus and why is car security more important than ever. Moreover, the next question is how do we obtain the message definitions for a specific car model.

Finally, this is where message mapping plays a key role. Luckily for us, raw CAN messages are not as random as they appear and we can find some certain patterns and characteristics to help us decode them. The process of assigning an unknown CAN message to a specific function or meaning is what we call message mapping. A few academic researchers have proposed solutions to either classify the messages or detect signals and their parameters, which do not fully recognize what exactly the message represents. Unfortunately, there is no universal method yet to map messages only with a message log from the bus and some level of interaction with the car is still required. Finding a message related to opening the door can be divided into three steps:

  1. Find out which messages are sent to the bus when you physically open the door. 
  2. If there is more than one, look at the payload and discover how does it change when you close or open the door. 
  3. Try to describe every possible state or value that is sent in the message.

It does not sound like big of a deal, right? Sadly, the task is a little bit more complicated than that. First of all, accessing the CAN bus itself could be a quite challenging task, because not all cars have their bus exposed to the OBD-II port. For instance, Volkswagen has its CAN bus hidden behind a gateway, therefore another channel needs to be found instead of a direct connection via OBD-II. In that case, you will have to take a more creative approach, which will require taking your car apart a little bit. Some modern cars may even offer ways to gain remote access, but that is way harder to accomplish still. Secondly, there are hundreds of messages sent to the bus every second and without any dedicated software, it would be impossible for us to navigate through all of that. Finally, this is where our tool comes in handy! CANdy can assort and filter out messages and provide useful information for mapping. It also gives you a better idea of what is going on the bus with its plotting modules and a decoder. What is more, you can write your own modules using its API to add some custom functionality. To better illustrate how CANdy works we would rather show you an example of mapping the gas pedal message using our tool.

This is how traffic on the CAN bus in Toyota Auris 2016 looks like in a span of 0.01 second.
One of our modules helped us detect message ID – 0x2c1, which appears when the gas pedal is pressed. We can get rid of all the noise with a message filter and get cleaner data for our analysis.  
The improved output suggests that some bytes of the payload may carry some useful information. Naturally, the most obvious way to examine such data is making a time series graph. And we have a module for it too.

This plot only shows the first and the seventh byte in the payload. But it is sufficient to recognize the data in the first byte as an indicator whether the pedal is pressed or not, while the seventh byte seems to tell us how much. In order to confirm or dispute our theory, one may look up an official definition for the gas pedal message on the internet or compare your results with someone else. One definition we found on the internet for Toyota Corolla 2017, a very similar model to Auris, describes the message like so:

It is not necessary to dive into details about the format, so we will interpret it for you. The message ID for the gas pedal is 705, which is 2c1 in hexadecimal. Then, there are two signals, which are technically just some values placed in the specified position of the payload. Also, the CAN message data field has a fixed length of 64 bits using zero-based indexing. In this case, it means that the fourth bit in the message indicates the gas pedal is released and the last byte of the payload is used for pressure on the pedal (offset 55 bits, length 8 bits). As we can see, our first guess about the indicator was most probably correct. The latter may be still applicable, because we do not have completely matching CAN definitions, but we cannot be sure either. Another way to test this theory is to try to press the pedal and see which bytes are changing accordingly. Such a task could be carried out with another module we wrote for rendering a real-time plot for a particular message and its bytes.

Ultimately, there are a lot of other units to map with their messages like windows, turn signals, etc. And there is nothing stopping you from trying to hack your car’s CAN bus the same way as we did. CANdy is published as an open-source tool for everyone to try out and for the next step, we would like to gather and publish a crowdsourced database of various CAN definitions. Thus, you are more than welcomed to take a look at CANdy, test it out, and share your results with us. For more information, please check out the paper with technical details and resources. Also, the repository with the tool is available at this link.

Categories
Security Research

[CVE-2020-15779] Path Traversal in Socket.io-file NPM module

Title: Path Traversal in Socket.io-file NPM module
Date: 18/05/2020
CVE-ID: 2020-15779
Advisory: https://www.npmjs.com/advisories/1519
Author: Thomas Sermpinis
Versions: <= 2.0.31
Package URL: https://www.npmjs.com/package/socket.io-file
Tested on: node v10.19.0, Socket.io-file v2.0.31, socket.io v2.3.0
Proof of Concept: https://www.exploit-db.com/exploits/48713

During one of my penetration tests for a local military equipment supplier, I faced a web application running on an embedded device that used web sockets in order to initiate the connection between the server and the client. There are several different technologies that can be used in the back-end system in order to make use of web sockets, but the client made use of Socket.io.

The web application was relatively small, with only a few entry points that did not seem to be vulnerable. All the modules were up to date and my enumeration started to go into a dead end. As there were more days for my pentest, I decided to dig deeper and I started analyzing more the request and researching about the npm modules that were included and were in use in the web application.

One of the functionalities was a configuration file upload, that was stored in a folder in the filesystem, by using the Socket.io-file npm module. Socket.io-file (2.0.31) is a node module for uploading files via the Socket.io module. Playing around with the requests I managed to bypass the restrictions and upload a file in a different folder from the expected one (I knew that as I had access to the backend of the system).

Client and project aside, the upload functionality of socket.io-file is vulnerable to improper input validation, allowing attackers to bypass upload directory restrictions and it allows them to upload files to paths of their choice in the underlying system.

Description of the Vulnerability

The default configuration of Socket.io-file comes with an upload functionality handled by websockets. When a user tries to upload a file with the web application, the following client side request is created in order for the file to be created:

Figure 1: Normal websocket request for file upload with Socket.io-file

42["socket.io-file::createFile",{"id":"u_0","name":"testfile.mp3","size":1,"chunkSize":10240,"sent":0,"data":{}}]

In order for this file to be created to the underlying system, the code from index.js of Socket.io-file is executed and the following part of the code, manages to merge the file path (supplied by the socket.io-file configuration) with the file name that was supplied by the user:

if(typeof options.uploadDir === 'string') {uploadDir = path.join(options.uploadDir, filename);}

As an example, if the user uploads a file with the name “testfile.mp3” and the server is configured to to store files in the “/home/Documents/socket-app/data” path the resulting path that Socket.io-file will create the file, will be “/home/Documents/socket-app/data/testfile.mp3”.

Because the aforementioned code makes no check on the file name, the upload request can be intercepted and the file name altered in a way that will move in certain paths of the system. The following example exploits this issue:

42["socket.io-file::createFile",{"id":"u_0","name":"../testfile.mp3","size":1,"chunkSize":10240,"sent":0,"data":{}}]

This request will generate the following path for the file to be stored “/home/Documents/socket-app/data/../testfile.mp3”, which means that the file will actually be created in “/home/Documents/socket-app/testfile.mp3” as the ../ characters will move the path one level lower in the filesystem.

Figure 2: File created in the node_modules directory of the filesystem, outside the intended directory.

From this example we can understand that we can write in several sensitive directories like the ~/ home directory (which includes the .ssh folder which allows us to rewrite the ssh configuration), in the root webserver directory (which can help us get a reverse shell under the right circumstances) and the cron directory (where we can inject cron jobs for code execution). Additionally, if the back-end system runs with superuser privileges (which is not so uncommon), the attacker can use this vulnerability to create files in even more sensitive paths (e.g. /root and /etc). As an example, we can write the /etc/passd file of our implementation like the following:

42["socket.io-file::createFile",{"id":"u_0","name":"../../../etc/passd","size":1,"chunkSize":10240,"sent":0,"data":{}}]

Issue Replication

In order to replicate the issue, the following steps have to be executed:

  • Setup a proxy to intercept HTTP and WebSocket requests (e.g. Burp Suite or OWASP Zap)
  • Upload a file using the Socket.io-file web application and intercept the websocket request
  • Change the “name” parameter by adding ../ and specifying the needed path:
    • 42[“socket.io-file::createFile”,{“id”:”u_0″,”name”:”../../../Downloads/testfile.mp3″,”size”:1,”chunkSize”:10240,”sent”:0,”data”:{}}]
    • This example will create the testfile.mp3 file in the Downloads directory of the current user (our test server stores files in “/home/ubuntutest/Documents/socket-app/data”)

Remediation

No fix is currently available. Consider using an alternative package until a fix is made available.

Vulnerability Disclosure Timeline

Following the npm guidelines for vulnerability disclosure (“If maintainers are unresponsive after 45 days, npm Security makes the advisory public”), we responsibly disclosed this vulnerability on 18th of May 2020.

  • Initial Disclosure: 18th May 2020
  • Security Team Validation: 18th May 2020
  • Advisory Release: 7th July 2020
  • CVE-ID Assignment: 15th July 2020
  • PoC Release at exploit-db.com: 27th July 2020