It’s the same as with Linux, GIMP, LibreOffice or OnlyOffice. Some people are so used to their routines that they expect everything to work the same and get easily pissed when not.

  • Riskable@programming.dev
    link
    fedilink
    English
    arrow-up
    30
    ·
    1 year ago

    There are risks with server security and threat of being hacked

    [Citation Needed]. I’m a security professional (my day job involves auditing code). I had a look through the Lemmy source (I’m also a Rust developer) and didn’t see anything there that would indicate any security issues. They made good architecture decisions (from a security perspective).

    NOTES ABOUT LEMMY SECURITY:

    User passwords are hashed with bcrypt which isn’t quite as good a choice as argon2 but it’s plenty good enough (waaaaay better than most server side stuff where developers who don’t know any better end up using completely inappropriate algorithms like SHA-256 or worse stuff like MD5). They hard-coded the use of DEFAULT_COST which I think is a mistake but it’s not a big deal (maybe I’ll open a ticket to get that changed to a configurable parameter after typing this).

    I have some minor nitpicks with the variable naming which can lead to confusion when auditing the code (from a security perspective). For example: form_with_encrypted_password.password_encrypted = password_hash; A hashed password is not the same thing as an “encrypted password”. An “encrypted password” can be reversed if you have the key used to encrypt it. A hashed password cannot be reversed without spending enormous amounts of computing resources (and possibly thousands of years in the case of bcrypt at DEFAULT_COST). A trivial variable name refactoring could do wonders here (maybe I should submit a PR).

    From an OWASP common vulnerabilities standpoint Lemmy is protected via the frameworks it was built upon. For example, Lemmy uses Diesel for Object Relational Mapping (ORM, aka “the database framework”) which necessitates the use of its own syntax instead of making raw SQL calls. This makes it so that Lemmy can (in theory) work with many different database back-ends (whatever Diesel supports) but it also completely negates SQL injection attacks.

    Lemmy doesn’t allow (executable) JavaScript in posts/comments (via various means not the least of which is passing everything through a Markdown compiler) so cross-site scripting vulnerabilities are taken care of as well as Cross Site Request Forgery (CSRF).

    Cookie security is handled via the jsonwebtoken crate which uses a randomly-generated secret to sign all the fields in the cookie. So if you tried to change something in the cookie Lemmy would detect that and throw it out the whole cookie (you’d have to re-login after messing with it). This takes care of the most common session/authentication management vulnerabilities and plays a role in protecting against CSRF as well.

    Lemmy’s code also validates every single API request very robustly. It not only verifies that any given incoming request is in the absolute correct format it also validates the timestamp in the user’s cookie (it’s a JWT thing).

    Finally, Lemmy is built using a programming language that was engineered from the ground up to be secure (well, free from bugs related to memory management, race conditions, and unchecked bounds): Rust. The likelihood that there’s a memory-related vulnerability in the code is exceptionally low and Lemmy has tests built into its own code that validate most functions (clone the repo and run cargo test to verify). It even has a built-in test to validate that tampered cookies/credentials will fail to authenticate (which is fantastic–good job devs!).

    REFERENCES:

    • epicspongee
      link
      fedilink
      English
      arrow-up
      1
      ·
      1 year ago

      It not only verifies that any given incoming request is in the absolute correct format it also validates the timestamp in the user’s cookie (it’s a JWT thing).

      This is false.

      Lemmy’s JWTs are forever tokens that do not expire. They do not have any expiration time. Here is the line of code where they disable JWT expiration verification.

      Lemmy’s JWTs are sent via a cookie and via a URL parameter. Pop open your browser console and look at it.

      There is no way to revoke individual sessions other than changing your password.

      If you are using a JWT cookie validation does not matter, you need to have robust JWT validation. Meaning JWTs should have short expiration times (~1hr), should be refreshed regularly, and should be sent in the header.

      • Riskable@programming.dev
        link
        fedilink
        English
        arrow-up
        1
        ·
        edit-2
        1 year ago

        When I said, “it validates the timestamp” I wasn’t talking about the JWT exp claim (which you’re correct in pointing out that Lemmy doesn’t use). I was talking about how JWT works: The signature is generated from the concatenation of the content of the message which includes the iat (Issued-at) timestamp. The fact that the timestamp is never updated after the user logs in is neither here nor there… You can’t modify the JWT message (including the iat timestamp) in Lemmy’s cookie without having it fail validation. So what I said is true.

        The JWTs don’t have an expiration time but the cookie does… It’s set to one year which I believe is the default for actix-web. I’m surprised that’s not configurable.

        You actually can invalidate a user’s session by forcibly setting their validator_time in the database to some date before their last password reset but that’s not really ideal. Lemmy is still new so I can’t really hold it against the devs for not adding a GUI feature to forcibly invalidate a user’s sessions (e.g. in the event their cookie was stolen).

        I also don’t like this statement of yours:

        If you are using a JWT cookie validation does not matter, you need to have robust JWT validation. Meaning JWTs should have short expiration times (~1hr), should be refreshed regularly, and should be sent in the header.

        Cookie validation does matter. It matters a lot! Real-world example: You’re using middleware (or an application firewall, load balancer, or similar) that inserts extra stuff into the cookie that has nothing at all to do with your JWT payload. Stuff like that may require that your application verify (or completely ignore) all sorts of things outside of the JWT that exist within the cookie.

        Also, using a short expiration time in an app like Lemmy doesn’t make sense; it would be super user-unfriendly. The user would be asked to re-login basically every time they tried to visit a Lemmy instance if they hadn’t used it in <some time shorter than an hour like you suggested>. Remember: This isn’t for message passing it’s for end user session tracking. It’s an entirely different use case than your typical JWT stuff where one service is talking with another.

        In this case Lemmy can definitely do better:

        • Give end users the ability to invalidate all logged in sessions without forcing a password reset.
        • Make the cookie expiration time configurable.

        When using JWT inside of a cookie (which was not what JWT was meant for if we’re being honest) there’s really no point to using the exp claim since the cookie itself has its own expiration time. So I agree with the Lemmy dev’s decision here; it’d just be pointless redundant data being sent with every single request.

        Now let me rant about a JWT pet peeve of mine: It should not require Base64 encoding! OMFG talk about pointless wastes of resources! There’s only one reason why JWT was defined to require Base64 encoding: So it could be passed through the Authorization header in an HTTP request (because JSON allows characters that HTTP headers do not). Yet JWT’s use case goes far beyond being used in HTTP headers. For example, if you’re passing JWTs over a WebSocket why the fuck would you bother with Base64 encoding? It’s just a pointless extra step (and adds unnecessary bytes)! Anyway…