balzack / databag

fast & lightweight self-hosted messenger
Apache License 2.0
902 stars 49 forks source link

Some Security considerations + docker size #62

Open LordPraslea opened 1 year ago

LordPraslea commented 1 year ago

Hi

Project sounds interesting. I love that it's lightweight (somewhat) and that it can run on a RPI. i've been searching for something like this built in GO for a while.

Some security considerations, i didn't do a full audit or exploration (seems to avoid basic XSS at the moment) Wouldn't it be better to somehow obfuscate the admin page/button? And instead use an admin user which is generated and chosen BY the user upon init. This will avoid brute force attacks.

As for the docker, you could use a multistage build. This will make the docker size smaller and will only copy the resulted binary and website instead of the whole sourcecode and nodejs libs which are probably not usefull. https://docs.docker.com/build/building/multi-stage/

Nice job!

balzack commented 1 year ago

I will look into the multistage build; I was not aware of this. Is this why you said it was "somewhat" lightweight, or do you see other things that can be optimized?

I agree with your point on adding admin privileges to an account; I see that as a better implementation. This would require a larger refactor, so is probably a ways out before I can get to it.

LordPraslea commented 1 year ago

By lightweight i meant that in theory, after the frontend is built it could be embeded it into the golang binary as 1 executable using the https://pkg.go.dev/embed package. This could make it that you can actually release the binaries instead of using docker, and integrating the binary directly into an alpine/slim debian docker for people who want to use docker. See also point 3.

I found another pretty big security issue, the admin token is sent as a GET parameter which has a few issues

  1. It's stored in the docker logs and/or it would be stored in the server logs (access logs, proxy logs..), which can give anyone access to it. LEt's say you use a reverse proxy between.. well then it certainly gets stored somewhere. It would be better to pass it off as POST OR use it initially to build a JWT (or anyother token which expires) and send that token instead.
  2. It's also stored unencrypted/unhashed in the sqlite DB.

I played around with the app via a local docker instance which was reverse proxied with SSH to a subdomain.

  1. Your whole build process could in reality be simplified and streamlined by using something such as HTMX for the frontend as it could be directly embedded in the app without the need for building react. But this is possibly a large refactoring for the moment :)
balzack commented 1 year ago

Firstly, thanks for your review of the project! I really appreciate your time and knowledge.

Thanks for the go package suggestion. I'll need to figure out how to do that, but it seems like a great way to make this project more accessible.

As to your other points:

  1. Is there a scenario in which someone could have access to the logs that isn't a system admin? Originally I had transferred the auth tokens within the HTTP header. Eventually when I built the mobile app I had to move the token to a query param, because the core image object in react native doesn't support customizing the HTTP header. If the logs are exposed to a non-admin, then I absolutely need to come up with a different solution.
  2. Good point. For my use case, I use a single purpose token, but that doesn't apply to everyone. I will update the store for this to use a salted-hash.
  3. I haven't programmed with HTMLX before, so perhaps my view is incorrect. I had read that HTMLX isn't desirable if your app has a lot of javascript code. Because the databag client needs to synchronize a view of a distributed database, it ends up doing a lot in javascript, and HTMLX wasn't a good fit. Please let me know if I am misinformed.