1 SqWebMail security 2 3 This document discloses security-oriented issues regarding the SqWebMail 4 CGI application. 5 6 In this document: 7 8 * [1]User IDs and Passwords 9 * [2]Mailbox IDs 10 * [3]Authentication 11 * [4]Browser Security - History 12 * [5]Browser Security - Caching 13 * [6]Browser Security - HTML 14 * [7]Browser Security - Referer: Tags 15 * [8]Sending Mail 16 * [9]Setuid Root 17 18User IDs and Passwords 19 20 SqWebMail's security scheme requires a valid userid/password to access an 21 account. The actual method for validating the userid and password is a 22 black-box module that can be easily replaced. The example black-box 23 implementation uses the PAM library, if available, or with the 24 /etc/passwd, /etc/shadow and the crypt() function. 25 26 It is possible to configure SqWebMail to transmit the userid and password 27 via secure HTTP. If secure HTTP is not available, the userid and password 28 is transmitted over the network in the clear, which can be picked up by a 29 sniffer. 30 31Mailbox IDs 32 33 After a userid and password is authenticated, the authentication module 34 returns a 'mailboxid'. The mailboxid is used as a handle for the mailbox. 35 A mailboxid may not necessarily be the same as the userid, but the sample 36 authentication modules make them the same. 37 38 Technically, the mailboxid that's generated by recent versions of 39 sqwebmail are of the form "userid.method", where method represents the 40 authentication module that was used. 41 42 A mailboxid is sent with every HTTP request, in the request itself. Note 43 that the mailboxid is transmitted over the network in the clear. It is 44 also possible to use secure HTTP for the every HTTP request, not just 45 initial authentication, but this has not been tested. 46 47 Unless the mailboxid is the same as a userid, there aren't many security 48 considerations in having the mailboxid broadcasted over the network. 49 That's because the mailboxid in the HTTP request is usually validated 50 based on a time-limited IP address (see "[10]Authentication"). Note that 51 there certain other potential ways - in addition to network traffic 52 sniffing - for an unauthorized party to attempt to grab mailboxids. See 53 "[11]Browser Security - HTML", and "[12]Browser Security - Referrer: 54 Tags". 55 56Authentication 57 58 Once the user ID and password are authenticated, authentication for 59 subsequent HTTP requests is based on a combination of an IP address, plus 60 a 128-bit random number that was generated during the login. 61 62 By default, SqWebMail permits access to the mailbox only from the same IP 63 address as the one where the user ID and password was authenticated from. 64 This can be selectively turned off at login time, in cases where the 65 client is behind a load-balancing firewall that uses multiple IP 66 addresses. In all cases, a 128-bit random number must be transmitted with 67 every HTTP request, and it must match the number generated during the 68 login, which is saved in the Maildir directory. 69 70 The Maildir directory must therefore have any group or world access rights 71 disabled. Additionally, every page served by SqWebMail includes HTTP 72 headers containing instructions to proxies and browsers that prohibit this 73 page from being cached. There are some buggy web browsers out there - most 74 of them originating in Redmond,WA - that ignore these caching directives, 75 and they end up saving the 128-bit random number in the local cache. 76 Unless access to the physical machine is secured, the local cache can be 77 trawled to obtain the 128-bit authentication token. 78 79 However, access to the mailbox is allowed only for a maximum period of 80 time after the initial authentication. Access is allowed only if the HTTP 81 requests come within a different, shorter period of time. If no access 82 requests have been made for a certain period of time, access will no 83 longer be available even if it comes from the right IP address, with the 84 right authentication token. 85 86 The IP address of the initial authentication, the dates and times 87 involved, are all stored in files in the maildir directory, with group and 88 world permissions turned off. 89 90Browser Security - History 91 92 In certain situations a mailboxid is a part of the actual URL requested. A 93 browser may maintain a history file of visited URLs. 94 95 SqWebMail uses a frame window in an attempt to keep the browser from 96 recording visited URLs. This approach works for most popular web browsers 97 that support frames - these browsers do not maintain history for 98 individual frames. Note that frames are not required to access the full 99 SqWebMail functionality. 100 101Browser Security - Caching 102 103 SqWebMail sets the expiration header on every HTTP page it serves. 104 Individual pages contain URLs and hidden fields with mailboxids. The 105 expiration header should keep the web pages from being saved in the 106 browser cache. 107 108Browser Security - HTML 109 110 SqWebMail has the ability to display HTML E-mail, which leads to several 111 complicated situations regarding embedded Javascript or Java applets that 112 try to grab the mailboxid of the recipient (amongst other things). 113 SqWebMail attempts to remove all forms of scripting from HTML E-mail as 114 follows: 115 116 * The following HTML tags are removed: <SCRIPT>, </SCRIPT>, <APP>, 117 </APP>, <APPLET>, </APPLET>, <SERVER>, </SERVER>, <OBJECT>, </OBJECT>, 118 <HTML>, </HTML>, <HEAD>, </HEAD>, <BODY>, </BODY>, <META>, <TITLE>, 119 </TITLE>, <FRAME>, </FRAME>, <LINK>, <IFRAME> and </IFRAME>. 120 * The following HTML attributes are stripped from every tag: ONLOAD=, 121 ONMOUSEOVER=, and all ON*= attributes; BACKGROUND=, STYLE=, TARGET=, 122 CODE=, CODETYPE=, and LANGUAGE= are removed; TARGET=_blank is added to 123 all <A> tags. 124 * The HREF and SRC attributes are stripped, unless the URL starts with 125 one of the following: http:, https:, ftp:, gopher:, wais:, or telnet, 126 and cid:. 127 * The HREF and SRC attribute values are prefixed with a URL that will 128 resolve to SqWebMail, and with an additional TARGET="_blank" 129 attribute. A request to that resulting URL will result in a blank page 130 with a 0-second refresh to the original URL. This method strips 131 mailbox IDs from Referer: tags sent to external web site. If the HREF 132 attribute starts with a cid:, it is replaced by an http: reference to 133 SqWebMail that will return the specified MIME part. 134 * IMG tags are removed and replaced with an A tag, in order to keep the 135 HTTP client from automatically loading any images from external web 136 sites, upon opening a given message. 137 * Everything inside the STYLE tag is removed. 138 139Browser Security - Referer: Tags 140 141 See the previous section regarding how SqWebMail attempts to remove 142 mailbox IDs from Referer: tags. 143 144Sending Mail 145 146 SqWebMail includes the ability to send mail. Issues regarding transmitting 147 E-mail from the HTTP client to the server are obvious. SqWebMail runs a 148 wrapper shell script in order to send the E-mail message. The wrapper 149 shell script normally runs qmail-inject, sendmail, or something else, 150 immediately. SqWebMail prepares a complete E-mail message. 151 152 SqWebMail depends on the mail server to read the headers for recipients 153 and to strip out the Bcc: header. SqWebMail uses the black-box 154 authentication module to set the contents of the From: header and provide 155 the envelope return address. 156 157 The IP address of the HTTP client is not inserted into the headers, 158 however the wrapper and the mail server are invoked under the userid of an 159 authenticated user. The wrapper shell script can be modified to insert the 160 IP address, if so desired. The wrapper shell script has access to the CGI 161 REMOTE_ADDR environment variable. 162 163SqWebMail daemon 164 165 sqwebmaild is the meat of the code. It's a daemon process that runs as 166 root, and listens on a publicly-available UNIX domain socket. The tiny 167 sqwebmail CGI binary is a stub that connects to the daemon, forwards the 168 HTTP request, and passes along sqwebmaild output to the HTTP client. 169 170 sqwebmaild essentially receives a bunch of environment variables that 171 comprise the HTTP request. Anyone on the system may connect to 172 sqwebmaild's socket, and send it a bunch of environment variables, just 173 like anyone can connect to the server and send any HTTP request to it. 174 However, sqwebmaild places an upper limit on the size of the environment, 175 and will only accept the environment variables which are used in HTTP 176 request, discarding any environment variables that it does not recognize 177 (PATH, LD_LIBRARY_PATH, etc...). 178 179 When virtual mailboxes are being used, it is possible to run sqwebmaild 180 under the virtual userid, instead of root. Apart from the obvious changes, 181 the --with-cacheowner option must be used so that the login cache is owned 182 by the virtual userid also. 183 184 On some platforms this may not work without some additional tweaking. If 185 authenticating with sqwebmail setuided to the virtual userid doesn't work: 186 187 * Verify that the password has been correctly set. 188 * Remove the source file authlib/changeuidgid.c. Replace everything in 189 that file with the following three lines of code, exactly as shown: 190 191 void authchangegroup() {} 192 void authchangeuidgid() {} 193 void authchangeusername() {} 194 195 196 * Recompile and reinstall. 197 198 sqwebmaild takes the following action when it receives an HTTP request via 199 the local socket: 200 201 * Determine if the HTTP request is a request from a client that's 202 already logged in. The other possibilities are the login request 203 itself, or a couple of requests which are used to show the initial 204 login screen. This is determined by the presence of the extra path in 205 the HTTP request. This approach avoids the need to parse HTTP 206 arguments. If the extra path containing the login ID is present, the 207 login ID is extracted, SqWebMail changes to the account's Maildir 208 directory, and drops root privileges. The CGI environment is read, and 209 the request is authenticated (see [13]Authentication, above). 210 211 * If it's a login screen, the appropriate forms are generated. 212 213 * If it's a login request, SqWebMail makes sure that the request format 214 is NOT a multipart/formdata POST, which takes the most amount of code 215 to interpret. Additionally, requests indicating more than 128 bytes of 216 posted data are rejected prior to even parsing them. Barring all that, 217 the userid/password is fetched from the request, and processed. The 218 multipart/formdata check shouldn't be necessary given a 64 byte upper 219 limit on unauthenticated requests, but it can't hurt. 220 221References 222 223 Visible links 224 1. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#uidpass 225 2. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#mid 226 3. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#auth 227 4. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#history 228 5. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#caching 229 6. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#html 230 7. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#referral 231 8. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#sending 232 9. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#setuid 233 10. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#auth 234 11. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#html 235 12. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#referral 236 13. file:///home/mrsam/src/courier.git/sqwebmail/libs/sqwebmail/SECURITY.html#auth 237