0

In a REST API, I'd like to receive images as base64 encoded strings in a JSON objects fron user's post and save them to disk using node.js fs module.

The request body are objects like:

 { file: 'data:image/png;base64,iVBORw0KGgoAAA...

I'm wondering if there are some vulnerabilities associated with such file storage and how to avoid them?

Karlom
  • 135
  • 1
  • 6

2 Answers2

4

First of all, there's all the standard web service security risks (connection security, authentication, authorization, session management, denial of service, logging, patching, etc.). I'm not going to talk more about those for now, but do bear in mind that you need a secure environment for something like this.

As for the risks specific to your system and ones like it... The most obvious risk comes if the users have any control over the filename the service creates. If so, you have risks such as file system traversal, overwriting of others' files, and so on. It doesn't look like you plan to do this, but it's something to bear in mind.

There's also the risk of uploading content that could be used to attack either the server or the other users. These attacks are easiest if the attacker can control the filename, but are possible if all they can control is the extension (and they learn the file name), and if there's a web API to download the file. To attack the server, upload a malicious file that the server will treat as executable (for example, a PHP page if the server supports those) and then navigate to it; this may not be possible if you're using a well-configured Node server. To attack other users, upload a malicious HTML file and try to trick other users into viewing it in their browser (resulting in stored XSS); this can be mitigated by making the files retrievable only from a different domain than the one for which the user has cookies / authentication, and/or forcing the browser to download the file rather than display it.

There's denial of service via simply uploading too much data. Consider how much data you'll allow users to store, and how you enforce that limit.

There's the risk of illegal content. The standard example here is child pornography; if users upload such content to your server and you are then found to be "in possession" of it, things could go badly for you. I'd recommend checking local laws, and ideally asking a lawyer, what your rights and responsibilities are when it comes to hosting user-uploaded content.

There's some risks to your JSON or base64 parsers, though these formats are simple and widely-implemented, so I wouldn't expect problems there. I don't understand why you want to use these formats, though; MIME content types are the standard way to upload files to a web server (and therefore feature built-in parsing in most web servers) and are less wasteful of bandwidth (base64 expands all encoded content to 4/3 the size, but there's no reason an HTTP request body needs to be composed only of printable characters).

Since you're storing a lot of user data, you need to consider at-rest data security. Encrypting the files individually, encrypting the whole volume, or using a transparently-encrypted external store are all potential ways to achieve this, but they also present the issue of key storage (as nearly all cryptosystems do). Don't forget to ensure your backups are also protected; tons of sensitive data has been leaked or stolen after somebody got ahold of the backup tapes or similar.

You may also want to consider the issue of user privacy. While not exactly a security feature, privacy (preventing unauthorized users - potentially including you, the service operator - from seeing what was uploaded) involves a similar mindset and is often provided using security tools (such as encryption). You tagged this question as "file-encryption", but you don't actually talk about encryption at all (base64 is an encoding, but there is no key involved; anybody who wants to can decode it, so it isn't an encryption scheme).

CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • So, if I understand correctly, if users can not choose the filename, extension and the filesize is limited, there is no risk right? I choose base64 because I bound to receive images inside json objects (which also contains jwt token to deal with) – Karlom Oct 19 '18 at 10:31
  • @Karlom there is always some level of risk. Nothing that allows user input is completely without risk. OWASP has a good overview if common risks, and attacks related to file upload. https://www.owasp.org/index.php/Unrestricted_File_Upload – Daisetsu Oct 19 '18 at 18:06
  • 1
    @Karlom JWT is usually sent in a header, rather than the body, although it could be sent in the body if you want. I don't understand why you want the uploads themselves to be inside JSON objects, but hey, it's not a significant security risk and that's what you asked about. With that said, I highlighted a number of risks that are not related to the users choosing any part of the filename, and if users can upload multiple files than limiting the size of each one isn't sufficient. – CBHacking Oct 20 '18 at 05:31
2

Base64 is a common way to include binary data in text documents, such as JSON or e-mails. In fact, this encoding was created for this purpose.

As a side note, this encoding is not intended to be used for storage of data, but for transmission of data over text protocols.

The vulnerabilities could come from the base64 parser, but since it is a very simple format, this is unlikely compared to other encoding formats. However it still happened in the past, multiple times. So you should take care while choosing your parser.

Other vulnerabilities could come from your JSON parser. The same remarks than for base64 applies here too.

The other possible vulnerabilities are not specifically dependent on base64 or JSON, thus I will not address them here (and that would be answering a fairly broad question). Generally, take care while developing your REST API. Good guides can be freely found, such as OWASP for the web development. You could also do a simple risk assessment to prioritize your security efforts.

A. Hersean
  • 10,046
  • 3
  • 28
  • 42