Technical Structural Details
This section lists the name and purpose of each field in each database table.
Constituents of a Drop-off
Each dropoff (table name "dropoff") contains the following fields, some of which are obvious:
- This is referenced from several other tables and gives the unique
number of each complete dropoff.
- The random string given to the user that is used as their key for
- The 2nd random string given to the user, so that the details of the
dropoff can be sent by 2 different methods if required for security.
- The username of the dropoff creator.
- The full name of the dropoff creator.
- The email address of the dropoff creator. Used to optionally send
them an email notification when the dropoff has been picked up.
- Should an email notification be sent to the creator when a recipient
has picked up the dropoff.
- The IP address used by the dropoff creator. For logging purposes.
- The timestamp when the dropoff was created.
- The "short note" optionally attached to the dropoff.
There is a list of all the dropped off files (table name "file") currently in the store.
- Unique row number of each file.
- Reference to the rowID in the "dropoff" table.
- Internal random filename.
- Filename as displayed to user.
- Size of the file.
- Always application/octet-stream.
- Short descriptive text for the file added by the dropoff creator.
There is a list of all the pickups made by users (table "pickup"), so they can be shown to the dropoff creators.
- Reference to the rowID in the "dropoff" table.
- Username (if available) of the person who picked up the dropoff. Not available if that user did not log in.
- Email address of the person who picked up the dropoff.
- IP address of the person who picked up the dropoff. Used for logging purposes.
- The time when the picked up made.
Every recipient of every dropoff is stored in the table "recipient".
- Reference to the rowID in the "dropoff" table.
- The full name of the recipient.
- The email address of the recipient.
Sender Address Verification
This is done by giving each verified email address a token which they must pass back to ZendTo to prove they are the owner of the email address they are using. It is created when they have passed the CAPTCHA test and the verification email is about to be sent to them. These tokens expire and are also deleted immediately after use so that playback attacks are not possible.
The authentication tokens are held in the table "authtable".
- Random string generated as the token.
- Full name of the sender who is being verified, so that it can be passed to the "New Dropoff" form.
- Email address of the sender who is being verified, so that it can be passed to the "New Dropoff" form.
- Organisation name of the sender who is being verified, so that it can be passed to the "New Dropoff" form.
- The timestamp when the token expires. Usually set to a few hours after the creation time.
Requests for Dropoffs
When a sender has been requested to dropoff some files, that person circumvents the email address verification and CAPTCHA processes, as they are assumed to be friendly and known to the final recipient of the dropoff.
The token passed to them in the email message is constructed from 3 words, each of which is 3 or 4 letters long. This makes the token very easy to pass by phone if the recipient needs the files urgently and cannot wait for the email to the sender to reach them. The token can be entered by the sender straight into a web form, used to circumvent the address verification and CAPTCHA processes, and also to pre-populate the "New Dropoff" form as far as possible.
The data is stored in the table "reqtable". The tokens expire after a few hours, and are deleted immediately after use so that playback attacks are not possible.
- The 3-word token string.
- The full name of the sender of the resulting drop-off.
- The email address of the sender of the resulting drop-off.
- The organisation name of the sender of the resulting drop-off.
- The full name of the recipient of the resulting drop-off.
- The email address of the recipient of the resulting drop-off. This can be over-ridden by a configuration setting in "preferences.php", which is used to force the dropoffs to be sent to an automatic support ticketing system if required.
- The short note accompanying the email message to the drop-off sender and al accompanying the dropoff itself.
- The "Subject:" line of the email message sent to the sender of the resulting drop-off. This is also used in the Subject: line of the drop-off itself, and so can contain a ticket number which, in conjunction with the "DestEmail" over-ride, can be used to force the drop-off to be attached to the worklog of the correct ticket.
- Timestamp of when the request expires. Usually a few hours after its creation.
Local User Management
One of the available authenticators is "Local" which uses the table "usertable" to store the credentials and name of each user permitted to login to ZendTo. Note that the password itself is not stored, only a 1-way hash of the password that is sufficient to verify the login attempt, but cannot be decrypted back to the user's password.
Management of local users is done using the commands in /opt/zendto/bin.
- The 1 word username of the user.
- A 1-way hash of the user's password. It cannot be decrypted back into the user's password, only checked against the hash of the login attempt to verify that the 2 values match.
- The full email address of the user.
- The full name of the user.
- The organisation name of the user.
Login Attempt Checking
If a user tries to login unsuccessfully too many times in too short a time period, they are locked out completely for a length of time, configurable in "preferences.php". This defeats attempts to use ZendTo to guess users' passwords.
The data is stored in the table "loginlog" and just tracks how many times a user has failed to login consecutively, and what time the first unsuccessful attempt occurred. The records for a user are also deleted as soon as the lockout time has expired, thereby resetting the counter for the user.
- The username used in the unsuccessful login attempt.
- The timestamp when the unsuccessful attempt occurred.
There are 2 primary sources of log information in ZendTo. The first is the web server itself, which will naturally log all pages requested. The second is the ZendTo log, which is usually stored in /var/zendto/zendto.log. This log is not automatically rolled, but takes a very long time to become large. It can be rolled at any time, a replacement logfile will automatically be created by ZendTo.
The zendto.log logs all ZendTo operations, and all failures of any action by a user. It is a human-readable text file with a timestamp at the start of each line.
Dropoff Request Keys
The process by which a user is invited to upload a drop-off involves the creation of a string of 3 different words, each of which is 3 or 4 letters. As there are about 3000 such words in English, that gives the number of possible strings as roughly 3000^3 = 27,000,000,000.
The list of potential words is stored in /opt/zendto/lib/wordlist.php and has been checked briefly for rude or offensive words. However, if you find any more, please let me know so that I can remove them from the list! Any particular word will only occur in an average of 1 in every 1,000 requests, so it is not a huge problem.
ZendTo has been built from the ground up with security in mind, so that
it is not open to attack on its web interface. Here are some of the
measures taken as its defence:
- Users who cannot login (i.e. users who are not members of the host organisation) can only send files to people who are members of the host organisation. It cannot be used to send files from one non-member to another.
- All communication via the web can be done encrypted with SSL
- All authentication traffic between the ZendTo server and its authenticators can be encrypted with SSL
- If using SQL-based authentication, user passwords are not stored. Instead, a one-way hash of the passwords are stored which is sufficient to authenticate users
- All usernames entered are checked against a configurable regexp, eliminating LDAP injection attacks
- All email addresses entered are checked against a regexp, eliminating email routing attacks by methods such as a "%" in an address
- All values entered in any web form are encoded to handle non-alphabetic characters, eliminating SQL injection and HTML injection attacks
- All values entered in any web form are checked against configurable regexps, eliminating unknown attacks
- Being written in PHP, the vast majority of buffer over-run attacks are eliminated
- The users' filenames are never used directly in the filestore used to keep all the current files. They are all replaced with random strings, so browsing the filesystem will produce very little useful information to a user who gained access to the filesystem
- All activity is logged by both ZendTo and the web server
- All IP addresses involved in a dropoff or pickup are logged and sent to the user, making attack attempts traceable
- All email messages to users stress clearly that they must only follow the link in the message if they were expecting to receive it, and to ignore it completely if not
- Unauthenticated users must prove they are a human being and not a computer by passing a CAPTCHA test
- Unauthenticated users must prove they own the email address they are claiming to use, by having to present an authentication key sent to them by email
- All authentication tokens may only be used once, eliminating playback attacks
- All "Request for Dropoff" tokens may only be used once, eliminating playback attacks
- Repeated failed login attempts in a configurable time period cause that user to be locked out for a configurable time period, eliminating brute force password breaking attacks
- All uploaded files are scanned for viruses, and the whole drop-off is rejected if any file is found to be infected
- Failure of the virus scanner causes all drop-offs to be rejected eliminating attacks that attempt to bypass the virus scanner by breaking it