Technical Structural Details

Database Structure

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:

rowID
This is referenced from several other tables and gives the unique number of each complete dropoff.
claimID
The random string given to the user that is used as their key for each dropoff.
claimPasscode
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.
authorizedUser
The username of the dropoff creator.
senderName
The full name of the dropoff creator.
senderEmail
The email address of the dropoff creator. Used to optionally send them an email notification when the dropoff has been picked up.
confirmDelivery
Should an email notification be sent to the creator when a recipient has picked up the dropoff.
senderIP
The IP address used by the dropoff creator. For logging purposes.
created
The timestamp when the dropoff was created.
note
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.

rowID
Unique row number of each file.
dID
Reference to the rowID in the "dropoff" table.
tmpname
Internal random filename.
basename
Filename as displayed to user.
lengthInBytes
Size of the file.
mimeType
Always application/octet-stream.
description
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.

dID
Reference to the rowID in the "dropoff" table.
authorizedUser
Username (if available) of the person who picked up the dropoff. Not available if that user did not log in.
emailAddr
Email address of the person who picked up the dropoff.
recipientIP
IP address of the person who picked up the dropoff. Used for logging purposes.
pickupTimestamp
The time when the picked up made.

Every recipient of every dropoff is stored in the table "recipient".

dID
Reference to the rowID in the "dropoff" table.
recipName
The full name of the recipient.
recipEmail
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".

Auth
Random string generated as the token.
FullName
Full name of the sender who is being verified, so that it can be passed to the "New Dropoff" form.
Email
Email address of the sender who is being verified, so that it can be passed to the "New Dropoff" form.
Organization
Organisation name of the sender who is being verified, so that it can be passed to the "New Dropoff" form.
Expiry
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.

Auth
The 3-word token string.
SrcName
The full name of the sender of the resulting drop-off.
SrcEmail
The email address of the sender of the resulting drop-off.
SrcOrg
The organisation name of the sender of the resulting drop-off.
DestName
The full name of the recipient of the resulting drop-off.
DestEmail
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.
Note
The short note accompanying the email message to the drop-off sender and al accompanying the dropoff itself.
Subject
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.
Expiry
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.

username
The 1 word username of the user.
password
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.
mail
The full email address of the user.
displayname
The full name of the user.
organization
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.

username
The username used in the unsuccessful login attempt.
created
The timestamp when the unsuccessful attempt occurred.

Logging

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.

Security Defences

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