多列布局

rAF 实例

灵感来自于 Paul Lewis
的文章,我将用 requestAnimationFrame
控制 scroll 。

16ms 的 _.throttle 拿来做对比,性能相仿,用于更复杂的场景时,rAF
可能效果更佳。

See the Pen Scroll comparison requestAnimationFrame vs
throttle by Corbacho
(@dcorb) on CodePen.

headroom.js
是个更高级的例子。

背景

正如原文所描述的那样,CSS属性选择器开发者可以根据属性标签的值匹配子字符串来选择元素。
这些属性值选择器可以做以下操作:

  • 如果字符串以子字符串开头,则匹配
  • 如果字符串以子字符串结尾,则匹配
  • 如果字符串在任何地方包含子字符串,则匹配

属性选择器能让开发人员查询单个属性的页面HTML标记,并且匹配它们的值。一个实际的用例是将以“”开头的所有href属性变为某种特定的颜色。

而在实际环境中,一些敏感信息会被存放在HTML标签内。在大多数情况下CSRF
token都是以这种方式被存储的:即隐藏表单的属性值中。

这使得我们可以将CSS选择器与表单中的属性进行匹配,并根据表单是否与起始字符串匹配,加载一个外部资源,例如背景图片,来尝试猜测属性的起始字母。

通过这种方式,攻击者可以进行逐字猜解并最终获取到完整的敏感数值。

想要解决这个问题受害者可以在其服务器实施内容安全策略(CSP),防止攻击者从外部加载CSS代码。

居中布局

Debounce 实例

调整大小的例子

调整桌面浏览器窗口大小的时候,会触发很多次 resize 事件。 看下面 demo:

See the Pen Debounce Resize Event
Example by Corbacho
(@dcorb) on CodePen.

如你所见,我们为 resize 事件使用了默认的 trailing
选项,因为我们只关心用户停止调整大小后的最终值。

基于 AJAX 请求的自动完成功能,通过 keypress 触发

为什么用户还在输入的时候,每隔50ms就向服务器发送一次 AJAX
请求?_.debounce 可以帮忙,当用户停止输入的时候,再发送请求。

此处也不需要 leading 标记,我们想等最后一个字符输完。

See the Pen Debouncing keystrokes
Example by Corbacho
(@dcorb) on CodePen.

相似的使用场景还有,直到用户输完,才验证输入的正确性,显示错误信息。

利用CSS注入(无iFrames)窃取CSRF令牌

2018/03/05 · CSS ·
CSRF

原文出处:
FreeBuf.COM   

CSS相信大家不会陌生,在百度百科中它的解释是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。那么,它仅仅只是一种用来表示样式的语言吗?当然不是!其实早在几年前,CSS就已被安全研究人员运用于渗透测试当中。这里有一篇文章就为我们详细介绍了一种,使用属性选择器和iFrame,并通过CSS注入来窃取敏感数据的方法。但由于该方法需要iFrame,而大多数主流站点都不允许该操作,因此这种攻击方法并不实用。

这里我将为大家详细介绍一种不需要iframe且只需10秒,就能为我们有效地窃取CSRF
token的方法

一旦用户的CSRF
token被窃取,由于受害者已经在攻击者的网站上,因此攻击者可以继续攻击并完成对用户的CSRF攻击操作。

等分布局

图片 1

公式转化:

l = w * n + g * (n-1) -> l = w * n + g * n – g -> l + g = (w

  • g) * n

图片 2

因此,我们需要解决两个问题:

  • 如何让总宽度增加g(即:L+g)
  • 如何让每个宽包含g(即:w+g)

1)使用float
(1)原理、用法

  • 原理:增大父框的实际宽度后,使用CSS3属性box-sizing进行布局的辅助。
  • 用法:先将父框设置为margin-left: -*px,再设置子框float:
    left、width: 25%、padding-left、box-sizing: border-box。

(2)代码实例

JavaScript

<div class=”parent”> <div
class=”column”><p>1</p></div> <div
class=”column”><p>2</p></div> <div
class=”column”><p>3</p></div> <div
class=”column”><p>4</p></div> </div>

