Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

based upon Kevinsbranch encrypted key in config.json using cryptojs && start performance fix #5465

Closed
wants to merge 6 commits into from

Conversation

ksaadDE
Copy link

@ksaadDE ksaadDE commented Aug 15, 2021

Problem: as mentioned in issue #1850
dbKey is in desktop-app of signal unencrypted on disk inside the config.json
A attacker with local privileges or system privileges could exfiltrate the dbKey (unencrypted inside config.json), the SQLIteDB and decrypt the content (either remote or locally).

Also, the code was blurry which resulted in higher start time (three times SQLinit sounds not so good)
-> reduced it to one time SQLinit in app.on('ready',...)

Tests:
https://streamable.com/ab5yvj
Tested manually by starting the app, sending && recieving messages and so on in dev env (not tested yet in any builds)
based upon Kevinsbranch since reCaptcha needed for dev

What the PR should do:
Speed up the start time of the Signal-Desktop app;

Should automatically ask the user the first time when started the app which password to choose.
AND should ask on every start what the password is
OR when the password is not set yet, asking for one and encrypting the old DB key.

The key property in config.json is now encrypted with AES && only user knows password.
A new property inside the config.js called "usesPassword" (true|false) is used for differentiating between an encrypted Key and not an encrypted key.

And added start.sh with nvm, making testing easier

And sorted the code salad inside the main.js (see comment at top of main.js)

Reasons not to store a hash inside config.json:
Hash would provide authentication, but the hash can be reverted under circumstances, therefore no hashing at all.
Also, the security is ensured through the encrypted dbKey. Since the issue was only the unencrypted storing on disk.

Dependencies:

  • electron-prompt
  • cryptojs

Last words:
Thanks! :-)

oops forget some small issue.  removed the userpasswordprompt.js from code (which I never use in the actual PR)
added information for the user for the 20 chars minimum

```
  if (password === null || password === undefined) return 'data.error.nopwentered_or_abort';
  if (password.length         < 20)                return 'data.error.pwshort';
  if (password.trim().length  < 20)                return 'data.error.pwwhitespace';
  if (password.length         > 128)               return 'data.error.pwlong';
  return 'data.success';
```
added information for the user more than 20 chars
``
  if (password === null || password === undefined) return 'data.error.nopwentered_or_abort';
  if (password.length         < 20)                return 'data.error.pwshort';
  if (password.trim().length  < 20)                return 'data.error.pwwhitespace';
  if (password.length         > 128)               return 'data.error.pwlong';
