Digital Colony!

Masking Email Addresses in PHP

Steve Waag from Lacanche Ranges was able to translate the ASP in Masking Your Email Address to PHP.
<?php
function maskEmail($email) {
  $maskedEmail = '';
  for ($j = 0; $j < strlen($email); $j++) {
    $maskedEmail .= '&#' . ord(substr($email, $j, 1)) . ';' ;
  }
  $emailHtml = '<a href="m&#' . ord('a') . ';&#' . ord('i') . ';&#' . ord('l')
    . ';&#' . ord('t') . ';o:' . $maskedEmail . '">' . $maskedEmail . '</a>';
  return $emailHtml;
}
?>

<p>For more information email me at
  <?php echo maskEmail('someEmail@someDomain.net') ?>.</p>

Labels: , ,

 

Override ReturnURL in ASP.NET Security

When using FormsAuthentication and a logged out user tries to enter a secured page that page name is appended to the ReturnUrl. After the user has been authenticated, the user is redirected to that page.

I had no problem with this feature until I timed out and hit my LogOff page. I wasn't authenticated to see the LogOff page, so it appended that page URL to the ReturnURL and sent me the LogOn page. Once I logged in, it redirected me back to the LogOff page, which promptly logged me out.

I decided it would be easier to pick the start page for the user, regardless of what the ReturnUrl parameter was. Instead of using FormsAuthentication.RedirectFromLoginPage, use FormsAuthentication.SetAuthCookie and handle the Redirect yourself.
if (FormsAuthentication.Authenticate(txtName.Text, txtPassword.Text))
{
    FormsAuthentication.SetAuthCookie(txtName.Text, true);
    Response.Redirect("MySecuredStartPage.aspx", true);              
}

Labels: , ,

 

Masking Your Email Address

Some of you are probably aware of spiders. They are these little programs that surf the internet looking for data. Some spiders assist search engines in helping you find the web page you are looking for. Those are the good spiders. There also exists evil spiders. They jump from web page to web page looking for email addresses. Once they find one, they send it to a database so someone can send you junk email. Not cool.

Hiding In Plain Sight

What we need is a way to display an email address so the reader of a web page can communicate with the web site, yet we also need to hide the address from the spider. The reader and the spider are looking at the same web page but at differently levels. The reader is looking at the browser's rendering of HTML. The spider is looking at raw HTML. Three ideas come to mind: ASCII codes, server-side mail forms and images. ASCII codes and images will look like email addresses on the screen, but nothing like an email address in the source code of the HTML document.

Method 1: ASCII

In HTML when you place "&#" in front of the ASCII code of a character the browser will write the character not the ASCII code to the screen. And because this article is being viewed by a browser, the code shots are images. The download will have the source in a text format.