1
2
3
4
5
6
<div class="parent">
    <div class="column"><p>1</p></div>
    <div class="column"><p>2</p></div>
    <div class="column"><p>3</p></div>
    <div class="column"><p>4</p></div>
</div>

JavaScript

.parent{ margin-left: -20px;//l增加g } .column{ float: left; width: 25%;
padding-left: 20px; box-sizing: border-box;//包含padding区域 w+g }

1
2
3
4
5
6
7
8
9
.parent{
    margin-left: -20px;//l增加g
}
.column{
    float: left;
    width: 25%;
    padding-left: 20px;
    box-sizing: border-box;//包含padding区域 w+g
}

(3)优缺点

  • 优点:兼容性较好
  • 缺点:ie6 ie7百分比兼容存在一定问题

2)使用table
(1)原理、用法

  • 原理:通过增加一个父框的修正框,增大其宽度,并将父框转换为table,将子框转换为tabel-cell进行布局。
  • 用法:先将父框的修正框设置为margin-left: -*px,再设置父框display:
    table、width:100%、table-layout: fixed,设置子框display:
    table-cell、padding-left。

(2)代码实例

JavaScript

<div class=”parent-fix”> <div class=”parent”> <div
class=”column”><p>1</p></div> <div
class=”column”><p>2</p></div> <div
class=”column”><p>3</p></div> <div
class=”column”><p>4</p></div> </div>
</div>

1
2
3
4
5
6
7
8
<div class="parent-fix">
    <div class="parent">
        <div class="column"><p>1</p></div>
        <div class="column"><p>2</p></div>
        <div class="column"><p>3</p></div>
        <div class="column"><p>4</p></div>
    </div>
</div>

JavaScript

.parent-fix{ margin-left: -20px;//l+g } .parent{ display: table;
width:100%; table-layout: fixed; } .column{ display: table-cell;
padding-left: 20px;//w+g }

1
2
3
4
5
6
7
8
9
10
11
12
.parent-fix{
    margin-left: -20px;//l+g
}
.parent{
    display: table;
    width:100%;
    table-layout: fixed;
}
.column{
    display: table-cell;
    padding-left: 20px;//w+g
}

(3)优缺点

  • 优点:结构和块数无关联
  • 缺点:增加了一层

3)使用flex
(1)原理、用法

  • 原理:通过设置CSS3布局利器flex中的flex属性以达到等分布局。
  • 用法:将父框设置为display: flex,再设置子框flex:
    1,最后设置子框与子框的间距margin-left。

(2)代码实例

JavaScript

<div class=”parent”> <div
class=”column”><p>1</p></div> <div
class=”column”><p>2</p></div> <div
class=”column”><p>3</p></div> <div
class=”column”><p>4</p></div> </div>

1
2
3
4
5
6
<div class="parent">
    <div class="column"><p>1</p></div>
    <div class="column"><p>2</p></div>
    <div class="column"><p>3</p></div>
    <div class="column"><p>4</p></div>
</div>

JavaScript

.parent{ display: flex; } .column{ flex: 1; } .column+.column{
margin-left:20px; }

1
2
3
4
5
6
7
8
9
.parent{
    display: flex;
}
.column{
    flex: 1;
}
.column+.column{
    margin-left:20px;
}

(3)优缺点

  • 优点:代码量少,与块数无关
  • 缺点:兼容性存在一定问题

requestAnimationFrame(rAF)

requestAnimationFrame 是另一种限速执行的方式。

跟 _.throttle(dosomething, 16)
等价。它是高保真的,如果追求更好的精确度的话,可以用浏览器原生的 API 。

可以使用 rAF API 替换 throttle 方法,考虑一下优缺点:

优点

  • 动画保持 60fps(每一帧 16 ms),浏览器内部决定渲染的最佳时机
  • 简洁标准的 API,后期维护成本低

缺点

  • 动画的开始/取消需要开发者自己控制,不像 ‘.debounce’ 或
    ‘.throttle’由函数内部处理。
  • 浏览器标签未激活时,一切都不会执行。
  • 尽管所有的现代浏览器都支持
    rAF,IE9,Opera
    Mini 和 老的 Android
    还是需要打补丁。
  • Node.js 不支持,无法在服务器端用于文件系统事件。

