Search code examples
phphtmlspecialcharsstrip-tags

Should I echo User Submitted Links Here With strip_tags() or htmlspecialchars()?


Got to securely echo User submitted link on my page so that echoing the user's submitted url does not contain html or javascript that break-up the html of my page. By html breakup, I mean a malicious user adds html tags on the url submission input field (on my link submission webform) and his html input messes with the html on my page during outputting his url as a link on my page. Or user ads Javascipt that gives alert or redirects other visitors to phishing sites from my page. Got to prevent malicious users submitting urls that have parts like:

?search=<script>alert('hacked')</script>

Really got to prevent users doing things like these. Prevent them adding codes where when when my other visitors load my page or click the malicious user's submitted link, then they fail to trigger the malicious codes or fail to get redirected to malicious sites. I got two choices. Not sure which one is valid ... Which is the valid echo out of these two and which one should I stick to:

A.

//WHICH OF THE FOLLOWING TWO ECHOES IS BEST ?
//OPTION 1
echo 'Link: <a href=' .'"' .strip_tags($url) .'"' .'>' .'<b>' .strip_tags($url) .'</b>' .'</a>'; echo '<br>';

B.

//OPTION 2
echo 'Link: <a href=' .'"' .htmlspecialchars($url) .'"' .'>' .'<b>' .htmlspecialchars($url) .'</b>' .'</a>'; echo '<br>'; 

CONTEXT

$query = "SELECT id,date_and_time,domain,domain_email,ip,url,anchor,description,keyword From $table WHERE $column = ? LIMIT $offset,$max";
$stmt = mysqli_stmt_init($conn);
if(mysqli_stmt_prepare($stmt,$query))
{
    mysqli_stmt_bind_param($stmt,'s',$find);
    mysqli_stmt_execute($stmt);
    if($result = mysqli_stmt_get_result($stmt))
    {
        $columns = mysqli_fetch_array($result);
        
        $submission_id = $columns['id'];
        $submission_date_and_time = $columns['date_and_time'];
        $domain = $columns['domain'];
        $domain_email = $columns['email'];
        $ip = $columns['ip'];
        $url = $columns['url'];
        $anchor = $columns['anchor'];
        $description = $columns['description'];
        $keyword = $columns['keyword'];
        $keyphrase = $columns['keyphrase'];
            
        echo 'Submission Id: ' .$submission_id; echo '<br>';
        echo 'Submission Date And Time: ' .$submission_date_and_time; echo '<br>';
        echo 'Email: ' .$domain_email; echo '<br>';
        echo 'Domain: ' .$domain; echo '<br>';
        echo 'Url: ' .$url; echo '<br>';
        echo 'Anchor: ' .$anchor; echo '<br>';
        echo 'Description: ' .$description; echo '<br>';
        echo 'Keyword: ' .$keyword; echo '<br>';
        echo 'Keyphrase: ' .$keyword; echo '<br>';
        //WHICH OF THE FOLLOWING TWO ECHOES IS BEST ?
        //OPTION 1
        echo 'Link: <a href=' .'"' .strip_tags($url) .'"' .'>' .'<b>' .strip_tags($url) .'</b>' .'</a>'; echo '<br>';
        //OPTION 2
        echo 'Link: <a href=' .'"' .htmlspecialchars($url) .'"' .'>' .'<b>' .htmlspecialchars($url) .'</b>' .'</a>'; echo '<br>'; 
    }
    else
    {
        //Error Messages for Production Mode only.
        echo 'Record fetching failed!';
        echo 'Error: ' .mysqli_stmt_error($stmt);
        echo 'Error: ' .mysqli_stmt_errno($stmt);
    }
mysqli_stmt_close($stmt);
}
mysqli_close($conn);

Or, if you have better way of coding to securely output user submitted links then I'd like to see how you do it.


Solution

  • Always use htmlspecialchars() when outputting anything in HTML context. Just get into the habit of doing it for every string, no matter what it contains.

    As for strip_tags(), many people doubt its usefulness. It's just a dumb regex that removes information between < and >. It might protect you against some attacks, but it is definitely not a security measure. The effect might only be accidental. If you need to remove information between < and >, you are probably better off using plain regex, which might be faster and easier to implement.

    If the URL comes from user input, then that input needs to be validated to be a proper URL. PHP has a filter FILTER_VALIDATE_URL to validate URLs which can be used to reject invalid input.