The function below accepts an email address as a parameter and returns a masked email address that is made up of ASCII codes. When the browser writes the codes to the screen it will get converted back to text. Although it's possible for a spider to read and convert ASCII codes inside the HTML source, it's probably not that prevalent. The function goes character by character converting the email address. The last step is to merge the masked email address with the HTML mailto: tag. In order to minimize the chances a clever spider might look for the mailto:, this example maskes that word as well.
Function maskEmail(email) 
   For j= 1 to Len(email) 
      maskEmail = maskEmail & "&#" & asc(Mid(email,j,1)) & ";" 
   Next 
   maskEmail = "<a href=""m&#" & asc("a") & ";&#" & asc("i") & ";&#" &_ 
     asc("l") & ";&#" & asc("t") & ";o:" & maskEmail & """>" & maskEmail & "</a>" 
End Function
Then you can call that VBScript function from inside an ASP page.
<p>For more information email me at <%= maskEmail("someEmail@someDomain.net") %>.</p>

Method 2: Server-side Mail Forms

These are the contact forms you see everywhere these days. The user fills out a form, clicks submit, and hopes it gets to somebody. This is great for the recipient, because their email address never appears on the site. However, some users don't trust filling out a form and will withhold feedback. Recently I was trying to open a new account with eFax.com. Their order entry page was down so I filled out a form alerting them to the problem. After detailing the problem the form rejected because I didn't already have an account with them. They didn't have a direct email address listed anywhere else, so I became a customer of one of their competitors.

Method 3: Images

I believe the ASCII method will work for a little while. Eventually as that trick becomes more popular, the spiders will get smarter. Who knows maybe the developer that writes the code for those evil little email spiders is reading this article right now. If we created an image with text of our email, the spiders would be truly be defeated. However creating an image for every email address in PhotoShop would be a hassle. And then what happens when we change fonts when the site gets redesigned? Creating the email images by hand isn't an option. We need to automate.

For this version I extended the ImageToText code sample at yyyZ.net.

Method 4: Chopped Javascript

Now that you have an email image or icon, you may want to assist the users so they click on an email address image it behaves as if it were a hypertext link. This means having their email client launched with the TO line filled out for them. In order for this to happen with the email image, we need to hack out a chopped Javascript function. There are many possible ways to write it. In this example I wrote a function that accepts an email address into 3 parts. It then reassembles the email and launches the email client. How you chop up the email address is up to you. Also feel free to change the sequence of the parameters.
<script language="JavaScript" type="text/javascript">  
function postage(one,two,three){ 
   window.location = 'mailto:'+one+two+three;} 
</script> 
<img src="123.jpg" alt="email" width="100" 
    height="40" border="0" 
    onmouseover="this.style.cursor='hand'" 
    onclick="postage('larryking@c','n','n.com');"/> 

Lab Demos

Mask Email Image Generator (Email Obfuscator)

Mask Email ASCII Generator

PHP Version of Masking Email Addresses

Labels: , , , ,

 

SQL Injection - Case Study

Well I got nailed today. My site INeedCoffee.com which is written using Classic ASP fell victim to a SQL Injection attack. The damage was limited to just one column in a table of nine rows.

Textbook SQL Injection Attack

Almost every example I've seen that explains SQL Injection shows how the WHERE clause is vulnerable to querystring manipulation.
sAuthorID = Request.QueryString("AuthorID")
sSQL = "SELECT firstName, lastName FROM Author WHERE authorID = " & sAuthorID

This query can be nailed with a single quote and an OR clause to dump the entire table to the screen. Adding 1' or '1'='1 to the querystring now yields this SQL.
SELECT firstName, lastName FROM Author WHERE authorID = 1 OR 1=1

Attacked Via a Column Sort

The attack I received came from appending additional SQL to ORDER BY clause. By clicking on the column header on the contributor page a column number is passed to the querystring. This was getting concatenated to a SQL statement.

EXAMPLE: http://ineedcoffee.com/by/michael_allen_smith/?s=1

The server-side ASP code looked like this:
sort = Request.QueryString("s")
If Len(sort) Then
    sSQL = sSQL & " ORDER BY " & sort
Else
    sSQL = sSQL & " ORDER BY C.Created DESC " 
End If

The hacker guessed the name of the table and one of the column names. From there it was an easy to hack together a querystring that looked like this:

http://ineedcoffee.com/by/michael_allen_smith/?s=1;UPDATE Section SET Name='hacked'

A simple semicolon followed by an UPDATE statement. This was just one column on a minor lookup table. I'm grateful that he/she didn't use the DROP TABLE command in the right sequence.

Locking It Down

Although ASP.NET has a nice feature to add parameters to dynamic SQL, Classic ASP is still best protected with stored procedures. Now the sort parameter goes into a stored procedure which can only perform SELECT. Prior to entering the stored procedure I'm now performing tests on length of the querystring (LEN) and determining if is an integer (IsNumeric).

Labels: , ,

 

Digital Colony Copyright © 1999-2008 XHTML   508
This site uses Blogger, which is not 100% XHTML compliant.
Try...Catch Disclaimer: For brevity many examples do not include error handling. That is your responsibility.