根据经验,如果 JavaScript
方法需要绘制或者直接改变属性,我会选择 requestAnimationFrame,只要涉及到重新计算元素位置,就可以使用它。

涉及到 AJAX 请求,添加/移除 class (可以触发 CSS
动画),我会选择 _.debounce 或者 _.throttle
,可以设置更低的执行频率(例子中的200ms 换成16ms)。

无iFrames

要做到无iFrame,我将使用一种类似于之前我讨论过的方法:我将创建一个弹窗,然后在设置计时器后更改弹出窗口的位置。

使用这种方法,我仍然可以加载受害者的CSS,但我不再依赖于受害者是否允许iFrame。因为最初的弹出是通过用户事件触发的,所以我并没有被浏览器阻止。

为了强制重载,我在CSS注入间弹出一个虚拟窗口,如下:

JavaScript

var win2 = window.open(”, ‘f’,
“top=100000,left=100000,menubar=1,resizable=1,width=1,height=1”) var
win2 =
window.open(`,
‘f’, “top=100000,left=100000,menubar=1,resizable=1,width=1,height=1”)

1
2
var win2 = window.open(‘https://security.love/anything’, ‘f’, "top=100000,left=100000,menubar=1,resizable=1,width=1,height=1")
var win2 = window.open(`https://security.love/cssInjection/victim.html?injection=${css}`, ‘f’, "top=100000,left=100000,menubar=1,resizable=1,width=1,height=1")

两列定宽+一列自适应

(1)原理、用法

  • 原理:这种情况与两列定宽查不多。
  • 用法:先将左、中框设置为float:left、width、margin-right,再设置右框overflow:hidden。

(2)代码实例

JavaScript

<div class=”parent”> <div class=”left”>
<p>left</p> </div> <div class=”center”>
<p>center</p> </div> <div class=”right”>
<p>right</p> <p>right</p> </div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="center">
        <p>center</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

JavaScript

<div class=”parent”> <div class=”left”>
<p>left</p> </div> <div class=”center”>
<p>center</p> </div> <div class=”right”>
<p>right</p> <p>right</p> </div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="center">
        <p>center</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

 

实例解析防抖动和节流阀

2016/04/26 · JavaScript
· DOM

本文由 伯乐在线 –
涂鸦码龙
翻译。未经许可,禁止转载!
英文出处:css-tricks。欢迎加入翻译组。

防抖(Debounce)和节流(throttle)都是用来控制某个函数在一定时间内执行多少次的技巧,两者相似而又不同。

当我们给 DOM
绑定事件的时候,加了防抖和节流的函数变得特别有用。为什么呢?因为我们在事件和函数执行之间加了一个控制层。记住,我们是无法控制
DOM 事件触发频率的。

看下滚动事件的例子:

See the Pen Scroll events counter
by Corbacho (@dcorb) on
CodePen.

当使用触控板,滚动滚轮,或者拖拽滚动条的时候,一秒可以轻松触发30次事件。经我的测试,在智能手机上,慢慢滚动一下,一秒可以触发事件100次之多。这么高的执行频率,你的滚动回调函数压力大吗?

早在2011年,Twitter 网站抛出了一个问题:向下滚动 Twitter
信息流的时候,变得很慢,很迟钝。John Resig
发表了一篇博客解释这个问题,文中解释到直接给
scroll 事件关联昂贵的函数,是多么糟糕的主意。

John(5年前)建议的解决方案是,在 onScroll 事件外部,每 250ms
循环执行一次。简单的技巧,避免了影响用户体验。

现如今,有一些稍微高端的方式处理事件。我来结合用例介绍下
Debounce,Throttle 和 requestAnimationFrame 吧。

没有后端服务器

在CureSec的文章中描述了将数据传输到后端服务器,但由于CSRF是针对客户端的攻击,因此如果我们能想出一种不需要服务器的方法,那么就可以为我们节省大量的开销和简化我们的操作。

为了接收受害者客户端加载资源,我们可以利用Service
Workers来拦截和读取请求数据。Service
Workers目前只适用于同源请求,在我的演示中受害者和攻击者页面已处于同一源上。

不过不久后,chrome很可能会合并这个实验性的功能,允许Service
Workers拦截跨域请求。

这样,就可以确保我们在客户端的攻击100%的执行,并强制用户在10秒内点击链接执行CSRF攻击,演示如下:

全屏布局的特点

  • 滚动条不是全局滚动条,而是出现在内容区域里,往往是主内容区域
  • 浏览器变大时,撑满窗口

结论

使用 debounce,throttle 和 requestAnimationFrame
都可以优化事件处理,三者各不相同,又相辅相成。

总之:

  • debounce:把触发非常频繁的事件(比如按键)合并成一次执行。
  • throttle:保证每 X
    毫秒恒定的执行次数,比如每200ms检查下滚动位置,并触发 CSS 动画。
  • requestAnimationFrame:可替代 throttle
    ,函数需要重新计算和渲染屏幕上的元素时,想保证动画或变化的平滑性,可以用它。注意:IE9
    不支持。

打赏支持我翻译更多好文章,谢谢!

打赏译者

Demo

如上所述,因为我并不想运行一个web服务器,所以我使用service
workers拦截和模拟服务器端组件。目前,该演示只适用于Chrome浏览器。

首先,我创建了一个易受攻击的目标,它存在一个基于DOM的CSS注入漏洞,并在页面放置了一个敏感token。我还对脚本标签添加了一些保护措施,对左尖括号和右尖括号进行了编码。

<form action=”” id=”sensitiveForm”> <input
type=”hidden” id=”secret” name=”secret” value=”dJ7cwON4BMyQi3Nrq26i”>
</form> <script src=”mockingTheBackend.js”></script>
<script> var fragment =
decodeURIComponent(window.location.href.split(“?injection=”)[1]); var
htmlEncode = fragment.replace(/</g,”<“).replace(/>/g,”>”);
document.write(“<style>” + htmlEncode + “</style>”);
</script>

1
2
3
4
5
6
7
8
9
<form action="https://security.love" id="sensitiveForm">
    <input type="hidden" id="secret" name="secret" value="dJ7cwON4BMyQi3Nrq26i">
</form>
<script src="mockingTheBackend.js"></script>
<script>
    var fragment = decodeURIComponent(window.location.href.split("?injection=")[1]);
    var htmlEncode = fragment.replace(/</g,"&lt;").replace(/>/g,"&gt;");
    document.write("<style>" + htmlEncode + "</style>");
</script>

接下来,我们将强制加载受害者的CSS,并且使用上述方法,可一次窃取(猜解)一个敏感字符。

在接收端,我已经定义了一个拦截请求的service
worker,并通过post-message将它们发送回域,然后我们将token存储在本地存储中以供后续使用。你也可以想象一个后端Web服务器,通过Web套接字或轮询将CSRF
token回发给攻击者域。

目前该测试仅支持CHROME:

demo

如果你的浏览器支持的话,只需点击打开页面任意位置,你将看到CSRF
token将逐一被猜解出来。

不定宽+自适应

1)使用float+overflow
(1)原理、用法

  • 原理:这种情况与两列定宽查不多。
  • 用法:先将左框设置为float:left、margin-right,再设置右框overflow:
    hidden,最后设置左框中的内容width。

