mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 06:23:38 +00:00
docs: Extract security-model.md.
This commit is contained in:
@@ -60,10 +60,8 @@ be a user of multiple Zulip realms. The administrators of a realm can
|
|||||||
choose whether to allow anyone to register an account and join, or
|
choose whether to allow anyone to register an account and join, or
|
||||||
only allow people who have been invited, or restrict registrations to
|
only allow people who have been invited, or restrict registrations to
|
||||||
members of particular groups (using email domain names or corporate
|
members of particular groups (using email domain names or corporate
|
||||||
single-sign-on login for verification). For more on scalability and
|
single-sign-on login for verification). For more on security
|
||||||
security considerations, see [the security section of the production
|
considerations, see [the security model section](security-model.html).
|
||||||
maintenance
|
|
||||||
instructions](prod-maintain-secure-upgrade.html#security-model).
|
|
||||||
|
|
||||||
The default Zulip home screen is like a chronologically ordered inbox;
|
The default Zulip home screen is like a chronologically ordered inbox;
|
||||||
it displays messages, starting at the oldest message that the user
|
it displays messages, starting at the oldest message that the user
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ Contents:
|
|||||||
prod-troubleshooting
|
prod-troubleshooting
|
||||||
prod-customize
|
prod-customize
|
||||||
prod-maintain-secure-upgrade
|
prod-maintain-secure-upgrade
|
||||||
|
security-model
|
||||||
prod-authentication-methods
|
prod-authentication-methods
|
||||||
prod-postgres
|
prod-postgres
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,12 @@ secure Zulip installation, including:
|
|||||||
- [Backups](#backups)
|
- [Backups](#backups)
|
||||||
- [Monitoring](#monitoring)
|
- [Monitoring](#monitoring)
|
||||||
- [Scalability](#scalability)
|
- [Scalability](#scalability)
|
||||||
- [Security Model](#security-model)
|
|
||||||
- [Management commands](#management-commands)
|
- [Management commands](#management-commands)
|
||||||
|
|
||||||
|
You may also want to read this related content:
|
||||||
|
|
||||||
|
- [Security Model](security-model.html)
|
||||||
|
|
||||||
## Upgrading
|
## Upgrading
|
||||||
|
|
||||||
**We recommend reading this entire section before doing your first
|
**We recommend reading this entire section before doing your first
|
||||||
@@ -353,196 +356,10 @@ running Zulip with a large team (>1000 users).
|
|||||||
Questions, concerns, and bug reports about this area of Zulip are very
|
Questions, concerns, and bug reports about this area of Zulip are very
|
||||||
welcome! This is an area we are hoping to improve.
|
welcome! This is an area we are hoping to improve.
|
||||||
|
|
||||||
## Security Model
|
## Securing your Zulip server
|
||||||
|
|
||||||
This section attempts to document the Zulip security model. Since
|
Zulip's security model is discussed in
|
||||||
this is new documentation, it likely does not cover every issue; if
|
[a separate document](security-model.html).
|
||||||
there are details you're curious about, please feel free to ask
|
|
||||||
questions on the Zulip development mailing list (or if you think
|
|
||||||
you've found a security bug, please report it to
|
|
||||||
zulip-security@googlegroups.com so we can do a responsible security
|
|
||||||
announcement).
|
|
||||||
|
|
||||||
### Secure your Zulip server like your email server
|
|
||||||
|
|
||||||
* It's reasonable to think about security for a Zulip server like you
|
|
||||||
do security for a team email server -- only trusted administrators
|
|
||||||
within an organization should have shell access to the server.
|
|
||||||
|
|
||||||
In particular, anyone with root access to a Zulip application server
|
|
||||||
or Zulip database server, or with access to the `zulip` user on a
|
|
||||||
Zulip application server, has complete control over the Zulip
|
|
||||||
installation and all of its data (so they can read messages, modify
|
|
||||||
history, etc.). It would be difficult or impossible to avoid this,
|
|
||||||
because the server needs access to the data to support features
|
|
||||||
expected of a group chat system like the ability to search the
|
|
||||||
entire message history, and thus someone with control over the
|
|
||||||
server has access to that data as well.
|
|
||||||
|
|
||||||
### Encryption and Authentication
|
|
||||||
|
|
||||||
* Traffic between clients (web, desktop and mobile) and the Zulip is
|
|
||||||
encrypted using HTTPS. By default, all Zulip services talk to each
|
|
||||||
other either via a localhost connection or using an encrypted SSL
|
|
||||||
connection.
|
|
||||||
|
|
||||||
* The preferred way to login to Zulip is using an SSO solution like
|
|
||||||
Google Auth, LDAP, or similar. Zulip stores user passwords using
|
|
||||||
the standard PBKDF2 algorithm. Password strength is checked and
|
|
||||||
weak passwords are visually discouraged using the `zxcvbn` library,
|
|
||||||
but Zulip does not by default have strong requirements on user
|
|
||||||
password strength. Modify the settings to adjust the password
|
|
||||||
strength requirements (length and `zxcvbn` minimum quality).
|
|
||||||
|
|
||||||
* Zulip requires CSRF tokens in all interactions with the web API to
|
|
||||||
prevent CSRF attacks.
|
|
||||||
|
|
||||||
### Messages and History
|
|
||||||
|
|
||||||
* Zulip message content is rendered using a specialized Markdown
|
|
||||||
parser which escapes content to protect against cross-site scripting
|
|
||||||
attacks.
|
|
||||||
|
|
||||||
* Zulip supports both public streams and private ("invite-only")
|
|
||||||
streams. Any Zulip user can join any public stream in the realm,
|
|
||||||
and can view the complete message history of any public stream
|
|
||||||
without joining the stream.
|
|
||||||
|
|
||||||
* A private ("invite-only") stream is hidden from users who are not
|
|
||||||
subscribed to the stream. Users who are not members of a private
|
|
||||||
stream cannot read messages on the stream, send messages to the
|
|
||||||
stream, or join the stream, even if they are a Zulip realm
|
|
||||||
administrator. Users can join private streams only when they are
|
|
||||||
invited. However, any member of a private stream can invite other
|
|
||||||
users to the stream. When a new user joins a private stream, they
|
|
||||||
can see future messages sent to the stream, but they do not receive
|
|
||||||
access to the stream's message history.
|
|
||||||
|
|
||||||
* Zulip supports editing the content and topics of messages that have
|
|
||||||
already been sent. As a general philosophy, our policies provide
|
|
||||||
hard limits on the ways in which message content can be changed or
|
|
||||||
undone. In contrast, our policies around message topics favor
|
|
||||||
usefulness (e.g. for conversational organization) over faithfulness
|
|
||||||
to the original.
|
|
||||||
|
|
||||||
The message editing policy can be configured on the realm
|
|
||||||
administration page. There are three configurations provided out of
|
|
||||||
the box: (i) users cannot edit messages at all, (ii) users can edit
|
|
||||||
any message they have sent, and (iii) users can edit the content of
|
|
||||||
any message they have sent in the last N minutes, and the topic of
|
|
||||||
any message they have sent. In (ii) and (iii), topic edits can also
|
|
||||||
be propagated to other messages with the same original topic, even
|
|
||||||
if those messages were sent by other users. The default setting is
|
|
||||||
(iii), with N = 10.
|
|
||||||
|
|
||||||
In addition, and regardless of the configuration above, messages
|
|
||||||
with no topic can always be edited to have a topic, by anyone in the
|
|
||||||
organization, and the topic of any message can also always be edited
|
|
||||||
by a realm administrator.
|
|
||||||
|
|
||||||
Also note that while edited messages are synced immediately to open
|
|
||||||
browser windows, editing messages is not a safe way to redact secret
|
|
||||||
content (e.g. a password) shared unintentionally. Other users may
|
|
||||||
have seen and saved the content of the original message, or have an
|
|
||||||
integration (e.g. push notifications) forwarding all messages they
|
|
||||||
receive to another service. Zulip also stores and sends to clients
|
|
||||||
the content of every historical version of a message.
|
|
||||||
|
|
||||||
### Users and Bots
|
|
||||||
|
|
||||||
* There are three types of users in a Zulip realm: Administrators,
|
|
||||||
normal users, and bots. Administrators have the ability to
|
|
||||||
deactivate and reactivate other human and bot users, delete streams,
|
|
||||||
add/remove administrator privileges, as well as change configuration
|
|
||||||
for the overall realm (e.g. whether an invitation is required to
|
|
||||||
join the realm). Being a Zulip administrator does not provide the
|
|
||||||
ability to interact with other users' private messages or the
|
|
||||||
messages sent to private streams to which the administrator is not
|
|
||||||
subscribed. However, a Zulip administrator subscribed to a stream
|
|
||||||
can toggle whether that stream is public or private. Also, Zulip
|
|
||||||
realm administrators have administrative access to the API keys of
|
|
||||||
all bots in the realm, so a Zulip administrator may be able to
|
|
||||||
access messages sent to private streams that have bots subscribed,
|
|
||||||
by using the bot's credentials.
|
|
||||||
|
|
||||||
In the future, Zulip's security model may change to allow realm
|
|
||||||
administrators to access private messages (e.g. to support auditing
|
|
||||||
functionality).
|
|
||||||
|
|
||||||
* Every Zulip user has an API key, available on the settings page.
|
|
||||||
This API key can be used to do essentially everything the user can
|
|
||||||
do; for that reason, users should keep their API key safe. Users
|
|
||||||
can rotate their own API key if it is accidentally compromised.
|
|
||||||
|
|
||||||
* To properly remove a user's access to a Zulip team, it does not
|
|
||||||
suffice to change their password or deactivate their account in the
|
|
||||||
SSO system, since neither of those prevents authenticating with the
|
|
||||||
user's API key or those of bots the user has created. Instead, you
|
|
||||||
should deactivate the user's account in the Zulip administration
|
|
||||||
interface (`/#administration`); this will automatically also
|
|
||||||
deactivate any bots the user had created.
|
|
||||||
|
|
||||||
* The Zulip mobile apps authenticate to the server by sending the
|
|
||||||
user's password and retrieving the user's API key; the apps then use
|
|
||||||
the API key to authenticate all future interactions with the site.
|
|
||||||
Thus, if a user's phone is lost, in addition to changing passwords,
|
|
||||||
you should rotate the user's Zulip API key.
|
|
||||||
|
|
||||||
* Zulip bots are used for integrations. A Zulip bot can do everything
|
|
||||||
a normal user in the realm can do including reading other, with a
|
|
||||||
few exceptions (e.g. a bot cannot login to the web application or
|
|
||||||
create other bots). In particular, with the API key for a Zulip
|
|
||||||
bot, one can read any message sent to a public stream in that bot's
|
|
||||||
realm. A likely future feature for Zulip is [limited bots that can
|
|
||||||
only send messages](https://github.com/zulip/zulip/issues/373).
|
|
||||||
|
|
||||||
* Certain Zulip bots can be marked as "API super users"; these special
|
|
||||||
bots have the ability to send messages that appear to have been sent
|
|
||||||
by another user (an important feature for implementing integrations
|
|
||||||
like the Jabber, IRC, and Zephyr mirrors).
|
|
||||||
|
|
||||||
### User-uploaded content
|
|
||||||
|
|
||||||
* Zulip supports user-uploaded files; ideally they should be hosted
|
|
||||||
from a separate domain from the main Zulip server to protect against
|
|
||||||
various same-domain attacks (e.g. zulip-user-content.example.com)
|
|
||||||
using the S3 integration.
|
|
||||||
|
|
||||||
The URLs of user-uploaded files are secret; if you are using the
|
|
||||||
"local file upload" integration, anyone with the URL of an uploaded
|
|
||||||
file can access the file. This means the local uploads integration
|
|
||||||
is vulnerable to a subtle attack where if a user clicks on a link in
|
|
||||||
a secret .PDF or .HTML file that had been uploaded to Zulip, access
|
|
||||||
to the file might be leaked to the other server via the Referrer
|
|
||||||
header (see [the "Uploads world readable" issue on
|
|
||||||
GitHub](https://github.com/zulip/zulip/issues/320)).
|
|
||||||
|
|
||||||
The Zulip S3 file upload integration is relatively safe against that
|
|
||||||
attack, because the URLs of files presented to users don't host the
|
|
||||||
content. Instead, the S3 integration checks the user has a valid
|
|
||||||
Zulip session in the relevant realm, and if so then redirects the
|
|
||||||
browser to a one-time S3 URL that expires a short time later.
|
|
||||||
Keeping the URL secret is still important to avoid other users in
|
|
||||||
the Zulip realm from being able to access the file.
|
|
||||||
|
|
||||||
* Zulip supports using the Camo image proxy to proxy content like
|
|
||||||
inline image previews that can be inserted into the Zulip message
|
|
||||||
feed by other users over HTTPS.
|
|
||||||
|
|
||||||
* By default, Zulip will provide image previews inline in the body of
|
|
||||||
messages when a message contains a link to an image. You can
|
|
||||||
control this using the `INLINE_IMAGE_PREVIEW` setting.
|
|
||||||
|
|
||||||
### Final notes and security response
|
|
||||||
|
|
||||||
If you find some aspect of Zulip that seems inconsistent with this
|
|
||||||
security model, please report it to zulip-security@googlegroups.com so
|
|
||||||
that we can investigate and coordinate an appropriate security release
|
|
||||||
if needed.
|
|
||||||
|
|
||||||
Zulip security announcements will be sent to
|
|
||||||
zulip-announce@googlegroups.com, so you should subscribe if you are
|
|
||||||
running Zulip in production.
|
|
||||||
|
|
||||||
## Management commands
|
## Management commands
|
||||||
|
|
||||||
|
|||||||
194
docs/security-model.md
Normal file
194
docs/security-model.md
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# Security Model
|
||||||
|
|
||||||
|
This section attempts to document the Zulip security model. Since
|
||||||
|
this is new documentation, it likely does not cover every issue; if
|
||||||
|
there are details you're curious about, please feel free to ask
|
||||||
|
questions on the Zulip development mailing list (or if you think
|
||||||
|
you've found a security bug, please report it to
|
||||||
|
zulip-security@googlegroups.com so we can do a responsible security
|
||||||
|
announcement).
|
||||||
|
|
||||||
|
## Secure your Zulip server like your email server
|
||||||
|
|
||||||
|
* It's reasonable to think about security for a Zulip server like you
|
||||||
|
do security for a team email server -- only trusted administrators
|
||||||
|
within an organization should have shell access to the server.
|
||||||
|
|
||||||
|
In particular, anyone with root access to a Zulip application server
|
||||||
|
or Zulip database server, or with access to the `zulip` user on a
|
||||||
|
Zulip application server, has complete control over the Zulip
|
||||||
|
installation and all of its data (so they can read messages, modify
|
||||||
|
history, etc.). It would be difficult or impossible to avoid this,
|
||||||
|
because the server needs access to the data to support features
|
||||||
|
expected of a group chat system like the ability to search the
|
||||||
|
entire message history, and thus someone with control over the
|
||||||
|
server has access to that data as well.
|
||||||
|
|
||||||
|
## Encryption and Authentication
|
||||||
|
|
||||||
|
* Traffic between clients (web, desktop and mobile) and the Zulip is
|
||||||
|
encrypted using HTTPS. By default, all Zulip services talk to each
|
||||||
|
other either via a localhost connection or using an encrypted SSL
|
||||||
|
connection.
|
||||||
|
|
||||||
|
* The preferred way to login to Zulip is using an SSO solution like
|
||||||
|
Google Auth, LDAP, or similar. Zulip stores user passwords using
|
||||||
|
the standard PBKDF2 algorithm. Password strength is checked and
|
||||||
|
weak passwords are visually discouraged using the `zxcvbn` library,
|
||||||
|
but Zulip does not by default have strong requirements on user
|
||||||
|
password strength. Modify the settings to adjust the password
|
||||||
|
strength requirements (length and `zxcvbn` minimum quality).
|
||||||
|
|
||||||
|
* Zulip requires CSRF tokens in all interactions with the web API to
|
||||||
|
prevent CSRF attacks.
|
||||||
|
|
||||||
|
* See
|
||||||
|
[the authentication methods documentation](prod-authentication-methods.html)
|
||||||
|
for details on Zulip's available authentication methods.
|
||||||
|
|
||||||
|
## Messages and History
|
||||||
|
|
||||||
|
* Zulip message content is rendered using a specialized Markdown
|
||||||
|
parser which escapes content to protect against cross-site scripting
|
||||||
|
attacks.
|
||||||
|
|
||||||
|
* Zulip supports both public streams and private ("invite-only")
|
||||||
|
streams. Any Zulip user can join any public stream in the realm,
|
||||||
|
and can view the complete message history of any public stream
|
||||||
|
without joining the stream.
|
||||||
|
|
||||||
|
* A private ("invite-only") stream is hidden from users who are not
|
||||||
|
subscribed to the stream. Users who are not members of a private
|
||||||
|
stream cannot read messages on the stream, send messages to the
|
||||||
|
stream, or join the stream, even if they are a Zulip realm
|
||||||
|
administrator. Users can join private streams only when they are
|
||||||
|
invited. However, any member of a private stream can invite other
|
||||||
|
users to the stream. When a new user joins a private stream, they
|
||||||
|
can see future messages sent to the stream, but they do not receive
|
||||||
|
access to the stream's message history.
|
||||||
|
|
||||||
|
* Zulip supports editing the content and topics of messages that have
|
||||||
|
already been sent. As a general philosophy, our policies provide
|
||||||
|
hard limits on the ways in which message content can be changed or
|
||||||
|
undone. In contrast, our policies around message topics favor
|
||||||
|
usefulness (e.g. for conversational organization) over faithfulness
|
||||||
|
to the original.
|
||||||
|
|
||||||
|
The message editing policy can be configured on the realm
|
||||||
|
administration page. There are three configurations provided out of
|
||||||
|
the box: (i) users cannot edit messages at all, (ii) users can edit
|
||||||
|
any message they have sent, and (iii) users can edit the content of
|
||||||
|
any message they have sent in the last N minutes, and the topic of
|
||||||
|
any message they have sent. In (ii) and (iii), topic edits can also
|
||||||
|
be propagated to other messages with the same original topic, even
|
||||||
|
if those messages were sent by other users. The default setting is
|
||||||
|
(iii), with N = 10.
|
||||||
|
|
||||||
|
In addition, and regardless of the configuration above, messages
|
||||||
|
with no topic can always be edited to have a topic, by anyone in the
|
||||||
|
organization, and the topic of any message can also always be edited
|
||||||
|
by a realm administrator.
|
||||||
|
|
||||||
|
Also note that while edited messages are synced immediately to open
|
||||||
|
browser windows, editing messages is not a safe way to redact secret
|
||||||
|
content (e.g. a password) shared unintentionally. Other users may
|
||||||
|
have seen and saved the content of the original message, or have an
|
||||||
|
integration (e.g. push notifications) forwarding all messages they
|
||||||
|
receive to another service. Zulip also stores and sends to clients
|
||||||
|
the content of every historical version of a message.
|
||||||
|
|
||||||
|
## Users and Bots
|
||||||
|
|
||||||
|
* There are three types of users in a Zulip realm: Administrators,
|
||||||
|
normal users, and bots. Administrators have the ability to
|
||||||
|
deactivate and reactivate other human and bot users, delete streams,
|
||||||
|
add/remove administrator privileges, as well as change configuration
|
||||||
|
for the overall realm (e.g. whether an invitation is required to
|
||||||
|
join the realm). Being a Zulip administrator does not provide the
|
||||||
|
ability to interact with other users' private messages or the
|
||||||
|
messages sent to private streams to which the administrator is not
|
||||||
|
subscribed. However, a Zulip administrator subscribed to a stream
|
||||||
|
can toggle whether that stream is public or private. Also, Zulip
|
||||||
|
realm administrators have administrative access to the API keys of
|
||||||
|
all bots in the realm, so a Zulip administrator may be able to
|
||||||
|
access messages sent to private streams that have bots subscribed,
|
||||||
|
by using the bot's credentials.
|
||||||
|
|
||||||
|
In the future, Zulip's security model may change to allow realm
|
||||||
|
administrators to access private messages (e.g. to support auditing
|
||||||
|
functionality).
|
||||||
|
|
||||||
|
* Every Zulip user has an API key, available on the settings page.
|
||||||
|
This API key can be used to do essentially everything the user can
|
||||||
|
do; for that reason, users should keep their API key safe. Users
|
||||||
|
can rotate their own API key if it is accidentally compromised.
|
||||||
|
|
||||||
|
* To properly remove a user's access to a Zulip team, it does not
|
||||||
|
suffice to change their password or deactivate their account in the
|
||||||
|
SSO system, since neither of those prevents authenticating with the
|
||||||
|
user's API key or those of bots the user has created. Instead, you
|
||||||
|
should deactivate the user's account in the Zulip administration
|
||||||
|
interface (`/#administration`); this will automatically also
|
||||||
|
deactivate any bots the user had created.
|
||||||
|
|
||||||
|
* The Zulip mobile apps authenticate to the server by sending the
|
||||||
|
user's password and retrieving the user's API key; the apps then use
|
||||||
|
the API key to authenticate all future interactions with the site.
|
||||||
|
Thus, if a user's phone is lost, in addition to changing passwords,
|
||||||
|
you should rotate the user's Zulip API key.
|
||||||
|
|
||||||
|
* Zulip bots are used for integrations. A Zulip bot can do everything
|
||||||
|
a normal user in the realm can do including reading other, with a
|
||||||
|
few exceptions (e.g. a bot cannot login to the web application or
|
||||||
|
create other bots). In particular, with the API key for a Zulip
|
||||||
|
bot, one can read any message sent to a public stream in that bot's
|
||||||
|
realm. A likely future feature for Zulip is [limited bots that can
|
||||||
|
only send messages](https://github.com/zulip/zulip/issues/373).
|
||||||
|
|
||||||
|
* Certain Zulip bots can be marked as "API super users"; these special
|
||||||
|
bots have the ability to send messages that appear to have been sent
|
||||||
|
by another user (an important feature for implementing integrations
|
||||||
|
like the Jabber, IRC, and Zephyr mirrors).
|
||||||
|
|
||||||
|
## User-uploaded content
|
||||||
|
|
||||||
|
* Zulip supports user-uploaded files; ideally they should be hosted
|
||||||
|
from a separate domain from the main Zulip server to protect against
|
||||||
|
various same-domain attacks (e.g. zulip-user-content.example.com)
|
||||||
|
using the S3 integration.
|
||||||
|
|
||||||
|
The URLs of user-uploaded files are secret; if you are using the
|
||||||
|
"local file upload" integration, anyone with the URL of an uploaded
|
||||||
|
file can access the file. This means the local uploads integration
|
||||||
|
is vulnerable to a subtle attack where if a user clicks on a link in
|
||||||
|
a secret .PDF or .HTML file that had been uploaded to Zulip, access
|
||||||
|
to the file might be leaked to the other server via the Referrer
|
||||||
|
header (see [the "Uploads world readable" issue on
|
||||||
|
GitHub](https://github.com/zulip/zulip/issues/320)).
|
||||||
|
|
||||||
|
The Zulip S3 file upload integration is relatively safe against that
|
||||||
|
attack, because the URLs of files presented to users don't host the
|
||||||
|
content. Instead, the S3 integration checks the user has a valid
|
||||||
|
Zulip session in the relevant realm, and if so then redirects the
|
||||||
|
browser to a one-time S3 URL that expires a short time later.
|
||||||
|
Keeping the URL secret is still important to avoid other users in
|
||||||
|
the Zulip realm from being able to access the file.
|
||||||
|
|
||||||
|
* Zulip supports using the Camo image proxy to proxy content like
|
||||||
|
inline image previews that can be inserted into the Zulip message
|
||||||
|
feed by other users over HTTPS.
|
||||||
|
|
||||||
|
* By default, Zulip will provide image previews inline in the body of
|
||||||
|
messages when a message contains a link to an image. You can
|
||||||
|
control this using the `INLINE_IMAGE_PREVIEW` setting.
|
||||||
|
|
||||||
|
## Final notes and security response
|
||||||
|
|
||||||
|
If you find some aspect of Zulip that seems inconsistent with this
|
||||||
|
security model, please report it to zulip-security@googlegroups.com so
|
||||||
|
that we can investigate and coordinate an appropriate security release
|
||||||
|
if needed.
|
||||||
|
|
||||||
|
Zulip security announcements will be sent to
|
||||||
|
zulip-announce@googlegroups.com, so you should subscribe if you are
|
||||||
|
running Zulip in production.
|
||||||
Reference in New Issue
Block a user