2019-03-22 11:03:55 +00:00
<!DOCTYPE html>
2019-03-23 02:41:12 +00:00
< html class = "theme-next gemini use-motion" lang = "zh-Hans" >
2019-03-22 11:03:55 +00:00
< head > < meta name = "generator" content = "Hexo 3.8.0" >
< meta charset = "UTF-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, maximum-scale=1" >
< meta name = "theme-color" content = "#222" >
< meta http-equiv = "Cache-Control" content = "no-transform" >
< meta http-equiv = "Cache-Control" content = "no-siteapp" >
< link href = "/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel = "stylesheet" type = "text/css" >
< link href = "/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel = "stylesheet" type = "text/css" >
< link href = "/css/main.css?v=5.1.4" rel = "stylesheet" type = "text/css" >
< link rel = "apple-touch-icon" sizes = "180x180" href = "/images/apple-touch-icon-next.png?v=5.1.4" >
2019-03-23 01:29:50 +00:00
< link rel = "icon" type = "image/png" sizes = "32x32" href = "/images/hackerrank.png?v=5.1.4" >
2019-03-22 11:03:55 +00:00
2019-03-23 01:29:50 +00:00
< link rel = "icon" type = "image/png" sizes = "16x16" href = "/images/hackerrank.png?v=5.1.4" >
2019-03-22 11:03:55 +00:00
< link rel = "mask-icon" href = "/images/logo.svg?v=5.1.4" color = "#222" >
< meta name = "keywords" content = "侧信道攻击,wifi," >
< meta name = "description" content = "TCP侧信道分析及利用的学习报告背景知识测信道香农信息论 什么是信息? 用来减少随机不确定的东西 什么是加密? 类似于加噪声,增加随机不确定性 “从密码分析者来看,一个保密系统几乎就是一个通信系统。待传的消息是统计事件,加密所用的密钥按概率选出,加密结果为密报,这是分析者可以利用的,类似于受扰信号。” 侧信道随之出现 越过加密算法增加的随机不定性,从其他的渠道获取数据标签,确定信息内容。" >
< meta name = "keywords" content = "侧信道攻击,wifi" >
< meta property = "og:type" content = "article" >
< meta property = "og:title" content = "wifi半双工侧信道攻击学习笔记" >
< meta property = "og:url" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/index.html" >
< meta property = "og:site_name" content = "混元霹雳手" >
< meta property = "og:description" content = "TCP侧信道分析及利用的学习报告背景知识测信道香农信息论 什么是信息? 用来减少随机不确定的东西 什么是加密? 类似于加噪声,增加随机不确定性 “从密码分析者来看,一个保密系统几乎就是一个通信系统。待传的消息是统计事件,加密所用的密钥按概率选出,加密结果为密报,这是分析者可以利用的,类似于受扰信号。” 侧信道随之出现 越过加密算法增加的随机不定性,从其他的渠道获取数据标签,确定信息内容。" >
< meta property = "og:locale" content = "zh-Hans" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/1.png" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/2-Man_in_the_middle_attack.svg.png" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/3-Connection_TCP.png" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/5-攻击模型.PNG" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/4-netstat获取信息.jpg" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/6-GRL-R.png" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/7-GRL-L.png" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/8-收包原理.jpg" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/8-noTrigger.PNG" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/8-trigger.PNG" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/9-序列号推断.PNG" >
< meta property = "og:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/9-http注入.PNG" >
< meta property = "og:updated_time" content = "2019-03-22T10:00:16.256Z" >
< meta name = "twitter:card" content = "summary" >
< meta name = "twitter:title" content = "wifi半双工侧信道攻击学习笔记" >
< meta name = "twitter:description" content = "TCP侧信道分析及利用的学习报告背景知识测信道香农信息论 什么是信息? 用来减少随机不确定的东西 什么是加密? 类似于加噪声,增加随机不确定性 “从密码分析者来看,一个保密系统几乎就是一个通信系统。待传的消息是统计事件,加密所用的密钥按概率选出,加密结果为密报,这是分析者可以利用的,类似于受扰信号。” 侧信道随之出现 越过加密算法增加的随机不定性,从其他的渠道获取数据标签,确定信息内容。" >
< meta name = "twitter:image" content = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/1.png" >
< script type = "text/javascript" id = "hexo.configurations" >
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
2019-03-23 02:41:12 +00:00
scheme: 'Gemini',
2019-03-22 11:03:55 +00:00
version: '5.1.4',
sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: true,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
< / script >
< link rel = "canonical" href = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/" >
< title > wifi半双工侧信道攻击学习笔记 | 混元霹雳手< / title >
< / head >
< body itemscope itemtype = "http://schema.org/WebPage" lang = "zh-Hans" >
< div class = "container sidebar-position-left page-post-detail" >
< div class = "headband" > < / div >
< header id = "header" class = "header" itemscope itemtype = "http://schema.org/WPHeader" >
< div class = "header-inner" > < div class = "site-brand-wrapper" >
< div class = "site-meta " >
< div class = "custom-logo-site-title" >
< a href = "/" class = "brand" rel = "start" >
< span class = "logo-line-before" > < i > < / i > < / span >
< span class = "site-title" > 混元霹雳手< / span >
< span class = "logo-line-after" > < i > < / i > < / span >
< / a >
< / div >
< p class = "site-subtitle" > < / p >
< / div >
< div class = "site-nav-toggle" >
< button >
< span class = "btn-bar" > < / span >
< span class = "btn-bar" > < / span >
< span class = "btn-bar" > < / span >
< / button >
< / div >
< / div >
< nav class = "site-nav" >
< ul id = "menu" class = "menu" >
< li class = "menu-item menu-item-home" >
< a href = "/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-home" > < / i > < br >
首页
< / a >
< / li >
< li class = "menu-item menu-item-about" >
< a href = "/about/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-user" > < / i > < br >
关于
< / a >
< / li >
< li class = "menu-item menu-item-tags" >
< a href = "/tags/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-tags" > < / i > < br >
标签
< / a >
< / li >
< li class = "menu-item menu-item-categories" >
< a href = "/categories/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-th" > < / i > < br >
分类
< / a >
< / li >
< li class = "menu-item menu-item-archives" >
< a href = "/archives/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-archive" > < / i > < br >
归档
< / a >
< / li >
2019-03-22 14:09:10 +00:00
< li class = "menu-item menu-item-search" >
< a href = "javascript:;" class = "popup-trigger" >
< i class = "menu-item-icon fa fa-search fa-fw" > < / i > < br >
搜索
< / a >
< / li >
2019-03-22 11:03:55 +00:00
< / ul >
2019-03-22 14:09:10 +00:00
< div class = "site-search" >
< div class = "popup search-popup local-search-popup" >
< div class = "local-search-header clearfix" >
< span class = "search-icon" >
< i class = "fa fa-search" > < / i >
< / span >
< span class = "popup-btn-close" >
< i class = "fa fa-times-circle" > < / i >
< / span >
< div class = "local-search-input-wrapper" >
< input autocomplete = "off" placeholder = "搜索..." spellcheck = "false" type = "text" id = "local-search-input" >
< / div >
< / div >
< div id = "local-search-result" > < / div >
< / div >
< / div >
2019-03-22 11:03:55 +00:00
< / nav >
< / div >
< / header >
< main id = "main" class = "main" >
< div class = "main-inner" >
< div class = "content-wrap" >
< div id = "content" class = "content" >
< div id = "posts" class = "posts-expand" >
< article class = "post post-type-normal" itemscope itemtype = "http://schema.org/Article" >
< div class = "post-block" >
< link itemprop = "mainEntityOfPage" href = "https://cool-y.github.io/2019/01/16/wifi半双工侧信道攻击学习笔记/" >
< span hidden itemprop = "author" itemscope itemtype = "http://schema.org/Person" >
< meta itemprop = "name" content = "Cool-Y" >
< meta itemprop = "description" content >
2019-03-22 13:49:21 +00:00
< meta itemprop = "image" content = "/images/avatar.png" >
2019-03-22 11:03:55 +00:00
< / span >
< span hidden itemprop = "publisher" itemscope itemtype = "http://schema.org/Organization" >
< meta itemprop = "name" content = "混元霹雳手" >
< / span >
< header class = "post-header" >
< h1 class = "post-title" itemprop = "name headline" > wifi半双工侧信道攻击学习笔记< / h1 >
< div class = "post-meta" >
< span class = "post-time" >
< span class = "post-meta-item-icon" >
< i class = "fa fa-calendar-o" > < / i >
< / span >
< span class = "post-meta-item-text" > 发表于< / span >
< time title = "创建于" itemprop = "dateCreated datePublished" datetime = "2019-01-16T15:35:27+08:00" >
2019-01-16
< / time >
< / span >
< span class = "post-category" >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-folder-o" > < / i >
< / span >
< span class = "post-meta-item-text" > 分类于< / span >
< span itemprop = "about" itemscope itemtype = "http://schema.org/Thing" >
< a href = "/categories/顶会论文/" itemprop = "url" rel = "index" >
< span itemprop = "name" > 顶会论文< / span >
< / a >
< / span >
< / span >
< span class = "post-comments-count" >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-comment-o" > < / i >
< / span >
< a href = "/2019/01/16/wifi半双工侧信道攻击学习笔记/#comments" itemprop = "discussionUrl" >
< span class = "post-comments-count gitment-comments-count" data-xid = "/2019/01/16/wifi半双工侧信道攻击学习笔记/" itemprop = "commentsCount" > < / span >
< / a >
< / span >
< span id = "/2019/01/16/wifi半双工侧信道攻击学习笔记/" class = "leancloud_visitors" data-flag-title = "wifi半双工侧信道攻击学习笔记" >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-eye" > < / i >
< / span >
< span class = "post-meta-item-text" > 阅读次数: < / span >
< span class = "leancloud-visitors-count" > < / span >
< / span >
2019-03-23 02:44:22 +00:00
< div class = "post-wordcount" >
< span class = "post-meta-item-icon" >
< i class = "fa fa-file-word-o" > < / i >
< / span >
< span title = "字数统计" >
2019-03-23 02:52:07 +00:00
3.7k 字
2019-03-23 02:44:22 +00:00
< / span >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-clock-o" > < / i >
< / span >
< span title = "阅读时长" >
2019-03-23 03:09:15 +00:00
12 分钟
2019-03-23 02:44:22 +00:00
< / span >
< / div >
2019-03-22 11:03:55 +00:00
< / div >
< / header >
< div class = "post-body" itemprop = "articleBody" >
< h1 id = "TCP侧信道分析及利用的学习报告" > < a href = "#TCP侧信道分析及利用的学习报告" class = "headerlink" title = "TCP侧信道分析及利用的学习报告" > < / a > TCP侧信道分析及利用的学习报告< / h1 > < h2 id = "背景知识" > < a href = "#背景知识" class = "headerlink" title = "背景知识" > < / a > 背景知识< / h2 > < h3 id = "测信道" > < a href = "#测信道" class = "headerlink" title = "测信道" > < / a > 测信道< / h3 > < p > < strong > 香农信息论< / strong > < / p >
< p > < img src = "./1.png" alt = "信息熵" > < / p >
< p > < strong > 什么是信息?< / strong > 用来减少随机不确定的东西< / p >
< p > < strong > 什么是加密?< / strong > 类似于加噪声,增加随机不确定性< / p >
< blockquote >
< p > “从密码分析者来看,一个保密系统几乎就是一个通信系统。待传的消息是统计事件,加密所用的密钥按概率选出,加密结果为密报,这是分析者可以利用的,类似于受扰信号。”< / p >
< / blockquote >
< p > < strong > 侧信道随之出现< / strong > 越过加密算法增加的随机不定性,从其他的渠道获取数据标签,确定信息内容。< / p >
< ol >
< li > 早期:采集加密电子设备在运行过程中的时间消耗、功率消耗或者电磁辐射消耗等边缘信息的差异性< / li >
< li > 而随着研究的深入, 逐渐从加密设备延伸到计算机内部CPU、内存等之间的信息传递< / li >
< li > 并在Web应用交互信息传递越来越频繁时, 延伸到了网络加密数据流的破解方面< / li >
< / ol >
< p > < strong > 侧信道攻击的流程< / strong > 第一个就是侧信道泄露的截取,第二个是信息的恢复。< / p >
< hr >
< h3 id = "网络攻击" > < a href = "#网络攻击" class = "headerlink" title = "网络攻击" > < / a > 网络攻击< / h3 > < ol >
< li > 中间人攻击< blockquote >
< p > “指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。”< / p >
< / blockquote >
< / li >
< / ol >
< p > < img src = "./2-Man_in_the_middle_attack.svg.png" alt > < / p >
< ul >
< li > 公共wifi、路由器劫持< / li >
< li > 一般使用加密来防御< / li >
< li > 加密的代价:维护密钥证书、影响功能(运营商无法做缓存)< / li >
< / ul >
< ol start = "2" >
< li > 非中间人攻击/偏离路径攻击/off-path attack< blockquote >
< p > 通信线路之外,攻击者看不到双方的消息,没办法截获和发送通信包。智能伪造成一方给另一方发消息。< / p >
< / blockquote >
< / li >
< / ol >
< ul >
< li > 攻击成功需要:消息合法+最先到达< / li >
< li > 防御措施: challenge-response/询问-应答机制< br > 双方在通信前交换一个随机数,这个随机数在每次的通信中都要被附带,而中间人看不见这个随机数,因此伪造的消息被认为不合法。< / li >
< li > 攻击者如何得到这个随机数:侧信道< / li >
< / ul >
< hr >
< h3 id = "TCP三次握手" > < a href = "#TCP三次握手" class = "headerlink" title = "TCP三次握手" > < / a > TCP三次握手< / h3 > < p > < img src = "./3-Connection_TCP.png" alt > < / p >
< blockquote >
< ol >
< li > 客户端通过向服务器端发送一个SYN来创建一个主动打开, 作为三路握手的一部分。客户端把这段连接的序号设定为< em > 随机数A< / em > 。< / li >
< li > 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK的确认码应为A+1, SYN/ACK包本身又有一个< em > 随机产生的序号B< / em > 。< / li >
< li > 最后, 客户端再发送一个ACK。当服务端收到这个ACK的时候, 就完成了三路握手, 并进入了连接创建状态。此时包的序号被设定为收到的确认号A+1, 而响应号则为B+1。< / li >
< / ol >
< / blockquote >
< p > 通过三次握手,确定对方不是非中间人< / p >
< p > < strong > < em > TCP序列号的问题< / em > < / strong > < / p >
< table >
< thead >
< tr >
< th style = "text-align:center" > 1985< / th >
< th style = "text-align:center" > 1995< / th >
< th style = "text-align:center" > 2001< / th >
< th style = "text-align:center" > 2004< / th >
< th style = "text-align:center" > 2007< / th >
< th style = "text-align:center" > 2012< / th >
< th style = "text-align:center" > 2012< / th >
< th style = "text-align:center" > 2016< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td style = "text-align:center" > Morris< / td >
< td style = "text-align:center" > Mitnik< / td >
< td style = "text-align:center" > Zalewsky< / td >
< td style = "text-align:center" > Waston< / td >
< td style = "text-align:center" > kLM< / td >
< td style = "text-align:center" > Herzberg< / td >
< td style = "text-align:center" > 作者< / td >
< td style = "text-align:center" > 作者< / td >
< / tr >
< tr >
< td style = "text-align:center" > 初始序列可预测< / td >
< td style = "text-align:center" > 真实利用< / td >
< td style = "text-align:center" > 漏洞仍在< / td >
< td style = "text-align:center" > BGP DoS< / td >
< td style = "text-align:center" > Windows攻击< / td >
< td style = "text-align:center" > Puppet-assisted< / td >
< td style = "text-align:center" > Malware-assisted< / td >
< td style = "text-align:center" > off-path attack< / td >
< / tr >
< / tbody >
< / table >
< ol >
< li > 90年代时发现并不随机: 1995年伪造客户端连接微软大楼的服务器< / li >
< li > 2007年在windows场景下用IDID侧信道猜出序列号: 只针对Windows, 花费几小时< / li >
< / ol >
< hr >
< h2 id = "Malware-assisted" > < a href = "#Malware-assisted" class = "headerlink" title = "Malware-assisted" > < / a > Malware-assisted< / h2 > < p > < strong > 攻击模型:< / strong > < br > 给受害者安装一个无特权的应用程序( 仅能网络连接) , 这个程序跟非中间人的攻击者里应外合, 劫持手机上所有的TCP连接。< br > < img src = "./5-攻击模型.PNG" alt > < / p >
< p > < strong > 如何劫持TCP< / strong > < / p >
< ol >
< li > < p > 需要的信息: Facebook的连接IP地址和端口号, 由此可以知道TCP连接的序列号, 利用序列号伪装成Facebook给手机发消息。< br > 使用netstat命令获取: < br > < img src = "./4-netstat获取信息.jpg" alt > < / p >
< / li >
< li > < p > 任务: 由于TCP的序列号通常连续, 所以要精确猜到它的下一个序列号。< / p >
< / li >
< li > 如何验证序列号正确:通过某种侧信道,这个恶意软件在后台可以提供反馈。< / li >
< / ol >
< h3 id = "变种一:防火墙" > < a href = "#变种一:防火墙" class = "headerlink" title = "变种一:防火墙" > < / a > 变种一:防火墙< / h3 > < p > < strong > 攻击过程:< / strong > TCP三次握手之后产生A和B, 将来传输的包序列号必须跟A和B很接近, 否则, 防火墙会丢弃这个包。因此只有猜对了序列号, 包才能到达手机端。到达手机端后, 后台的恶意软件可以帮助我们判断手机是否接受了这个数据包。< / p >
< p > < strong > 具体侧信道方案:< / strong > CPU资源使用率( 噪音很大) ——> TCP计数器( 后台软件运行制造噪音) ——> 低噪音计数器:包被丢掉时,一个相应的错误计数器。< / p >
< p > < strong > 解决方法:< / strong > 关闭防火墙检查序列号的功能< / p >
< h3 id = "变种二:无防火墙" > < a href = "#变种二:无防火墙" class = "headerlink" title = "变种二:无防火墙" > < / a > 变种二:无防火墙< / h3 > < p > 具体侧信道方案: 跟TCP业务逻辑有关的计数器——收到的TCP包序列号小于期望时增加, 大于时不变。二分查找搜索正确的序列号。< br > 影响范围: Android、Linux、MacOS、FreeBSD< / p >
< hr >
< h2 id = "Pure-off-path-无恶意软件协助" > < a href = "#Pure-off-path-无恶意软件协助" class = "headerlink" title = "Pure off-path:无恶意软件协助" > < / a > Pure off-path:无恶意软件协助< / h2 > < blockquote >
< p > 不植入恶意软件, 劫持任意两台机器的TCP连接: 首先确定是否建立TCP连接, 然后推测其序列号A和B。< / p >
< / blockquote >
< h3 id = "Global-Rate-Limit" > < a href = "#Global-Rate-Limit" class = "headerlink" title = "Global Rate Limit" > < / a > Global Rate Limit< / h3 > < blockquote >
< p > USENIX 2016 : Off-Path TCP Exploits: Global Rate Limit Considered Dangerous< / p >
< / blockquote >
< p > < strong > 侧信道:< / strong > 所有的侧信道, 本质上就是攻击者和受害者之间共享着某些资源, 如之前的全局TCP计数器。这里使用的侧信道是 < strong > < em > 服务器上< / em > < / strong > 的共享资源,< strong > < em > 限速器< / em > < / strong > ( RFC 5961) 限制某一种包的发送速率( 默认100p/s) < / p >
< p > < strong > 如何利用共享限速器:< / strong > < br > 先判断是否建立了连接。然后伪造TCP包, 需要猜测源端口, 如果猜测正确, 服务器会返回一个challenge, 攻击者不断触发, 一共可以收到99个( 还有一个发给了客户端) ; 如果猜测错误, 则一共可以收到100个challenge。< / p >
< p > < img src = "./6-GRL-R.png" alt > < / p >
< p > < img src = "./7-GRL-L.png" alt > < / p >
< p > < strong > 评估:< / strong > 是否建立了连接:< 10s ; Seq: 30s ; ACK:< 10s< / p >
< p > < strong > 解决方案:< / strong > 1. 加噪音, 100变成150、200; 2. 限速器做成局部的< / p >
< hr >
< h3 id = "Unfixable-WiFi-timing" > < a href = "#Unfixable-WiFi-timing" class = "headerlink" title = "Unfixable WiFi timing" > < / a > Unfixable WiFi timing< / h3 > < blockquote >
< p > USENIX 2018 : Off-Path TCP Exploit: How Wireless Routers< br > Can Jeopardize Your Secrets< br > 之前的漏洞无论是计数器还是限速器都属于软件,很好更正,但这篇文章的漏洞利用无法修复。< / p >
< / blockquote >
< p > < strong > TCP收包的原理: < / strong > 通常TCP收包要看这个包是否匹配了当前的某一个连接。如果连接匹配上了, 就会去看这个包的序列号; 如果序列号不对, 会触发一个回复, 说明这个序列号存在问题; 如果序列号正确, 但反向序列号不对, 也会丢包。当连接匹配、序列号和反向序列号正确时, 就会返回一个数据包。< br > < img src = "./8-收包原理.jpg" alt > < / p >
< p > < strong > 侧信道:< / strong > 攻击者伪装成服务器给客户端发包,正确的序列号会有< strong > < em > 回复< / em > < / strong > ,错误则没有。但回复时发送给服务器的,有没有回复攻击者并不知道。那么如何去判断有没有回复,利用无线网络的 < strong > < em > 半双工< / em > < / strong > 传输。< br > 让有回包和没有回包的时间差异放大。< / p >
< p > < strong > 判断流程:< / strong > 客户端和路由器之间wifi通信。攻击者依次发送三个数据包, 第一个包用来测试正常的RTT。第2个包是伪装成服务器发送的, 如果第2个包猜对了, 客户端会向服务器返回数据包, 这会导致占用更长时间的wifi信道, 从而会使第3个包的RTT更长。< br > < img src = "./8-noTrigger.PNG" alt > < / p >
< p > < img src = "./8-trigger.PNG" alt > < / p >
< p > < strong > 评估:< / strong > 在本地环境下, 如果发送40个包, 就有20ms的RTT差别。< / p >
< p > < strong > 攻击应用:< / strong > < br > < strong > 1. 攻击模型:< / strong > 受害者访问了我们的钓鱼网站, 这时javascript( 傀儡) 会在后台执行, 主动建立到攻击者的连接( 规避NAT或防火墙造成的不可抵达问题) , 这时攻击者就可以从外网测试RTT。< / p >
< blockquote >
< p > 与理想情况的不同: 客户端通常在NAT或防火墙之后; 操作系统不一定严格遵守TCP收包的原则< / p >
< / blockquote >
< pre > < code > Attacker -------wire----------|
Router ---------wireless-------Victim (client)
Server -------wire----------|
< / code > < / pre > < p > < strong > 2. 攻击目标:< / strong > 推断出客户端和服务器是否建立了连接; 合计连接中交换的字节数或强制中断连接; 注入恶意payload到连接( 不失一般性的关注web缓存投毒) 。前两个不需要傀儡初始化连接, 第三个不一定需要, 但攻击者控制了时序, 能够简化攻击。< / p >
< p > < strong > 3. 攻击过程:< / strong > 假设傀儡已经建立了连接, 攻击者可以劫持并替换任何不加密的网站( 如武汉大学) , 并在浏览器缓存。这是因为当浏览器请求相同的ip地址时, 会复用之前的TCP连接。这意味着恶意网站中的傀儡可以通过重复HTML元素来建立到目标域名的单个持久连接。然后, 路径外攻击者可以进行侧信道攻击, 以推断目标连接中使用的端口号和序列号, 然后注入虚假的http响应, 并要求浏览器不重新检查对象的新鲜度, 从而达到持续性的缓存投毒。< / p >
< p > < strong > 4. 细节:< / strong > < / p >
< ul >
< li > < strong > 连接(四元组)推断:< / strong > 每一轮使用30个重复包测试一个端口, 如果端口号正确, 就会发现RTT大幅增加。如果还要完成 < strong > < em > web缓存投毒< / em > < / strong > ,还需要傀儡初始化连接来协助,根据系统不同,有不同的端口选择算法可以优化:< strong > < em > windows& macOS< / em > < / strong > 使用全局和顺序端口分配策略为其TCP连接选择短暂的端口号, 这意味着攻击者可以在观察到与恶意Web服务器的初始连接后推断出要使用的下一个端口号, 这完全消除了对端口号推断的需要。< strong > < em > NAT< / em > < / strong > 端口保留,不需要关心外部端口被转换成不可预知的内部端口。< strong > < em > 来自同一域名的多个IP地址< / em > < / strong > ,这意味着攻击者需要付出更大的代价来推断端口号。< / li >
< li > < strong > 序列号推断:< / strong > 通过利用时序侧信道来判断是否存在相应的响应,从而将窗口序列号与窗外序列号区分开来。一旦我们得到一个 < strong > < em > 窗口内序列号< / em > < / strong > ,通过进行二分搜索进一步将序列号空间缩小到单个值 < strong > < em > RCV.NXT< / em > < / strong > 。如果还要使用傀儡建立的连接发起web缓存投毒, 可以进一步优化: < strong > < em > 增大接收窗口的大小< / em > < / strong > , 可以减少猜测的迭代次数, 通常可以放大到500000(之前是65535), 而且根据RFC793,窗口放大之后就永远不会缩小。< br > < img src = "./9-序列号推断.PNG" alt > < / li >
< li > < p > < strong > TCP劫持: < / strong > 通过劫持傀儡初始化的连接, 可以简化web缓存投毒的过程。三个os在ACK验证上都不符合规范, 所以各自处理情况也不同——< strong > < em > windows< / em > < / strong > : 客户端必须持续发送请求以防止ACK接收窗口仅为一个字节, 这要求攻击者必须能准确预期下一个序列号并解决大量流量带来的噪声。< br > 因此, 作者设计了一种新策略, 该策略利用处理重叠数据的TCP行为和处理损坏的HTTP响应的浏览器行为——在Windows主机上缓冲的攻击者注入数据可能会破坏来自服务器的真实HTTP响应。 < strong > < em > ( 1) 注入< / em > < / strong > , 傀儡不断从服务器上请求脚本, 而攻击者发送2^23/|wnd|个欺骗性数据包, 这些包的窗口序列号与RCV.NXT加上偏移量相匹配, 其中|wnd|为ack接收窗口大小, 第i个数据包的ACK号为i*|wnd|, payload为< / p >
< figure class = "highlight plain" > < table > < tr > < td class = "gutter" > < pre > < span class = "line" > 1< / span > < br > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > websocket.send(|wnd|*i)< / span > < br > < / pre > < / td > < / tr > < / table > < / figure >
< p > 因此, 这些数据包中包含有效ACK号的一个包将被缓冲, 并破坏真实的HTTP响应头。浏览器执行注入的脚本时, 它将通过websocket发送猜测的ACK号, 提供有效的窗口内ACK号。< br > < img src = "./9-http注入.PNG" alt > < br > < strong > < em > ( 2) 利用< / em > < / strong > , 由于客户端已经接受了额外的欺骗payload, 推进了其预期的序列号, 因此客户端和服务器实际上已经被去同步。攻击者现在可以简单地发送欺骗性响应( 知道预期的序列号和有效的ACK号) 。如果我们只想执行一次性注入, 只需用恶意脚本替换第一步中的payload就足够了。< br > 此外, 针对Windows的注入步骤存在更加通用的替代策略, 不依赖于浏览器行为。 具体来说, 由于HTTP响应的前几个字节是可预先确定的( 即HTTP) , 不破坏真实的响应, 而是覆盖标题和正文以形成合法但恶意的响应。 在这种情况下,浏览器将完全忘记注入的存在。 这表明一旦序列号泄露, 就存在各种方法来有效地将数据注入浏览器, 而不用进行基于时间信道的慢得多的ACK号推断。< / p >
< / li >
< / ul >
< hr >
< h2 id = "Discussion" > < a href = "#Discussion" class = "headerlink" title = "Discussion" > < / a > Discussion< / h2 > < p > 时序侧信道来自无线网络的半双工性质。由于无线协议中固有的冲突和回退, 它被进一步放大。正如我们的测试路由器所证实的那样, 现代无线路由器都支持CSMA / CA和RTS / CTS, 因为它是802.11标准的一部分,并且该原则不太可能很快改变。< br > 虽然作者只讨论威胁模型, 其中来自受害客户端的连接是针对性的, 但攻击实际上也适用于源自通过同一无线路由器连接的其他客户端的连接。这是因为所有这些客户端( 例如, 在相同NAT之后) 共享了相同的冲突域并因此遭受相同的定时信道。通过探测数据包在任何客户端上触发的响应将有效地延迟探测后查询。在这种情况下, 受害者连接( 通过傀儡打开) 只是为远程攻击者提供了测量碰撞的机会。< br > 此外, 我们可以扩展威胁模型以考虑无线连接的服务器, 例如物联网设备。已经证明, 通过公共IP地址和开放端口可以访问数百万个物联网设备。在这种情况下, 可以针对此类IoT设备上的连接启动完全偏离路径的攻击。例如, 计算在连接上交换的字节, 终止与另一主机的连接, 在正在进行的telnet连接上注入恶意命令。< / p >
< / div >
2019-03-22 12:33:24 +00:00
< div >
< div style = "padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;" >
< div > 您的支持将鼓励我继续创作!< / div >
< button id = "rewardButton" disable = "enable" onclick = "var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}" >
< span > 打赏< / span >
< / button >
< div id = "QR" style = "display: none;" >
< div id = "wechat" style = "display: inline-block" >
2019-03-22 13:20:22 +00:00
< img id = "wechat_qr" src = "/images/Wechatpay.png" alt = "Cool-Y 微信支付" >
2019-03-22 12:33:24 +00:00
< p > 微信支付< / p >
< / div >
< div id = "alipay" style = "display: inline-block" >
2019-03-22 13:25:11 +00:00
< img id = "alipay_qr" src = "/images/Alipay.png" alt = "Cool-Y 支付宝" >
2019-03-22 12:33:24 +00:00
< p > 支付宝< / p >
< / div >
< / div >
< / div >
< / div >
2019-03-22 11:03:55 +00:00
< footer class = "post-footer" >
< div class = "post-tags" >
< a href = "/tags/侧信道攻击/" rel = "tag" > # 侧信道攻击< / a >
< a href = "/tags/wifi/" rel = "tag" > # wifi< / a >
< / div >
< div class = "post-nav" >
< div class = "post-nav-next post-nav-item" >
< a href = "/2018/11/16/BIBA访问控制模型实现(python)/" rel = "next" title = "利用python实现BIBA模型" >
< i class = "fa fa-chevron-left" > < / i > 利用python实现BIBA模型
< / a >
< / div >
< span class = "post-nav-divider" > < / span >
< div class = "post-nav-prev post-nav-item" >
< a href = "/2019/02/22/qq数据库的加密解密/" rel = "prev" title = "QQ数据库的加密与解密" >
QQ数据库的加密与解密 < i class = "fa fa-chevron-right" > < / i >
< / a >
< / div >
< / div >
< / footer >
< / div >
< / article >
< div class = "post-spread" >
< / div >
< / div >
< / div >
< div class = "comments" id = "comments" >
< div id = "gitment-container" > < / div >
< / div >
< / div >
< div class = "sidebar-toggle" >
< div class = "sidebar-toggle-line-wrap" >
< span class = "sidebar-toggle-line sidebar-toggle-line-first" > < / span >
< span class = "sidebar-toggle-line sidebar-toggle-line-middle" > < / span >
< span class = "sidebar-toggle-line sidebar-toggle-line-last" > < / span >
< / div >
< / div >
< aside id = "sidebar" class = "sidebar" >
< div class = "sidebar-inner" >
< ul class = "sidebar-nav motion-element" >
< li class = "sidebar-nav-toc sidebar-nav-active" data-target = "post-toc-wrap" >
文章目录
< / li >
< li class = "sidebar-nav-overview" data-target = "site-overview-wrap" >
站点概览
< / li >
< / ul >
< section class = "site-overview-wrap sidebar-panel" >
< div class = "site-overview" >
< div class = "site-author motion-element" itemprop = "author" itemscope itemtype = "http://schema.org/Person" >
2019-03-22 13:49:21 +00:00
< img class = "site-author-image" itemprop = "image" src = "/images/avatar.png" alt = "Cool-Y" >
2019-03-22 11:03:55 +00:00
< p class = "site-author-name" itemprop = "name" > Cool-Y< / p >
< p class = "site-description motion-element" itemprop = "description" > < / p >
< / div >
< nav class = "site-state motion-element" >
< div class = "site-state-item site-state-posts" >
< a href = "/archives/" >
< span class = "site-state-item-count" > 5< / span >
< span class = "site-state-item-name" > 日志< / span >
< / a >
< / div >
< div class = "site-state-item site-state-categories" >
< a href = "/categories/index.html" >
< span class = "site-state-item-count" > 4< / span >
< span class = "site-state-item-name" > 分类< / span >
< / a >
< / div >
< div class = "site-state-item site-state-tags" >
< a href = "/tags/index.html" >
< span class = "site-state-item-count" > 11< / span >
< span class = "site-state-item-name" > 标签< / span >
< / a >
< / div >
< / nav >
2019-03-22 13:39:30 +00:00
< div class = "links-of-author motion-element" >
< span class = "links-of-author-item" >
2019-03-22 13:40:50 +00:00
< a href = "https://github.com/Cool-Y" target = "_blank" title = "GitHub" >
2019-03-22 13:39:30 +00:00
< i class = "fa fa-fw fa-github" > < / i > GitHub< / a >
< / span >
< span class = "links-of-author-item" >
< a href = "http://weibo.com/HanYanOpenFire" target = "_blank" title = "Weibo" >
< i class = "fa fa-fw fa-weibo" > < / i > Weibo< / a >
< / span >
< span class = "links-of-author-item" >
< a href = "mailto:cool.yim@whu.edu.cn" target = "_blank" title = "E-Mail" >
< i class = "fa fa-fw fa-envelope" > < / i > E-Mail< / a >
< / span >
< span class = "links-of-author-item" >
< a href = "https://www.instagram.com/yan__han/" target = "_blank" title = "Instagram" >
< i class = "fa fa-fw fa-instagram" > < / i > Instagram< / a >
< / span >
< / div >
2019-03-22 11:03:55 +00:00
< / div >
< / section >
<!-- noindex -->
< section class = "post-toc-wrap motion-element sidebar-panel sidebar-panel-active" >
< div class = "post-toc" >
< div class = "post-toc-content" > < ol class = "nav" > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#TCP侧信道分析及利用的学习报告" > < span class = "nav-number" > 1.< / span > < span class = "nav-text" > TCP侧信道分析及利用的学习报告< / span > < / a > < ol class = "nav-child" > < li class = "nav-item nav-level-2" > < a class = "nav-link" href = "#背景知识" > < span class = "nav-number" > 1.1.< / span > < span class = "nav-text" > 背景知识< / span > < / a > < ol class = "nav-child" > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#测信道" > < span class = "nav-number" > 1.1.1.< / span > < span class = "nav-text" > 测信道< / span > < / a > < / li > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#网络攻击" > < span class = "nav-number" > 1.1.2.< / span > < span class = "nav-text" > 网络攻击< / span > < / a > < / li > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#TCP三次握手" > < span class = "nav-number" > 1.1.3.< / span > < span class = "nav-text" > TCP三次握手< / span > < / a > < / li > < / ol > < / li > < li class = "nav-item nav-level-2" > < a class = "nav-link" href = "#Malware-assisted" > < span class = "nav-number" > 1.2.< / span > < span class = "nav-text" > Malware-assisted< / span > < / a > < ol class = "nav-child" > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#变种一:防火墙" > < span class = "nav-number" > 1.2.1.< / span > < span class = "nav-text" > 变种一:防火墙< / span > < / a > < / li > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#变种二:无防火墙" > < span class = "nav-number" > 1.2.2.< / span > < span class = "nav-text" > 变种二:无防火墙< / span > < / a > < / li > < / ol > < / li > < li class = "nav-item nav-level-2" > < a class = "nav-link" href = "#Pure-off-path-无恶意软件协助" > < span class = "nav-number" > 1.3.< / span > < span class = "nav-text" > Pure off-path:无恶意软件协助< / span > < / a > < ol class = "nav-child" > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#Global-Rate-Limit" > < span class = "nav-number" > 1.3.1.< / span > < span class = "nav-text" > Global Rate Limit< / span > < / a > < / li > < li class = "nav-item nav-level-3" > < a class = "nav-link" href = "#Unfixable-WiFi-timing" > < span class = "nav-number" > 1.3.2.< / span > < span class = "nav-text" > Unfixable WiFi timing< / span > < / a > < / li > < / ol > < / li > < li class = "nav-item nav-level-2" > < a class = "nav-link" href = "#Discussion" > < span class = "nav-number" > 1.4.< / span > < span class = "nav-text" > Discussion< / span > < / a > < / li > < / ol > < / li > < / ol > < / div >
< / div >
< / section >
<!-- /noindex -->
< / div >
< / aside >
< / div >
< / main >
< footer id = "footer" class = "footer" >
< div class = "footer-inner" >
< div class = "copyright" > © < span itemprop = "copyrightYear" > 2019< / span >
< span class = "with-love" >
< i class = "fa fa-user" > < / i >
< / span >
< span class = "author" itemprop = "copyrightHolder" > Cool-Y< / span >
2019-03-23 02:44:22 +00:00
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-area-chart" > < / i >
< / span >
2019-03-23 02:52:07 +00:00
< span title = "Site words total count" > 6.4k< / span >
2019-03-23 02:44:22 +00:00
2019-03-22 11:03:55 +00:00
< / div >
< div class = "powered-by" > 由 < a class = "theme-link" target = "_blank" href = "https://hexo.io" > Hexo< / a > 强力驱动< / div >
< span class = "post-meta-divider" > |< / span >
2019-03-23 02:41:12 +00:00
< div class = "theme-info" > 主题 — < a class = "theme-link" target = "_blank" href = "https://github.com/iissnan/hexo-theme-next" > NexT.Gemini< / a > v5.1.4< / div >
2019-03-22 11:03:55 +00:00
< / div >
< / footer >
< div class = "back-to-top" >
< i class = "fa fa-arrow-up" > < / i >
< / div >
< / div >
< script type = "text/javascript" >
if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
window.Promise = null;
}
< / script >
< script type = "text/javascript" src = "/lib/jquery/index.js?v=2.1.3" > < / script >
< script type = "text/javascript" src = "/lib/fastclick/lib/fastclick.min.js?v=1.0.6" > < / script >
< script type = "text/javascript" src = "/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7" > < / script >
< script type = "text/javascript" src = "/lib/velocity/velocity.min.js?v=1.2.1" > < / script >
< script type = "text/javascript" src = "/lib/velocity/velocity.ui.min.js?v=1.2.1" > < / script >
< script type = "text/javascript" src = "/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5" > < / script >
< script type = "text/javascript" src = "/js/src/utils.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/motion.js?v=5.1.4" > < / script >
2019-03-23 01:54:13 +00:00
< script type = "text/javascript" src = "/js/src/affix.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/schemes/pisces.js?v=5.1.4" > < / script >
2019-03-22 11:03:55 +00:00
< script type = "text/javascript" src = "/js/src/scrollspy.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/post-details.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/bootstrap.js?v=5.1.4" > < / script >
<!-- LOCAL: You can save these files to your site and update links -->
< link rel = "stylesheet" href = "https://aimingoo.github.io/gitmint/style/default.css" >
< script src = "https://aimingoo.github.io/gitmint/dist/gitmint.browser.js" > < / script >
<!-- END LOCAL -->
< script type = "text/javascript" >
function renderGitment(){
var gitment = new Gitmint({
id: window.location.pathname,
owner: 'Cool-Y',
repo: 'gitment-comments',
lang: "" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
oauth: {
client_secret: '1c5db4da72df5e6fc318d12afe5f4406f7c54343',
client_id: '180955a2c3ae3d966d9a'
}});
gitment.render('gitment-container');
}
renderGitment();
< / script >
2019-03-22 14:09:10 +00:00
< script type = "text/javascript" >
// Popup Window;
var isfetched = false;
var isXml = true;
// Search DB path;
var search_path = "search.xml";
if (search_path.length === 0) {
search_path = "search.xml";
} else if (/json$/i.test(search_path)) {
isXml = false;
}
var path = "/" + search_path;
// monitor main search box;
var onPopupClose = function (e) {
$('.popup').hide();
$('#local-search-input').val('');
$('.search-result-list').remove();
$('#no-result').remove();
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
}
function proceedsearch() {
$("body")
.append('< div class = "search-popup-overlay local-search-pop-overlay" > < / div > ')
.css('overflow', 'hidden');
$('.search-popup-overlay').click(onPopupClose);
$('.popup').toggle();
var $localSearchInput = $('#local-search-input');
$localSearchInput.attr("autocapitalize", "none");
$localSearchInput.attr("autocorrect", "off");
$localSearchInput.focus();
}
// search function;
var searchFunc = function(path, search_id, content_id) {
'use strict';
// start loading animation
$("body")
.append('< div class = "search-popup-overlay local-search-pop-overlay" > ' +
'< div id = "search-loading-icon" > ' +
'< i class = "fa fa-spinner fa-pulse fa-5x fa-fw" > < / i > ' +
'< / div > ' +
'< / div > ')
.css('overflow', 'hidden');
$("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');
$.ajax({
url: path,
dataType: isXml ? "xml" : "json",
async: true,
success: function(res) {
// get the contents from search data
isfetched = true;
$('.popup').detach().appendTo('.header-inner');
var datas = isXml ? $("entry", res).map(function() {
return {
title: $("title", this).text(),
content: $("content",this).text(),
url: $("url" , this).text()
};
}).get() : res;
var input = document.getElementById(search_id);
var resultContent = document.getElementById(content_id);
var inputEventFunction = function() {
var searchText = input.value.trim().toLowerCase();
var keywords = searchText.split(/[\s\-]+/);
if (keywords.length > 1) {
keywords.push(searchText);
}
var resultItems = [];
if (searchText.length > 0) {
// perform local searching
datas.forEach(function(data) {
var isMatch = false;
var hitCount = 0;
var searchTextCount = 0;
var title = data.title.trim();
var titleInLowerCase = title.toLowerCase();
var content = data.content.trim().replace(/< [^>]+>/g,"");
var contentInLowerCase = content.toLowerCase();
var articleUrl = decodeURIComponent(data.url);
var indexOfTitle = [];
var indexOfContent = [];
// only match articles with not empty titles
if(title != '') {
keywords.forEach(function(keyword) {
function getIndexByWord(word, text, caseSensitive) {
var wordLen = word.length;
if (wordLen === 0) {
return [];
}
var startPosition = 0, position = [], index = [];
if (!caseSensitive) {
text = text.toLowerCase();
word = word.toLowerCase();
}
while ((position = text.indexOf(word, startPosition)) > -1) {
index.push({position: position, word: word});
startPosition = position + wordLen;
}
return index;
}
indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
});
if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
isMatch = true;
hitCount = indexOfTitle.length + indexOfContent.length;
}
}
// show search results
if (isMatch) {
// sort index by position of keyword
[indexOfTitle, indexOfContent].forEach(function (index) {
index.sort(function (itemLeft, itemRight) {
if (itemRight.position !== itemLeft.position) {
return itemRight.position - itemLeft.position;
} else {
return itemLeft.word.length - itemRight.word.length;
}
});
});
// merge hits into slices
function mergeIntoSlice(text, start, end, index) {
var item = index[index.length - 1];
var position = item.position;
var word = item.word;
var hits = [];
var searchTextCountInSlice = 0;
while (position + word.length < = end & & index.length != 0) {
if (word === searchText) {
searchTextCountInSlice++;
}
hits.push({position: position, length: word.length});
var wordEnd = position + word.length;
// move to next position of hit
index.pop();
while (index.length != 0) {
item = index[index.length - 1];
position = item.position;
word = item.word;
if (wordEnd > position) {
index.pop();
} else {
break;
}
}
}
searchTextCount += searchTextCountInSlice;
return {
hits: hits,
start: start,
end: end,
searchTextCount: searchTextCountInSlice
};
}
var slicesOfTitle = [];
if (indexOfTitle.length != 0) {
slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
}
var slicesOfContent = [];
while (indexOfContent.length != 0) {
var item = indexOfContent[indexOfContent.length - 1];
var position = item.position;
var word = item.word;
// cut out 100 characters
var start = position - 20;
var end = position + 80;
if(start < 0 ) {
start = 0;
}
if (end < position + word . length ) {
end = position + word.length;
}
if(end > content.length){
end = content.length;
}
slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
}
// sort slices in content by search text's count and hits' count
slicesOfContent.sort(function (sliceLeft, sliceRight) {
if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
return sliceRight.searchTextCount - sliceLeft.searchTextCount;
} else if (sliceLeft.hits.length !== sliceRight.hits.length) {
return sliceRight.hits.length - sliceLeft.hits.length;
} else {
return sliceLeft.start - sliceRight.start;
}
});
// select top N slices in content
var upperBound = parseInt('1');
if (upperBound >= 0) {
slicesOfContent = slicesOfContent.slice(0, upperBound);
}
// highlight title and content
function highlightKeyword(text, slice) {
var result = '';
var prevEnd = slice.start;
slice.hits.forEach(function (hit) {
result += text.substring(prevEnd, hit.position);
var end = hit.position + hit.length;
result += '< b class = "search-keyword" > ' + text.substring(hit.position, end) + '< / b > ';
prevEnd = end;
});
result += text.substring(prevEnd, slice.end);
return result;
}
var resultItem = '';
if (slicesOfTitle.length != 0) {
resultItem += "< li > < a href = '" + articleUrl + "' class = 'search-result-title' > " + highlightKeyword(title, slicesOfTitle[0]) + "< / a > ";
} else {
resultItem += "< li > < a href = '" + articleUrl + "' class = 'search-result-title' > " + title + "< / a > ";
}
slicesOfContent.forEach(function (slice) {
resultItem += "< a href = '" + articleUrl + "' > " +
"< p class = \"search-result\" > " + highlightKeyword(content, slice) +
"...< / p > " + "< / a > ";
});
resultItem += "< / li > ";
resultItems.push({
item: resultItem,
searchTextCount: searchTextCount,
hitCount: hitCount,
id: resultItems.length
});
}
})
};
if (keywords.length === 1 & & keywords[0] === "") {
resultContent.innerHTML = '< div id = "no-result" > < i class = "fa fa-search fa-5x" / > < / div > '
} else if (resultItems.length === 0) {
resultContent.innerHTML = '< div id = "no-result" > < i class = "fa fa-frown-o fa-5x" / > < / div > '
} else {
resultItems.sort(function (resultLeft, resultRight) {
if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
return resultRight.searchTextCount - resultLeft.searchTextCount;
} else if (resultLeft.hitCount !== resultRight.hitCount) {
return resultRight.hitCount - resultLeft.hitCount;
} else {
return resultRight.id - resultLeft.id;
}
});
var searchResultList = '< ul class = \"search-result-list\" > ';
resultItems.forEach(function (result) {
searchResultList += result.item;
})
searchResultList += "< / ul > ";
resultContent.innerHTML = searchResultList;
}
}
if ('auto' === 'auto') {
input.addEventListener('input', inputEventFunction);
} else {
$('.search-icon').click(inputEventFunction);
input.addEventListener('keypress', function (event) {
if (event.keyCode === 13) {
inputEventFunction();
}
});
}
// remove loading animation
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
proceedsearch();
}
});
}
// handle and trigger popup window;
$('.popup-trigger').click(function(e) {
e.stopPropagation();
if (isfetched === false) {
searchFunc(path, 'local-search-input', 'local-search-result');
} else {
proceedsearch();
};
});
$('.popup-btn-close').click(onPopupClose);
$('.popup').click(function(e){
e.stopPropagation();
});
$(document).on('keyup', function (event) {
var shouldDismissSearchPopup = event.which === 27 & &
$('.search-popup').is(':visible');
if (shouldDismissSearchPopup) {
onPopupClose();
}
});
< / script >
2019-03-22 11:03:55 +00:00
< script src = "https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js" > < / script >
< script > AV . initialize ( "EWwoJgHNdlj6iBjiFlMcabUO-gzGzoHsz" , "x8FxDrYG79C8YFrTww9ljo8K" ) ; < / script >
< script >
function showTime(Counter) {
var query = new AV.Query(Counter);
var entries = [];
var $visitors = $(".leancloud_visitors");
$visitors.each(function () {
entries.push( $(this).attr("id").trim() );
});
query.containedIn('url', entries);
query.find()
.done(function (results) {
var COUNT_CONTAINER_REF = '.leancloud-visitors-count';
if (results.length === 0) {
$visitors.find(COUNT_CONTAINER_REF).text(0);
return;
}
for (var i = 0; i < results.length ; i + + ) {
var item = results[i];
var url = item.get('url');
var time = item.get('time');
var element = document.getElementById(url);
$(element).find(COUNT_CONTAINER_REF).text(time);
}
for(var i = 0; i < entries.length ; i + + ) {
var url = entries[i];
var element = document.getElementById(url);
var countSpan = $(element).find(COUNT_CONTAINER_REF);
if( countSpan.text() == '') {
countSpan.text(0);
}
}
})
.fail(function (object, error) {
console.log("Error: " + error.code + " " + error.message);
});
}
function addCount(Counter) {
var $visitors = $(".leancloud_visitors");
var url = $visitors.attr('id').trim();
var title = $visitors.attr('data-flag-title').trim();
var query = new AV.Query(Counter);
query.equalTo("url", url);
query.find({
success: function(results) {
if (results.length > 0) {
var counter = results[0];
counter.fetchWhenSave(true);
counter.increment("time");
counter.save(null, {
success: function(counter) {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(counter.get('time'));
},
error: function(counter, error) {
console.log('Failed to save Visitor num, with error message: ' + error.message);
}
});
} else {
var newcounter = new Counter();
/* Set ACL */
var acl = new AV.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
newcounter.setACL(acl);
/* End Set ACL */
newcounter.set("title", title);
newcounter.set("url", url);
newcounter.set("time", 1);
newcounter.save(null, {
success: function(newcounter) {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(newcounter.get('time'));
},
error: function(newcounter, error) {
console.log('Failed to create');
}
});
}
},
error: function(error) {
console.log('Error:' + error.code + " " + error.message);
}
});
}
$(function() {
var Counter = AV.Object.extend("Counter");
if ($('.leancloud_visitors').length == 1) {
addCount(Counter);
} else if ($('.post-title-link').length > 1) {
showTime(Counter);
}
});
< / script >
< / body >
< / html >