(2)代码实例

JavaScript

<div class=”parent”> <div class=”left”>
<p>left</p> </div> <div class=”right”>
<p>right</p> <p>right</p> </div>
</div>

1
2
3
4
5
6
7
8
9
<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

JavaScript

.left{ float: left; margin-right: 20px; } .right{ overflow: hidden; }
.left p{ width: 200px; }

1
2
3
4
5
6
7
8
9
10
.left{
        float: left;
        margin-right: 20px;
    }
.right{
    overflow: hidden;
}
.left p{
    width: 200px;
}

(3)优缺点

  • 优点:简单
  • 缺点:ie6下兼容性存在一定问题

2)使用table
(1)原理、用法

  • 原理:通过将父框改变为表格,将左右框转换为类似于同一行的td以达到多列布局,设置父框宽度100%,给左框子元素一个固定宽度从而达到自适应。
  • 用法:先将父框设置为display: table、width:
    100%,再设置左、右框display: table-cell,最后设置左框width:
    0.1%、padding-right以及左框中的内容width。

(2)代码实例

JavaScript

<div class=”parent”> <div class=”left”>
<p>left</p> </div> <div class=”right”>
<p>right</p> <p>right</p> </div>
</div>

1
2
3
4
5
6
7
8
9
<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

JavaScript

.parent{ display: table; width: 100%; } .left,.right{ display:
table-cell; } .left{ width: 0.1%; padding-right: 20px; } .left p{
width:200px; }

1
2
3
4
5
6
7
8
9
10
11
12
13
.parent{
    display: table; width: 100%;
    }
.left,.right{
    display: table-cell;
}
.left{
    width: 0.1%;
    padding-right: 20px;
}
.left p{
    width:200px;
}

(3)优缺点

  • 缺点:ie6 ie7不支持

3)使用flex
(1)原理、用法

  • 原理:通过设置CSS3布局利器flex中的flex属性以达到多列布局,加上给左框中的内容定宽、给右框设置flex达到不定款+自适应。
  • 用法:先将父框设置为display:flex,再设置右框flex:1,最后设置左框margin-right:20px、左框中的内容width。

(2)代码实例

JavaScript

<div class=”parent”> <div class=”left”>
<p>left</p> </div> <div class=”right”>
<p>right</p> <p>right</p> </div>
</div>

1
2
3
4
5
6
7
8
9
<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

JavaScript

.parent { display:flex; } .left { margin-right:20px; } .right { flex:1;
} .left p{ width: 200px; }

1
2
3
4
5
6
7
8
9
10
11
12
.parent {
    display:flex;
}
.left {
    margin-right:20px;
}
.right {
    flex:1;
}
.left p{
    width: 200px;
}

(3)优缺点

  • 优点:flex很强大
  • 缺点:兼容性存在一定问题,性能存在一定问题

如何使用 debounce 和 throttle 以及常见的坑 

自己造一个 debounce / throttle
的轮子看起来多么诱人,或者随便找个博文复制过来。我是建议直接使用
underscore 或 Lodash 。如果仅需要 _.debounce 和 _.throttle
方法,可以使用 Lodash 的自定义构建工具,生成一个 2KB
的压缩库。使用以下的简单命令即可:

Shell

npm i -g lodash-cli lodash-cli include=debounce,throttle

1
2
npm i -g lodash-cli
lodash-cli include=debounce,throttle

常见的坑是,不止一次地调用 _.debounce 方法:

JavaScript

// 错误 $(window).on(‘scroll’, function() { _.debounce(doSomething,
300); }); // 正确 $(window).on(‘scroll’, _.debounce(doSomething, 200));

1
2
3
4
5
6
7
8
9
10
11
// 错误
 
$(window).on(‘scroll’, function() {
 
   _.debounce(doSomething, 300);
 
});
 
// 正确
 
$(window).on(‘scroll’, _.debounce(doSomething, 200));

debounce
方法保存到一个变量以后,就可以用它的私有方法 debounced_version.cancel(),lodash
和 underscore.js 都有效。

JavaScript

var debounced_version = _.debounce(doSomething, 200);
$(window).on(‘scroll’, debounced_version); // 如果需要的话
debounced_version.cancel();

1
2
3
4
5
6
7
var debounced_version = _.debounce(doSomething, 200);
 
$(window).on(‘scroll’, debounced_version);
 
 
// 如果需要的话
debounced_version.cancel();

结语

有趣的是,反射型CSS注入实际上比存储型CSS注入更致命,因为存储型CSS注入需要一个服务器在受害者渲染之前来更新CSS。

一段时间以来,CSS注入在严重程度上来回变化。过去IE浏览器是允许用户在CSS中执行Javascript代码的。这个演示也从某种程度上表明了CSS注入,以及在你的域上渲染不受信任的CSS仍会导致严重的安全问题。

*参考来源:github,FB小编
secist 编译,转载请注明来自FreeBuf.COM

1 赞 收藏
评论

图片 3

发表评论

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