```
@ksaadDE ksaadDE changed the title based upon Kevinsbranch encrypted key in config.json using cryptojs based upon Kevinsbranch encrypted key in config.json using cryptojs && start performance fix Aug 15, 2021
@indutny-signal
Copy link
Contributor

Thanks for opening this PR. We value your time and understand why this is important to you. With features like this, however, we'd appreciate if you could start by requesting them on community forums ( https://community.signalusers.org/c/feature-requests/desktop-feature-requests/20 ) before investing any time into it. Unfortunately we cannot merge your Pull Request at this time, but feel free to keep it open for yours and ours future reference.

Some immediate feedback that I could give is that it might not be a good idea to combine refactor changes with the logic changes as it makes it harder for a reviewer to look through the code. Additionally, the multiple database initialization that you mentioned is just awaiting for the same promise so it doesn't happen thrice. Furthermore awaiting this initialization is necessary for the startup logic and migrations to proceed correctly.

@ksaadDE
Copy link
Author

ksaadDE commented Aug 16, 2021

First of all Hi! @indutny-signal

we'd appreciate if you could start by requesting them on community forums ( https://community.signalusers.org/c/feature-requests/desktop-feature-requests/20 ) before investing any time into it. Unfortunately we cannot merge your Pull Request at this time, but feel free to keep it open for yours and ours future reference.

We actually have multiple feature requests in the Signal community and on Github!

image
In the Github discussion I pinged you, it could be nice to read.

Furthermore awaiting this initialization is necessary for the startup logic and migrations to proceed correctly.

In my testing it didn't play a big role, since I reordered them and let it do the important stuff in the right order (nothing more or less). The code is now much cleaner. I only moved the consts and lets which were (before) outside of functions to the top in a cleaner order.
btw At sqlError you peform a new await since you copy over the promise to a new subpromise. Which is is not a good way of handling it. You could just use the await sqlinit from the beginning, without any trouble (as I do!).

If you want to see a working example, without pairing between devices and no setup as standlone (no time for it):
https://streamable.com/ab5yvj

We all would like to see the feature implemented asap, since the key unencrypted on disk is currently a HIGH risk!
Since 2017 is a FR opened and nobody cares about it. One of you even replied you don't care about it in one of these threads xD
image

Two things wo might bypass any mentioned protection:

  • RATs
  • 0815 Ransomware with Credstealer!

Also, I agree it is a bit difficult to differentiate between the big changes, the prompt and AES stuff, but also the rest. But it's possible, I inserted comments at the right places.

@EvanHahn-Signal
Copy link
Contributor

EvanHahn-Signal commented Sep 17, 2021

Thanks for your hard work. Unfortunately, this pull request has many unrelated things, and we won't be merging it.

  • The CAPTCHA changes were done in load CAPTCHA to enable phone number verification #5473 and should be a separate issue.

  • I don't understand the benefit of the start.sh changes. This should already be done by people developing Desktop, and I don't think it belongs in the repo. In addition, it will only won't work on Windows. (EDIT: updated my comment about Windows)

  • We have no immediate plans to start encrypting the database as you've added here, unfortunately. If we did this, we would probably make this process largely invisible to the user and use Keytar to store sensitive data.

  • There are many files in this pull request that shouldn't be included, such as compiled JavaScript.

I'm going to close this issue, but please email evanhahn@signal.org if you want to help out in a more directed way!

@ksaadDE
Copy link
Author

ksaadDE commented Sep 17, 2021

We have no immediate plans to start encrypting the database as you've added here, unfortunately.

Well you don't have plans to fix the insecurity in Signal-Desktop? Well, I'm not sure if the Community really likes that.
The DB is already encrypted, but your config.json is not. That's what I've fixed. With crypto-js, a commonly used library for it - which seems to be one of the securest.

I don't understand the benefit of the start.sh changes. In addition, it will only work on Windows.

start.sh wasn't changed, it was added. I used it for dev purposes (don't want to type in everytime the same commands), like stated in the comments inside the file.
No ".sh" (e.g. bash) runs only under Linux, not Windows! (Except for Linux Subsystem on Windows)

There are many files in this pull request that shouldn't be included, such as compiled JavaScript.

Where? The 18 Files did not include compiled JS. Please link them individually.
/E: after discuss below, a user mentions Files like the SystemTrayIcon and TypeScript, I didn't change anything there - still wondering why it wasn't included in the .gitignore if it gets generated.

The CAPTCHA changes were done in load CAPTCHA to enable phone number verification #5473 and should be a separate issue.

I've used the Kevinsbranch, because your Captcha Verification doesn't work in the actual Signal-Dev Version. You didn't know that? I bet you knew it before, there's even a issue for it!

Btw: Keytar is not suited for that use-case, it would conflict with the currrent implementation of your encrypted SQLiteDB.

You're closing a issue the Community requested a lot of times. Without any real reasons, just to underline that.

@Herohtar
Copy link
Contributor

Herohtar commented Sep 17, 2021

There are many files in this pull request that shouldn't be included, such as compiled JavaScript.

Where?

All the .js files that contain things like function(o, m, k, k2) -- that's the result of TypeScript being "compiled" into JavaScript. If you need him to list those for you, then it just shows you don't understand what you are working with.

@ksaadDE
Copy link
Author

ksaadDE commented Sep 18, 2021

function

There are many files in this pull request that shouldn't be included, such as compiled JavaScript.

Where?

All the .js files that contain things like function(o, m, k, k2) -- that's the result of TypeScript being "compiled" into JavaScript. If you need him to list those for you, then it just shows you don't understand what you are working with.

The funny thing is, I didn't work with TypeScript. I guess it was generated when doing the testing process or building process.

Like you put compiled into quotes, in my understanding compiling is not the process of generating files with "interesting" code. So I searched or better to say looked out for binary code. I wouldn't call it either minifying or something like that.

After seeing the mentioned stuff inside the System Tray Service js and with your hint , I agree to that point.

Usually Devs excluding these files in .gitignore. Why it wasn't done here? So that I don't have to take a look into a part where I didn't change anything

Still doesn't explain that people confusing Linux and Windows (especially basic skills like .sh files) xD

TL;DR:
You could just remove the files in the merge, so I don't see it as a valid point. You know what your code does, so you could fix it and add it to the .gitignore.

But the rest is still unclear. ^^

it just shows you don't understand what you are working with.

Btw2: Don't run in the trap making the mistake to confuse JS and TS. ;)

@EvanHahn-Signal
Copy link
Contributor

Well you don't have plans to fix the insecurity in Signal-Desktop? Well, I'm not sure if the Community really likes that.
The DB is already encrypted, but your config.json is not. That's what I've fixed. With crypto-js, a commonly used library for it - which seems to be one of the securest.

The threat model is this: if you have malware on your computer, it has free reign. It could, for example, take screenshots every 5 seconds and steal your data that way. So: encrypting the data on disk, while possible for us to do, would be redundant.

That's not to say we'll never address this, but we don't see it as an obvious insecurity.

start.sh wasn't changed, it was added. I used it for dev purposes (don't want to type in everytime the same commands), like stated in the comments inside the file.

That's great—please keep this file around for future development on Signal Desktop, but I don't think we'll need it in the source repository.

No ".sh" (e.g. bash) runs only under Linux, not Windows! (Except for Linux Subsystem on Windows)

You're totally right—my mistake. I've edited my original comment.

Usually Devs excluding these files in .gitignore. Why it wasn't done here? So that I don't have to take a look into a part where I didn't change anything

It's there:

app/*.js

It's possible that you added these with git add --force, which lets you bypass .gitignore.

@ksaadDE
Copy link
Author

ksaadDE commented Sep 21, 2021

Threat model

Think about some oldschool drive-by download or webexploit. Lets say the Malware is not able to do a PrivEsc, but it can exfiltrate config.json and the encrypted DB. That means all info are now ready for easy use by the attacker or the C2. We don't even talk about well written Spyware at this point! Also, we don't talk about stuff going on at system or root priv.

Due to the complete exfiltration the attacker has nothing to do than just reading the decrypted stuff inside the DB. It's easy, it's fast and powerful. Uh that guy writes about bringing his kids to some school? Well we'll take his kids out of there, "earning" some money. Uh nice passwords and creditcard information...? uh he's ill? good to know!

My mitigation allows the user to set a password which encrypts the DB key inside the config.json.
That means the dark side could only extract garbage. Let them exfil, if they can't to anything with it, makes things hard for them and easy for the good, innocent people.

FDE
Your FullDiskEncryption does not protect against threats when the system is already decrypted. Yes it is encrypted on your drive, but not when the system is opened and executed (if you view it as a program running on the computer). That solution was created against attacks physical attack vectors, like the oldschool guy breaking into your company or home, stealing your drives.
That's the redundancy you mean? Or do you mean the decryptable messages inside the SQLDB?

Keyloggers
If you type stuff in it's very likely someone recording it. That's the reality.
That's why using good password managers. Then the malware (better to say bad Spyware) sees only the ctrl + C and ctrl +V possibility. Also, to mention it, some password managers encrypting at copying and decrypting at pasting. Makes it very hard, but still possible.

Screenshots
Yes, possible and done in reality. But you would need some system or exfiltrating by hand the key infos you get. And you only get a tiny piece of the whole information - completely the opposite of exfiltrating the complete DB, decrypting it and taking advantage out of that info.

That's great—please keep this file around for future development on Signal Desktop, but I don't think we'll need it in the source repository.

What ever you want, but I would prefer to have it directly in there. So if I would test under Linux I just run that script an it's done ;)
Maybe that makes it easier for people to contribute good stuff.

It's possible that you added these with git add --force, which lets you bypass .gitignore.

I went through the history I've never used the --force option.
Anyways it's not that thing to delete these files :) I would clone the forked repo, go into the kevinsbranch, remove the app/*.js files and then uploading it again, opening a new PR. But you don't think about to use it anyways, so I don't need to do it. xD

Do you still want to prevent a protection against that threat the next 20 years?
I thinks it's time to go with the time. It's not about killing every attack an attacker may try. Times changing fast, business models of the dark side too. But it's better to make it very hard for them, so they get frustrated and give up soon.

I really appreciate your offers, but I don't think I will contribute in the future. Why should I waste more time on that?

Serious threats getting downplayed, while less important stuff seems to be a priority. Users had the wish to fully encrypt the DB, for years now.

Why not making a optional version of Signal, where it's done, like in my code? There's no point to say "no" to that, or do I need to know something?

Greetz

@DDvO
Copy link

DDvO commented Dec 26, 2021

Thanks a lot @ksaadDE for providing this pull request!
You did not only complain about that severe security leak, like I did a couple of days ago in #5703,
but even spent considerable effort fixing it and offered your solution here.
Yet then it got rejected, with just secondary, superficial, and unconvincing reasons given.
You have my full sympathy for the severe frustration this must have caused to you.

I am also heavily disappointed by the attitude exhibited here and elsewhere by Signal representatives.
For whatever reason, they do not want security controllable by the average user. Shame.

P.S. Here is the ultimate bug fix: use some other, sincerely secure messenger.

@AndrewtheCanon
Copy link

Signal stores the key unencrypted along with the database. is there going to be any changes to this?

@ksaadDE
Copy link
Author

ksaadDE commented Jul 5, 2022

Signal stores the key unencrypted along with the database. is there going to be any changes to this?

You can read the messages above by the Signal Team. They don't want to change anything to it, because it is in their opinion not important (official opinion of them). People might wonder if that's true.

I went silent about this issue, not only because I am a bit speechless, more because I got very interesting E-Mails.

Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants