<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>网络安全 &#8211; 寂静花园</title>
	<atom:link href="https://www.addesp.com/archives/tag/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/feed" rel="self" type="application/rss+xml" />
	<link>https://www.addesp.com</link>
	<description>寂静中交织着热情</description>
	<lastBuildDate>Sun, 22 Sep 2024 04:28:56 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>
	<item>
		<title>证书透明机制 — 防范证书签发机构作恶</title>
		<link>https://www.addesp.com/archives/5638</link>
					<comments>https://www.addesp.com/archives/5638#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Mon, 01 May 2023 06:36:26 +0000</pubDate>
				<category><![CDATA[科普]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=5638</guid>

					<description><![CDATA[原来就是你小子乱签证书？]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">写在前面</h2>



<p class="wp-block-paragraph"><a href="https://baike.baidu.com/item/公钥基础设施/10881894" target="_blank" rel="noopener nofollow" title="公钥基础设施（PKI）">公钥基础设施（PKI）</a>是当今互联网世界的安全基石，它可以帮助我们确认通信双方的身份，防止数据被窃听或篡改。</p>



<p class="wp-block-paragraph">简单回忆一下经典的互联网身份验证过程，浏览器向服务器请求网站的 HTTPS 证书，验证证书所代表的网站是否就是被访问的网站，如果不是则停止通信，以避免<a href="https://baike.baidu.com/item/中间人攻击/1739730" target="_blank" rel="noopener nofollow" title="">中间人攻击</a>。</p>



<p class="wp-block-paragraph">浏览器不仅要确定证书所代表的网站是否正确，也要确定证书本身是否是伪造的。所以浏览器会存储一些受信任的证书签发机构（CA），只要是他们签发的证书都被认为是可信的。</p>



<p class="wp-block-paragraph">不过 CA 并不总是可信的：</p>



<ul class="wp-block-list">
<li>CA 可能会出于某些原因签发用于攻击证书。</li>



<li>CA 被黑客控制，签发了用于攻击的证书。</li>



<li>CA 因为操作失误/系统故障等原因签发了错误的证书。</li>
</ul>



<p class="wp-block-paragraph">比如说如果我拿到了一个网站的证书，但这个网站并不属于我，我就可以窃听，篡改这个网站的通信。</p>



<p class="wp-block-paragraph">证书透明机制（<a href="https://certificate.transparency.dev/">Certificate Transparency</a>）即 <strong>CT</strong> 机制可以缓解这个问题。</p>



<h2 class="wp-block-heading">何为透明？</h2>



<p class="wp-block-paragraph">从上文来看，如果某个 CA 签发了不合规的证书，只要我们及时吊销它，就不会有被攻击的风险。所以问题的关键就是如何及时发现不合规的证书。</p>



<p class="wp-block-paragraph">证书透明机制维护了一个<strong>向所有人公开的日志数据库</strong>，所有加入到 CT 机制的 CA 签发的每一个证书都会被记录到这个数据库中。所以所谓透明就是把 CA 的签发所有证书都公开，这样一旦 CA 乱搞很快就会被发现。</p>



<h2 class="wp-block-heading">CT 机制下 CA 如何签发一张证书？</h2>



<ol class="wp-block-list">
<li>网站所有者向 CA 请求签发一张属于自己的证书。</li>



<li>CA 机构验证申请者的身份，并首先生成一张 “<strong>预证书”</strong>（precertificate），并将这张证书提交给 CT 数据库。下文将解释什么是预证书，以及为什么需要它。</li>



<li>CT 数据库接收到预证书后，立即将 “<strong>证书签名时间戳</strong>”（signed certificate timestamp）返回给 CA，并承诺预证书会在某个时间点之后被写入到 CT 数据库。这个时间戳会被 CT 签名，确保不给伪造。</li>



<li>CA 将这个时间戳写入证书中，签名，成为最终的证书。</li>



<li>将最终的证书返回给网站所有者。</li>
</ol>



<p class="wp-block-paragraph">我们首先来解释一下 “<strong>预证书</strong>”。</p>



<p class="wp-block-paragraph">CT 数据库需要知道证书的全部内容才能将其写入到数据库，CA 机构需要 “<strong>证书签名时间戳</strong>” 才能生成最终的证书。但是生成最终证书需要 CT 提供 “<strong>证书签名时间戳</strong>”，CT 又需要知道证书的全部内容才返回这个时间戳，</p>



<p class="wp-block-paragraph">“预证书” 可以解决这个问题，”预证书” 包含了最终证书的所有信息（除了 “证书签名时间戳”），同，时它被标记为不可用，不会被浏览器识别为有效的证书。</p>



<p class="wp-block-paragraph">由于 “预证书” 包含了最终证书几乎所有的信息，所以存储这张证书依然可以建立与最终证书对应关系。所以 CT 可以放心地将 “证书签名时间戳“ 返回给 CA，并由 CA 签发最终的证书。</p>



<p class="wp-block-paragraph">回到证书签发流程，我们会发现 CT 并不关心一张证书的签发是否合规，它只是如实地记录每一个被签发证书，以及签发这个证书 CA。</p>



<h2 class="wp-block-heading">CT 机制如何保证安全？</h2>



<p class="wp-block-paragraph">为了及时发现不合规的证书，就需要有人监视这个数据库的变动。</p>



<p class="wp-block-paragraph">利益相关方比如 Google，会监控数据库的变动，如果它发现有自己以外的 CA 签发了 Google 的证书，那么 Google 可以立即将这个发现公之于众，然后在自己的浏览器（Chrome）中吊销这个证书，鉴于 Chrome 的市场份额，这可以很大程度地保持安全。</p>



<p class="wp-block-paragraph">同时许多浏览器（Chrome，Safari 等）会强制证书加入 CT 机制，这些浏览器会验证 “<strong>证书签名时间戳</strong>” 是否来自受信任的 CT 数据库，如果不是则中断通信。</p>



<p class="wp-block-paragraph">你可能会疑惑为什么浏览器不直接去 CT 数据库查询对应的证书，一部分原因是这种做法等同于向 CT 数据库发送自己的浏览器历史记录。</p>



<h2 class="wp-block-heading">为什么 CA 和浏览器要参与到 CT 机制？</h2>



<p class="wp-block-paragraph">CT 机制是增强安全措施，如果 CA 拒绝加入会被公众怀疑你的证书是否合规，浏览器拒绝加入则会让用户怀疑使用你的浏览器是否安全。</p>



<p class="wp-block-paragraph">Google 是这项机制的重要推动者，如果 CA 不加入 CT，那么你签发的证书很可能不被市场份额极高的 Google Chrome 所信任。</p>



<h2 class="wp-block-heading">谁来确保 CT 不会作恶？</h2>



<p class="wp-block-paragraph">整个证书签发和写入数据库的流程都由密码学提供保证，任何人都不可能篡改已经写入数据库的信息。所以 CT 作恶的唯一方式就是照常签发 “证书签名时间戳”，但是不将证书写入数据库以避免来自外部的审查。</p>



<p class="wp-block-paragraph">所以要成为浏览器信任的 CT，需要满足一些条件，随便举几个例子。</p>



<ul class="wp-block-list">
<li>CT 能够在指定时间内将证书信息写入数据库。</li>



<li>CT 服务的停机时间不能超出某个时间范围。</li>



<li>······</li>
</ul>



<p class="wp-block-paragraph">每个浏览器的审核标准也不同，必须满足标准才会被浏览器信任。比如你可以<a href="https://github.com/GoogleChrome/CertificateTransparency" target="_blank" rel="noopener" title="查看 Google Chrome 的审核标准">查看 Google Chrome 的审核标准</a>。</p>



<h2 class="wp-block-heading">CT 和 CA 依然有机会作恶</h2>



<p class="wp-block-paragraph">是的，CT 机制并不能解决这个问题，但是它让这个问题<strong>变好了</strong>。</p>



<h2 class="wp-block-heading">参考资料</h2>



<ul class="wp-block-list">
<li><a href="https://certificate.transparency.dev" target="_blank" rel="noopener" title="">https://certificate.transparency.dev</a></li>



<li><a href="https://www.thesslstore.com/blog/ssl-precertificates/" target="_blank" rel="noopener" title="What are SSL Precertificates?">What are SSL Precertificates?</a></li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/5638/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Seafile 服务端加密缺陷分析</title>
		<link>https://www.addesp.com/archives/4654</link>
					<comments>https://www.addesp.com/archives/4654#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Tue, 08 Jun 2021 16:25:56 +0000</pubDate>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[Seafile]]></category>
		<category><![CDATA[已知明文攻击]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=4654</guid>

					<description><![CDATA[Seafile 的服务端加密功能存在缺陷，攻击者可以发起「已知明文攻击」。我翻了翻中文的搜索结果没有发现类似的文章，于是写下这篇文章提醒一下正在使用或者打算使用 Seafile 的用户。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">概述</h2>



<p class="wp-block-paragraph"><a href="https://www.seafile.com/en/home/" target="_blank" rel="noreferrer noopener nofollow" title="https://www.seafile.com/en/home/">Seafile</a> 是一个十分受欢迎的企业网盘，提供社区版供用户免费使用，也提供专业版供有更高需求的用户/企业使用。</p>



<p class="wp-block-paragraph">当你使用 Seafile 创建了一个加密存储库的时候这个库内的文件在服务端也会被加密，防止服务器管理员获取文件内容。</p>



<p class="wp-block-paragraph">不过这种加密存在缺陷，容易受到攻击。我翻了翻中文的搜索结果没有发现类似的文章，于是写下这篇文章提醒一下正在使用或者打算使用 Seafile 的用户。</p>



<p class="wp-block-paragraph">本文章完成时 Seafile 的最新版本为 8.0.5。</p>



<h2 class="wp-block-heading">攻击手段及后果</h2>



<p class="wp-block-paragraph">攻击者可以通过猜测某个加密库内的某个文件的内容来获取该库内的其它文件的部分或全部明文。因为目前 Seafile 并不加密一些元数据比如目录名和文件名，所以根据文件名进行猜测是有可能的。比如 python 源代码文件的开头大概率是 <code>import</code> 关键字。</p>



<h2 class="wp-block-heading">缺陷分析</h2>



<p class="wp-block-paragraph">我们<a href="https://manual.seafile.com/security/security_features/" target="_blank" rel="noreferrer noopener nofollow" title="https://manual.seafile.com/security/security_features/">打开英文版的官方文档</a>，看看 Seafile 的加密流程。</p>



<ol class="wp-block-list"><li>随机生成一个 32 Byte 的数字作为「文件密钥」。</li><li>通过用户为加密库指定的密码生成一个「派生密钥」和一个「初始化向量（IV）」，然后使用 AES-CBC 算法通过「派生密钥」和「初始化向量（IV）」加密「文件密钥」，得到被「被加密的文件密钥」。「被加密的文件密钥」会存储在服务端，解密时可以通过相同的方式计算出「派生密钥」和「初始化向量（IV）」用来解密「被加密的文件密钥」。</li><li>该加密库内的所有文件可以被「文件密钥」加密。</li></ol>



<p class="wp-block-paragraph">从上面过程中我们可以看出「派生密钥」和「初始化向量（IV）」从加密库创建时就被固定一下，并且不会变化，这实际上并不是正确的做法。因为按照 AES-CBC 的设计，不同的数据应该使用不同的且不可预测的「初始化向量（IV）」，否则就容易受到「已知明文攻击」。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>已知明文攻击：攻击者利用已知明文和对应的密文进行攻击。</p></blockquote>



<h2 class="wp-block-heading">为什么「初始化向量（IV）」不能重复使用？</h2>



<p class="wp-block-paragraph">引入「初始化向量（IV）」是为了解决同一段明文总会被加密成同一段密文这一缺陷，因为这种加密方式难以抵御统计分析，攻击者可以通过密文中某一片段的出现的频率、位置和时间等猜测对应的明文。比如某段密文总是出现双方首次通信，则这段密文对应的明文很可能是「你好」之类的问候语。</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="902" height="363" src="https://www.addesp.com/wp-content/uploads/2021/06/DD92B63D7B6CE580F39DB.webp" alt="" class="wp-image-4676"/><figcaption>AES-CBC 加密过程</figcaption></figure>



<p class="wp-block-paragraph">引入「初始化向量（IV）」后就会让相同的明文产生不同的密文，但是如果「初始化向量（IV）」不变，同一段明文还是会产生相同的密文，所以算法设计时就要求「初始化向量（IV）」必须不可预测并且仅使用一次并且不可预测，简单来说就是使用随机的数据作为「初始化向量（IV）」。</p>



<h2 class="wp-block-heading">参考资料</h2>



<ul class="wp-block-list"><li><a href="https://manual.seafile.com/security/security_features/" target="_blank" rel="noreferrer noopener nofollow" title="https://manual.seafile.com/security/security_features/">Security features &#8211; Seafile admin manual</a></li><li><a href="https://github.com/haiwen/seafile/issues/350" target="_blank" rel="noreferrer noopener nofollow" title="https://github.com/haiwen/seafile/issues/350">Encrypted libraries leak lots of information · Issue #350 · haiwen/seafile</a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/4654/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>从零设计通信协议（二）</title>
		<link>https://www.addesp.com/archives/4528</link>
					<comments>https://www.addesp.com/archives/4528#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Mon, 24 May 2021 13:21:42 +0000</pubDate>
				<category><![CDATA[从零设计通信协议]]></category>
		<category><![CDATA[唯密文攻击]]></category>
		<category><![CDATA[网络安全]]></category>
		<category><![CDATA[通信协议]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=4528</guid>

					<description><![CDATA[升级协议以抵御「唯密文攻击」。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">写在前面</h2>



<ul class="wp-block-list"><li>本系列的介绍以及协议功能见「<a href="https://www.addesp.com/archives/4463">从零设计通信协议（一）</a>」。</li><li>本系列的全部文章见「<a href="https://www.addesp.com/archives/category/%e7%ac%94%e8%ae%b0/%e4%bb%8e%e9%9b%b6%e8%ae%be%e8%ae%a1%e9%80%9a%e4%bf%a1%e5%8d%8f%e8%ae%ae">从零设计通信协议系列</a>」。</li></ul>



<h2 class="wp-block-heading">上一版协议</h2>



<p class="wp-block-paragraph">首先回顾的以下上一版的协议。</p>



<figure class="wp-block-table aligncenter is-style-regular"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-center" data-align="center">1 字节</th><th class="has-text-align-center" data-align="center">X 字节</th></tr></thead><tbody><tr><td class="has-text-align-center" data-align="center">数据长度</td><td class="has-text-align-center" data-align="center">数据</td></tr></tbody></table><figcaption>数据包格式</figcaption></figure>



<p class="wp-block-paragraph">整个数据包使用 AES-128-ECB 加密。</p>



<ul class="wp-block-list"><li>数据长度：表示「数据」的长度，单位为字节。</li><li>数据：表示具体的通信数据。</li></ul>



<p class="wp-block-paragraph">我们可以通过数据包的前一个字节获取数据长度，之后向后读取 X 字节即可获取全部的数据，整个数据包使用 AES-128-ECB 加密，看起来很安全。其实使用 AES-128-ECB 加密容易受到「唯密文攻击」。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>唯密文攻击：指在仅知道密文的情况加进行攻击，攻击成功轻则获得部分或全部明文，重则获取密钥。</p><cite><a href="https://baike.baidu.com/item/%E5%94%AF%E5%AF%86%E6%96%87%E6%94%BB%E5%87%BB" target="_blank" rel="noreferrer noopener" title="https://baike.baidu.com/item/%E5%94%AF%E5%AF%86%E6%96%87%E6%94%BB%E5%87%BB">唯密文攻击_百度百科</a></cite></blockquote>



<h2 class="wp-block-heading">ECB 模式的缺陷</h2>



<p class="wp-block-paragraph">ECB 模式的缺陷就是相同的明文会产生相同的密文，这会让攻击者有机会猜出密文的含义，难以抵抗统计分析。</p>



<p class="wp-block-paragraph">例如我和 Alice 对话，每次我发送的第一个信息是「你好」，假设使用 ECB 模式加密后的密文为「#￥%#￥」，那么如果 Eve 中间截获我的数据包，发现我和 Alice 每次通信我都会先发一个「#￥%#￥」给 Alice。根据日常的对话习惯，Eve 猜测这可能是在打招呼，进而怀疑「#￥%#￥」解密后是「你好」、「有空么」之类的话，这已经十分接近我们的明文信息了。</p>



<p class="wp-block-paragraph">上面的例子可能并不特别可怕，但是如果进行统计分析的话就难说了。</p>



<h2 class="wp-block-heading">CBC 模式</h2>



<p class="wp-block-paragraph">CBC 即密码分组链接（<strong>C</strong>ipher-<strong>B</strong>lock <strong>C</strong>haining），我们无需关心原理，只需要知道该模式通过一个随机的初始化向量 <strong>IV</strong> 保证了每条消息的唯一性，即相同的明文可以对应许多个密文。</p>



<h2 class="wp-block-heading">第二版协议</h2>



<p class="wp-block-paragraph">下面我们使用 AES-128-CBC 算法来加密我们的通讯信息，使用 CBC 模式加密不仅需要密钥，也需要一个随机的初始化向量 <strong>IV</strong>，所以我们需要将 <strong>IV</strong> 传递给对方。</p>



<figure class="wp-block-table is-style-regular"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-center" data-align="center">16 字节</th><th class="has-text-align-center" data-align="center">1 字节</th><th class="has-text-align-center" data-align="center">X 字节</th></tr></thead><tbody><tr><td class="has-text-align-center" data-align="center">IV</td><td class="has-text-align-center" data-align="center">数据长度</td><td class="has-text-align-center" data-align="center">数据</td></tr></tbody></table><figcaption>数据包格式</figcaption></figure>



<p class="wp-block-paragraph"><strong>数据包从第 17 个字节开始的所有数据要使用 AES-128-CBC 加密。</strong></p>



<ul class="wp-block-list"><li>IV：AES-128-CBC 加密时所用的初始化向量。</li><li>数据长度：表示「数据」的长度，单位为字节。</li><li>数据：表示具体的通信数据。</li></ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>初始化向量 <strong>IV</strong> 可以公开，但要保证不可预测。</p></blockquote>



<h2 class="wp-block-heading">写在最后</h2>



<p class="wp-block-paragraph">本次我们升级了协议，使得协议可以抵御「唯密文攻击」，本系列将会持续完善这一协议。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/4528/feed</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>从零设计通信协议（一）</title>
		<link>https://www.addesp.com/archives/4463</link>
					<comments>https://www.addesp.com/archives/4463#respond</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Mon, 24 May 2021 07:19:41 +0000</pubDate>
				<category><![CDATA[从零设计通信协议]]></category>
		<category><![CDATA[网络安全]]></category>
		<category><![CDATA[通信协议]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=4463</guid>

					<description><![CDATA[逐步完善一个玩具性质的应用层通信协议。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">写在前面</h2>



<p class="wp-block-paragraph">当你看到这个网页时你会知道 HTTPS 协议正在工作，你还知道这个协议能够抵御许多的网络攻击，保证通信安全。不过，我们知道的可能没有更多了。</p>



<p class="wp-block-paragraph">作为一个充满好奇心的沙雕，我希望自己搞一个玩具性质的应用层通信协议。所以本系列将会把我的设计过程记录在这里，本系列每次更新都会进行增强协议功能或修复安全性问题，你或许可以学习到一些知识，或许也可能找出我的一些错误。</p>



<h2 class="wp-block-heading">协议功能</h2>



<p class="wp-block-paragraph">为通信双方提供一个可靠的、有序的、安全的通信协议。要求通信双方预先共享足够强的密钥，并保证密钥不泄露。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>我们假装 TLS 不存在。</p></blockquote>



<h2 class="wp-block-heading">有序和可靠</h2>



<p class="wp-block-paragraph">既然是应用层协议，那么应用层以下的协议自然是随便选的。TCP 协议就可以保证数据传输的有序和可靠，所以本协议使用 TCP 作为底层传输协议。</p>



<h2 class="wp-block-heading">安全</h2>



<p class="wp-block-paragraph">什么是安全呢？我们就暂时定义为通信内容不被泄露和篡改吧。</p>



<h2 class="wp-block-heading">第一版协议</h2>



<p class="wp-block-paragraph">目前我们的协议很简单，再加上已经预先共享了密钥，所以就先不加上握手机制了。所以现在要做的就是选择加密算法，随便从网上找找，就用 AES-128-ECB 吧。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>AES-128-ECB：AES 表示高级加密标准（<strong>A</strong>dvanced <strong>E</strong>ncryption <strong>S</strong>tandard）；128 表示密钥长度为 128 bit；ECB 表示加密模式为电子密码本（<strong>E</strong>lectronic <strong>C</strong>ode<strong>B</strong>ook）。</p></blockquote>



<p class="wp-block-paragraph">选择好了加密算法，那么我们就开始设计我们数据包格式吧。</p>



<figure class="wp-block-table aligncenter is-style-regular"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-center" data-align="center">1 字节</th><th class="has-text-align-center" data-align="center">X 字节</th></tr></thead><tbody><tr><td class="has-text-align-center" data-align="center">数据长度</td><td class="has-text-align-center" data-align="center">数据</td></tr></tbody></table><figcaption>数据包格式</figcaption></figure>



<p class="wp-block-paragraph">整个数据包使用 AES-128-ECB 加密。</p>



<ul class="wp-block-list"><li>数据长度：表示「数据」的长度，单位为字节。</li><li>数据：表示具体的通信数据。</li></ul>



<p class="wp-block-paragraph">这样只要任何一方将上面的数据包正确解密就可以获取通信的内容，也可以按照此格式给对方发送信息。</p>



<h2 class="wp-block-heading">写在最后</h2>



<p class="wp-block-paragraph">协议十分简陋，但是已经算是一个雏形了，本系列将会持续完善这一协议。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/4463/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>nginx TLS 配置建议（Mozilla Recommendation）</title>
		<link>https://www.addesp.com/archives/4293</link>
					<comments>https://www.addesp.com/archives/4293#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Mon, 12 Apr 2021 16:01:20 +0000</pubDate>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=4293</guid>

					<description><![CDATA[本文主要按照 Mozilla 对于服务端 TLS 协议配置的建议来提供 nginx 的配置建议，按照这些建议进行配置可以让我们的站点更加安全。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">写在前面</h2>



<p class="wp-block-paragraph">本文主要按照 Mozilla 对于服务端 TLS 协议配置的建议来提供 nginx 的配置建议，按照这些建议进行配置可以让我们的站点更加安全。</p>



<h2 class="wp-block-heading">适用于个人站点的配置</h2>



<p class="wp-block-paragraph">如果你的站点无需向后兼容（老旧的浏览器、客户端和操作系统），那么这是整个建议中最安全的配置。所以十分适合个人站点，比如个人博客。</p>



<pre class="wp-block-code language-nginx"><code>server {
    ......
    # 启用 HSTS。
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
    # 仅启用 TLS 1.3 协议。
    ssl_protocols TLSv1.3;
    ssl_conf_command MinProtocol TLSv1.3;
    # 启用建议的加密套件，这些套件均支持前向安全性。
    ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
    # 启用建议的 ECC 曲线。
    ssl_ecdh_curve  X25519:prime256v1:secp384r1;
    ......
}</code></pre>



<h2 class="wp-block-heading">适用于绝大多数站点的配置</h2>



<p class="wp-block-paragraph">如果你需要兼容过去五年内发布的应用程序（如浏览器），下面是建议的配置。</p>



<pre class="wp-block-code language-nginx"><code>server {
    ......
    # 启用 HSTS。
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
    # 仅启用 TLS 1.2 和 TLS 1.3 协议。
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_conf_command MinProtocol TLSv1.2;
    # 启用建议的加密套件，这些套件均支持前向安全性。
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
    # 启用建议的 ECC 曲线。
    ssl_ecdh_curve  X25519:prime256v1:secp384r1;
    ......
}</code></pre>



<h2 class="wp-block-heading">升级你的 Openssl</h2>



<p class="wp-block-paragraph">请将你的 Openssl 升级到 1.1.1k 或以上的版本，之前的版本已经被爆出了两个漏洞，详见 <a href="https://www.openssl.org/news/secadv/20210325.txt" target="_blank" rel="noreferrer noopener" title="https://www.openssl.org/news/secadv/20210325.txt">OpenSSL Security Advisory [25 March 2021]</a>。一个漏洞可以进行 DoS 攻击，另一个则可以进行中间人攻击。</p>



<p class="wp-block-paragraph">你可以通过运行命令 <code>nginx -V</code> 来查看你的 nginx 编译时用的 openssl 的版本，或者运行时使用的版本。你应该能看到下面这行，请保证运行时所使用 openssl 的版本在 1.1.1k 及以上，如果没有括号里的内容请确保编译时所使用的 openssl 的版本在 1.1.1k 及以上</p>



<pre class="wp-block-preformatted">built with OpenSSL 1.1.1i  8 Dec 2020 (running with OpenSSL 1.1.1k  25 Mar 2021)</pre>



<h2 class="wp-block-heading">前向安全性</h2>



<p class="wp-block-paragraph">简单来说如果某一天你的服务器上的证书私钥泄露了，你之前的通信也无法被解密，你需要做的只是换一个证书而已。</p>



<h2 class="wp-block-heading">参考资料</h2>



<ul class="wp-block-list"><li><a href="https://wiki.mozilla.org/Security/Server_Side_TLS" target="_blank" rel="noreferrer noopener" title="https://wiki.mozilla.org/Security/Server_Side_TLS">Security/Server Side TLS &#8211; MozillaWiki</a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/4293/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>BGP 劫持 — 连 IP 都是假的</title>
		<link>https://www.addesp.com/archives/4225</link>
					<comments>https://www.addesp.com/archives/4225#respond</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Fri, 09 Apr 2021 08:10:29 +0000</pubDate>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=4225</guid>

					<description><![CDATA[听说你喜欢 ping ？]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">写在前面</h2>



<p class="wp-block-paragraph">当你打不开某个网站的时候你会怎么办？</p>



<p class="wp-block-paragraph">你可能会先 ping 一下域名看一下延迟。如果延迟正常的话你大概会检查一下自己的 DNS 解析结果是否正确。如果 DNS 解析也是正确的你大概会怀疑网站本身出了问题。但是你老家的亲戚能打开你却打不开，这是怎么回事呢？</p>



<p class="wp-block-paragraph">这种情况下你可能遇到了「BGP 劫持」，它可以将你的通信劫持到指定主机上，并且 IP 地址不发生变化。</p>



<h2 class="wp-block-heading">什么是 BGP ?</h2>



<p class="wp-block-paragraph">BGP（Border Gateway Protocol），即边界网关协议，用于各个 AS（自治系统）之间互相交换路由信息。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>自治系统（AS）：可以简单地理解为一个或多个网络管理员管理的网络区域，比如一块属于某个 ISP 的网络，某个学校的网络，你自己在家里建立一个局域网也可以理解为自治系统。</p></blockquote>



<p class="wp-block-paragraph">一般来说路由器可以通过 RIP 或 OSPF 协议来互相交换路由信息，但是这通常只能用于不那么大的网络。如果网络太大，比如国与国之间，那么 RIP 和 OSPF 协议就力不从心了。</p>



<p class="wp-block-paragraph">首先就是要维护的路由信息太大，软硬件成本都不可接受。然后就是各个网络内部的情况可能不同，比如计算路线代价的时候可能各个自治系统的定义不一样，比如自治系统 A 的某条线路代价为 100 表示速度比较慢的线路，但是自治系统 B 的代价 100 则表示不可用的线路。最后就是一些特殊的需求，比如国家内部的终端在公网交换信息，理论上有两种路线，一种是走国内的线路，另一种是从国外的线路绕行到国内的线路，BGP 协议可以让国内的通信无需绕行国外，提高速度。</p>



<p class="wp-block-paragraph">下图是一个简单的 BGP 工作示意图。</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1377" height="640" src="https://www.addesp.com/wp-content/uploads/2021/04/BGP-1.webp" alt="" class="wp-image-4258"/><figcaption>BGP 协议</figcaption></figure>



<h2 class="wp-block-heading">BGP 协议的安全缺陷</h2>



<p class="wp-block-paragraph">BGP 协议并不能验证 BGP 发言人所声明的信息是否为真，也就是说 BGP 发言人完全可以声明一个不属于自己的网络，然后将被声明的网络的流量引到自己的自治系统内，完成 BGP 劫持。</p>



<p class="wp-block-paragraph">下图是一个 BGP 劫持的示意图。</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1390" height="1000" src="https://www.addesp.com/wp-content/uploads/2021/04/BGP劫持.webp" alt="" class="wp-image-4262"/><figcaption>BGP 劫持</figcaption></figure>



<p class="wp-block-paragraph">此时攻击者可选择丢弃掉 N3 网络所有的流量、进行窃听或者篡改。</p>



<h2 class="wp-block-heading">为什么 IP 不会变？</h2>



<p class="wp-block-paragraph">回顾 OSI 七层模型，其中第三层为网络层，负责根据 IP 转发 IP 数据报。一旦 BGP 劫持成功，路由器会错误地将发往网络 N3 的数据报发往网络 N4，但是路由器并不知道，所以从使用者的角度看，自己的 IP 地址是正常的。</p>



<h2 class="wp-block-heading">BGP 协议的改进</h2>



<p class="wp-block-paragraph"><a href="https://tools.ietf.org/html/rfc7454" target="_blank" rel="noreferrer noopener" title="https://tools.ietf.org/html/rfc7454">BGP Operations and Security — RFC7454</a> 中记录了一些最佳实践，如引入 ACL（访问控制列表），在传输层建立安全机制等，有兴趣的读者可以自行阅读。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/4225/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OCSP—让你及时发现被吊销的数字证书的协议</title>
		<link>https://www.addesp.com/archives/3498</link>
					<comments>https://www.addesp.com/archives/3498#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Sun, 31 Jan 2021 17:07:50 +0000</pubDate>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=3498</guid>

					<description><![CDATA[没有及时发现证书失效是很可怕的事，尤其是在金融交易中。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">用途</h2>



<p class="wp-block-paragraph">互联网世界中我们需要确定对方的身份，比如防止我想和小明说话，但是实际却在和黑客说话这种情况。一种比较常见的认证方式就是数字证书，比如 HTTPS 站点的 SSL 证书。关于 HTTPS 的工作流程的简单介绍，可以看一下我之前的一篇文章——<a href="https://www.addesp.com/archives/284" target="_blank" rel="noreferrer noopener">简要说明 HTTPS 是如何保证数据安全</a>。</p>



<p class="wp-block-paragraph">一般来说客户端收到对方的证书后会沿着证书链确定各级证书是否有效以决定是否信任接收到的证书。在这种验证流程中操作系统、浏览器和安全软件都可以内置一些 CA 的证书以便证书的检查。</p>



<p class="wp-block-paragraph">如果一个证书是无效的，那么它一定符合下列情况中的至少一个。</p>



<ul class="wp-block-list"><li>证书本身过期或者证书链上的某个证书过期。</li><li>证书本身被吊销或者证书链上的某个证书被吊销。</li></ul>



<p class="wp-block-paragraph">证书的有效期已经写入证书本身，无需额外的信息即可判断。但是如果一个证书出于某种原因被吊销了（比如私钥泄露），客户端此时无法根据证书所携带的信息来确定是否被吊销。OCSP 就是为了解决这个问题。</p>



<h2 class="wp-block-heading">协议概述</h2>



<p class="wp-block-paragraph">OCSP 全称 Online Certificate Status Protocol，即在线证书状态协议。它可以让客户端与服务器通信以确定某个证书的状态，即未撤销、已撤销或未知。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>笔者并未在协议文档中找到关于 OCSP 所使用的传输机制，报文结构等信息，所以 OCSP 理论上可以有多种实现。</p></blockquote>



<h2 class="wp-block-heading">通信流程</h2>



<p class="wp-block-paragraph">客户端向提供 COSP 服务的服务器发送一个请求，包含下列内容。</p>



<ul class="wp-block-list"><li>协议版本。</li><li>服务请求的类型（协议文档并未指明有哪些类型）。</li><li>打算查询状态的一个或多个证书的 ID。</li><li>可选的扩展信息。</li></ul>



<p class="wp-block-paragraph">服务器接收到请求之后首先会检查请求是否符合下列要求。</p>



<ul class="wp-block-list"><li>请求格式正确。</li><li>服务器支持请求中所指定的「服务请求的类型」。</li><li>客户端提供的信息要足以让服务器做出相应，即不能缺少必要信息。</li></ul>



<p class="wp-block-paragraph">然后服务器会通过某些方式获取证书的状态，然后响应客户端的请求，响应中包含下列内容。</p>



<ul class="wp-block-list"><li>响应内容的语法版本。</li><li>响应器的 ID。</li><li>本次响应的生成时间。</li><li>针对每一个证书的响应，包含下列内容。<ul><li>该证书的 ID。</li><li>该证书的状态，包含未撤销、已撤销和未知。</li><li>针对本证书的响应的有效期。</li><li>可选的扩展信息。</li></ul></li><li>可选的扩展信息。</li><li>使用的签名算法的 ID。</li><li>本次响应内容的哈希值的签名。</li></ul>



<p class="wp-block-paragraph">证书状态未知表示服务器不知道这个证书的状态。通常是签发被查询证书的 CA 不受信任，比如自签证书。也有可能是服务器知道的不够多，比如这个证书本身没有问题，但是服务器没有收录。当客户端得到这个回复的时候可以自行选择，比如默认不信任，或者通过其他方式查询状态等。</p>



<p class="wp-block-paragraph">证书状态为已撤销通常表示为此证书被 CA 撤销，但这并不绝对。对于类似自签证书这样的由不受信任的 CA 签发的证书，服务器也可以在响应中将其标记为已撤销状态，意为服务器打算让客户端直接拒绝这个证书，而不是像证书状态未知那样交给客户端自己去选择。</p>



<p class="wp-block-paragraph">一旦一个由不受信任的 CA 颁发的证书在本次响应中被标记为已撤销，那么本次响应必须要符合下列要求。</p>



<ul class="wp-block-list"><li>必须在本次响应中说明撤销的原因。</li><li>必须在本次响应中说明撤销的时间。</li><li>不能在本次响应中包含 CRL 的参考信息。</li></ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>CRL 是另一个用来查询证书状态的协议。</p></blockquote>



<h2 class="wp-block-heading">写在最后</h2>



<p class="wp-block-paragraph">OCSP 会拖慢证书的验证时间，尤其是在提供 OCSP 的服务器不那么可用的情况下，所以有了 OCSP stapling。它将验证工作放到了 Web 服务器，也就是说你在连接一个 HTTPS 站点的时候同时向站点对应的服务器发起 OCSP 请求，因为 Web 服务器对于访问它的客户端来说通常都是高可用的，所以这种方式一般比较快。本站也在写完本篇文章后支持了此种方式。</p>



<p class="wp-block-paragraph">本文只是粗略地说明协议的运行过程，一些细节被省略，比如如何预防重放攻击。如果有兴趣可以自行查看协议文档。</p>



<h2 class="wp-block-heading">参考资料</h2>



<ul class="wp-block-list"><li><a href="https://tools.ietf.org/html/rfc6960" target="_blank" rel="noreferrer noopener">RFC 6960 &#8211; X.509 Internet Public Key Infrastructure Online Certificate Status Protocol &#8211; OCSP</a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/3498/feed</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>D-H 密钥交换—即使被窃听也能安全地交换密钥</title>
		<link>https://www.addesp.com/archives/2710</link>
					<comments>https://www.addesp.com/archives/2710#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Tue, 01 Dec 2020 14:03:22 +0000</pubDate>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">https://www.addesp.com/?p=2710</guid>

					<description><![CDATA[是的，即使通信全程都被窃听，你依然可以和对方安全地协商出密钥来进行加密通讯。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">写在前面</h2>



<p class="wp-block-paragraph">是的，即使通信全程都被窃听，你依然可以和对方安全地协商出密钥来进行加密通讯。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><strong>迪菲-赫尔曼密钥交换</strong>（英语：Diffie–Hellman key exchange，缩写为D-H） 是一种<a target="_blank" href="https://baike.baidu.com/item/%E5%AE%89%E5%85%A8%E5%8D%8F%E8%AE%AE" rel="noreferrer noopener">安全协议</a>。它可以让双方在完全没有对方任何预先信息的条件下通过不安全<a target="_blank" href="https://baike.baidu.com/item/%E4%BF%A1%E9%81%93" rel="noreferrer noopener">信道</a>创建起一个<a target="_blank" href="https://baike.baidu.com/item/%E5%AF%86%E9%92%A5" rel="noreferrer noopener">密钥</a>。这个密钥可以在后续的通讯中作为<a target="_blank" href="https://baike.baidu.com/item/%E5%AF%B9%E7%A7%B0%E5%AF%86%E9%92%A5" rel="noreferrer noopener">对称密钥</a>来<a target="_blank" href="https://baike.baidu.com/item/%E5%8A%A0%E5%AF%86" rel="noreferrer noopener">加密</a>通讯内容。公钥交换的概念最早由瑞夫·墨克（Ralph C. Merkle）提出，而这个密钥交换方法，由<a target="_blank" href="https://baike.baidu.com/item/%E6%83%A0%E7%89%B9%E8%8F%B2%E5%B0%94%E5%BE%B7%C2%B7%E8%BF%AA%E8%8F%B2" rel="noreferrer noopener">惠特菲尔德·迪菲</a>（Bailey Whitfield Diffie）和<a target="_blank" href="https://baike.baidu.com/item/%E9%A9%AC%E4%B8%81%C2%B7%E8%B5%AB%E5%B0%94%E6%9B%BC" rel="noreferrer noopener">马丁·赫尔曼</a>（Martin Edward Hellman）在1976年首次发表。马丁·赫尔曼曾主张这个密钥交换方法，应被称为<strong>迪菲-赫尔曼-墨克密钥交换</strong>（英语：Diffie–Hellman–Merkle key exchange）。</p><cite><a href="https://baike.baidu.com/item/%E8%BF%AA%E8%8F%B2%EF%BC%8D%E8%B5%AB%E5%B0%94%E6%9B%BC%E5%AF%86%E9%92%A5%E4%BA%A4%E6%8D%A2" target="_blank" rel="noreferrer noopener">迪菲-赫尔曼密钥交换_百度百科</a></cite></blockquote>



<h2 class="wp-block-heading">D-H 密钥交换流程</h2>



<ol class="wp-block-list"><li>通信双方甲和乙事先约定好两个精心挑选的数，一个是质数 $p$，另一个是 $g$。这两个数是可以公开的。我们假设 $p=23,g=5$。</li><li>甲随机选择一个整数 $a$，计算 $A=g^a \mod p$，并将 $A$ 发送给乙。其中 $A$ 是可以公开的，但是 $a$ 不能泄露。我们假设 $a=6$，那么 $A=5^6 \mod 23 =8$。</li><li>乙随机选择一个整数 $b$，计算 $B=g^b \mod p$，并将 $B$ 发送给甲。其中 $B$ 是可以公开的，但是 $b$ 不能泄露。我们假设 $b=15$，那么 $B=5^{15} \mod 23 =19$。</li><li>此时双方就可以计算出共有的密码 $s$。甲通过计算 $s = B^a \mod p = 19^6 \mod 23 = 2$。乙通过计算 $s = A^b \mod p = 8^6 \mod 23 = 2$。</li><li>双方得到了相同的密码 $s$。但这个密码并不是一方主动发给另一方的，而是通过双方交换的信息计算而来的。此时可以使用 $s$ 生成对称密钥来加密通信。</li></ol>



<p class="wp-block-paragraph">根据模运算法则 $g^a \mod p = [{(g \mod p)}^a] \mod p$，同理 $g^b \mod p = [{(g \mod p)}^b] \mod p$，显然 $s={(g^a \mod p)}^b \mod p = {(g^b \mod p)}^a \mod p$。</p>



<p class="wp-block-paragraph">可以发现公开的信息只有 $p,g,A,B$，而只需要在草稿纸上试一试就感觉这些信息逆向算出$a,b$是很难的事情，貌似只能去穷举，事实也确实如此。由于计算出密码 $s$ 除了 $p,g,A,B$ 以外还需要 $a$ 或 $b$，所以这种密钥交换方式即使在被窃听的情况下也能保证安全（前提是不会受到中间人攻击）。</p>



<h2 class="wp-block-heading">离散对数问题</h2>



<p class="wp-block-paragraph">上文说到逆向计算 $a,b$ 是很难的，这其实就是著名的离散对数问题。相关的数学表述本文不会涉及，首先是因为本文的初衷是了解即可，没必要钻那么深，其次就是笔者不是搞数学的，水平有限，查了半天资料还是一知半解的，就不瞎说了。就举一个比较直观的例子吧。</p>



<p class="wp-block-paragraph">我们设 $g=3,p=10$，依次计算 $g^i \mod p$，其中  $i = 0,1,2,···,99$。</p>


<div  class='collapse-block shadow-sm collapse-block-success collapsed hide-border-left'><div class='collapse-block-title'><span class='collapse-block-title-inner'>点击查看计算结果</span><i class='collapse-icon fa fa-angle-down'></i></div><div class='collapse-block-body' style='display:none;'><br />
$$<br />
\begin{aligned}<br />
3^{0} \mod 10 = 1 \\<br />
3^{1} \mod 10 = 3 \\<br />
3^{2} \mod 10 = 9 \\<br />
3^{3} \mod 10 = 7 \\<br />
3^{4} \mod 10 = 1 \\<br />
3^{5} \mod 10 = 3 \\<br />
3^{6} \mod 10 = 9 \\<br />
3^{7} \mod 10 = 7 \\<br />
3^{8} \mod 10 = 1 \\<br />
3^{9} \mod 10 = 3 \\<br />
3^{10} \mod 10 = 9 \\<br />
3^{11} \mod 10 = 7 \\<br />
3^{12} \mod 10 = 1 \\<br />
3^{13} \mod 10 = 3 \\<br />
3^{14} \mod 10 = 9 \\<br />
3^{15} \mod 10 = 7 \\<br />
3^{16} \mod 10 = 1 \\<br />
3^{17} \mod 10 = 3 \\<br />
3^{18} \mod 10 = 9 \\<br />
3^{19} \mod 10 = 7 \\<br />
3^{20} \mod 10 = 1 \\<br />
3^{21} \mod 10 = 3 \\<br />
3^{22} \mod 10 = 9 \\<br />
3^{23} \mod 10 = 7 \\<br />
3^{24} \mod 10 = 1 \\<br />
3^{25} \mod 10 = 3 \\<br />
3^{26} \mod 10 = 9 \\<br />
3^{27} \mod 10 = 7 \\<br />
3^{28} \mod 10 = 1 \\<br />
3^{29} \mod 10 = 3 \\<br />
3^{30} \mod 10 = 9 \\<br />
3^{31} \mod 10 = 7 \\<br />
3^{32} \mod 10 = 1 \\<br />
3^{33} \mod 10 = 3 \\<br />
3^{34} \mod 10 = 8 \\<br />
3^{35} \mod 10 = 2 \\<br />
3^{36} \mod 10 = 6 \\<br />
3^{37} \mod 10 = 6 \\<br />
3^{38} \mod 10 = 0 \\<br />
3^{39} \mod 10 = 6 \\<br />
3^{40} \mod 10 = 8 \\<br />
3^{41} \mod 10 = 2 \\<br />
3^{42} \mod 10 = 2 \\<br />
3^{43} \mod 10 = 6 \\<br />
3^{44} \mod 10 = 4 \\<br />
3^{45} \mod 10 = 2 \\<br />
3^{46} \mod 10 = 4 \\<br />
3^{47} \mod 10 = 0 \\<br />
3^{48} \mod 10 = 8 \\<br />
3^{49} \mod 10 = 8 \\<br />
3^{50} \mod 10 = 4 \\<br />
3^{51} \mod 10 = 2 \\<br />
3^{52} \mod 10 = 4 \\<br />
3^{53} \mod 10 = 4 \\<br />
3^{54} \mod 10 = 6 \\<br />
3^{55} \mod 10 = 8 \\<br />
3^{56} \mod 10 = 0 \\<br />
3^{57} \mod 10 = 4 \\<br />
3^{58} \mod 10 = 2 \\<br />
3^{59} \mod 10 = 2 \\<br />
3^{60} \mod 10 = 0 \\<br />
3^{61} \mod 10 = 8 \\<br />
3^{62} \mod 10 = 4 \\<br />
3^{63} \mod 10 = 4 \\<br />
3^{64} \mod 10 = 0 \\<br />
3^{65} \mod 10 = 2 \\<br />
3^{66} \mod 10 = 8 \\<br />
3^{67} \mod 10 = 4 \\<br />
3^{68} \mod 10 = 6 \\<br />
3^{69} \mod 10 = 4 \\<br />
3^{70} \mod 10 = 8 \\<br />
3^{71} \mod 10 = 4 \\<br />
3^{72} \mod 10 = 0 \\<br />
3^{73} \mod 10 = 0 \\<br />
3^{74} \mod 10 = 6 \\<br />
3^{75} \mod 10 = 0 \\<br />
3^{76} \mod 10 = 0 \\<br />
3^{77} \mod 10 = 4 \\<br />
3^{78} \mod 10 = 6 \\<br />
3^{79} \mod 10 = 2 \\<br />
3^{80} \mod 10 = 4 \\<br />
3^{81} \mod 10 = 2 \\<br />
3^{82} \mod 10 = 8 \\<br />
3^{83} \mod 10 = 0 \\<br />
3^{84} \mod 10 = 6 \\<br />
3^{85} \mod 10 = 4 \\<br />
3^{86} \mod 10 = 2 \\<br />
3^{87} \mod 10 = 8 \\<br />
3^{88} \mod 10 = 4 \\<br />
3^{89} \mod 10 = 0 \\<br />
3^{90} \mod 10 = 6 \\<br />
3^{91} \mod 10 = 2 \\<br />
3^{92} \mod 10 = 6 \\<br />
3^{93} \mod 10 = 0 \\<br />
3^{94} \mod 10 = 0 \\<br />
3^{95} \mod 10 = 0 \\<br />
3^{96} \mod 10 = 2 \\<br />
3^{97} \mod 10 = 6 \\<br />
3^{98} \mod 10 = 2 \\<br />
3^{99} \mod 10 = 6 \\<br />
\end{aligned}<br />
$$<br />
</div></div>



<p class="wp-block-paragraph">那么如果我问求一个 $k$ 使得 $3^k \mod 10 = 6$。在没有快捷算法的情况下我们只能一个一个地试，此时可以视为随机取 $i$ 的值去试。可以注意到在上面列出的 100 个计算结果中 6 出现了 13 次，出现的概率是 $13\%$，这意味着我在穷举过程中每次计算都有 $13\%$ 的概率的都正确答案。</p>



<p class="wp-block-paragraph">那么当我们让$p=17$，即一个素数时，情况就变了。</p>


<div  class='collapse-block shadow-sm collapse-block-success collapsed hide-border-left'><div class='collapse-block-title'><span class='collapse-block-title-inner'>点击查看计算结果</span><i class='collapse-icon fa fa-angle-down'></i></div><div class='collapse-block-body' style='display:none;'><br />
$$<br />
\begin{aligned}<br />
&amp; 3^{0} \mod 17 = 1 \\<br />
&amp; 3^{1} \mod 17 = 3 \\<br />
&amp; 3^{2} \mod 17 = 9 \\<br />
&amp; 3^{3} \mod 17 = 10 \\<br />
&amp; 3^{4} \mod 17 = 13 \\<br />
&amp; 3^{5} \mod 17 = 5 \\<br />
&amp; 3^{6} \mod 17 = 15 \\<br />
&amp; 3^{7} \mod 17 = 11 \\<br />
&amp; 3^{8} \mod 17 = 16 \\<br />
&amp; 3^{9} \mod 17 = 14 \\<br />
&amp; 3^{10} \mod 17 = 8 \\<br />
&amp; 3^{11} \mod 17 = 7 \\<br />
&amp; 3^{12} \mod 17 = 4 \\<br />
&amp; 3^{13} \mod 17 = 12 \\<br />
&amp; 3^{14} \mod 17 = 2 \\<br />
&amp; 3^{15} \mod 17 = 6 \\<br />
&amp; 3^{16} \mod 17 = 1 \\<br />
&amp; 3^{17} \mod 17 = 3 \\<br />
&amp; 3^{18} \mod 17 = 9 \\<br />
&amp; 3^{19} \mod 17 = 10 \\<br />
&amp; 3^{20} \mod 17 = 13 \\<br />
&amp; 3^{21} \mod 17 = 5 \\<br />
&amp; 3^{22} \mod 17 = 15 \\<br />
&amp; 3^{23} \mod 17 = 11 \\<br />
&amp; 3^{24} \mod 17 = 16 \\<br />
&amp; 3^{25} \mod 17 = 14 \\<br />
&amp; 3^{26} \mod 17 = 8 \\<br />
&amp; 3^{27} \mod 17 = 7 \\<br />
&amp; 3^{28} \mod 17 = 4 \\<br />
&amp; 3^{29} \mod 17 = 12 \\<br />
&amp; 3^{30} \mod 17 = 2 \\<br />
&amp; 3^{31} \mod 17 = 6 \\<br />
&amp; 3^{32} \mod 17 = 1 \\<br />
&amp; 3^{33} \mod 17 = 3 \\<br />
&amp; 3^{34} \mod 17 = 8 \\<br />
&amp; 3^{35} \mod 17 = 15 \\<br />
&amp; 3^{36} \mod 17 = 11 \\<br />
&amp; 3^{37} \mod 17 = 1 \\<br />
&amp; 3^{38} \mod 17 = 11 \\<br />
&amp; 3^{39} \mod 17 = 0 \\<br />
&amp; 3^{40} \mod 17 = 0 \\<br />
&amp; 3^{41} \mod 17 = 8 \\<br />
&amp; 3^{42} \mod 17 = 11 \\<br />
&amp; 3^{43} \mod 17 = 16 \\<br />
&amp; 3^{44} \mod 17 = 15 \\<br />
&amp; 3^{45} \mod 17 = 11 \\<br />
&amp; 3^{46} \mod 17 = 7 \\<br />
&amp; 3^{47} \mod 17 = 6 \\<br />
&amp; 3^{48} \mod 17 = 10 \\<br />
&amp; 3^{49} \mod 17 = 12 \\<br />
&amp; 3^{50} \mod 17 = 2 \\<br />
&amp; 3^{51} \mod 17 = 6 \\<br />
&amp; 3^{52} \mod 17 = 15 \\<br />
&amp; 3^{53} \mod 17 = 2 \\<br />
&amp; 3^{54} \mod 17 = 5 \\<br />
&amp; 3^{55} \mod 17 = 15 \\<br />
&amp; 3^{56} \mod 17 = 10 \\<br />
&amp; 3^{57} \mod 17 = 14 \\<br />
&amp; 3^{58} \mod 17 = 8 \\<br />
&amp; 3^{59} \mod 17 = 14 \\<br />
&amp; 3^{60} \mod 17 = 12 \\<br />
&amp; 3^{61} \mod 17 = 10 \\<br />
&amp; 3^{62} \mod 17 = 13 \\<br />
&amp; 3^{63} \mod 17 = 13 \\<br />
&amp; 3^{64} \mod 17 = 14 \\<br />
&amp; 3^{65} \mod 17 = 10 \\<br />
&amp; 3^{66} \mod 17 = 5 \\<br />
&amp; 3^{67} \mod 17 = 15 \\<br />
&amp; 3^{68} \mod 17 = 7 \\<br />
&amp; 3^{69} \mod 17 = 5 \\<br />
&amp; 3^{70} \mod 17 = 11 \\<br />
&amp; 3^{71} \mod 17 = 16 \\<br />
&amp; 3^{72} \mod 17 = 16 \\<br />
&amp; 3^{73} \mod 17 = 14 \\<br />
&amp; 3^{74} \mod 17 = 9 \\<br />
&amp; 3^{75} \mod 17 = 12 \\<br />
&amp; 3^{76} \mod 17 = 2 \\<br />
&amp; 3^{77} \mod 17 = 7 \\<br />
&amp; 3^{78} \mod 17 = 0 \\<br />
&amp; 3^{79} \mod 17 = 16 \\<br />
&amp; 3^{80} \mod 17 = 12 \\<br />
&amp; 3^{81} \mod 17 = 2 \\<br />
&amp; 3^{82} \mod 17 = 4 \\<br />
&amp; 3^{83} \mod 17 = 16 \\<br />
&amp; 3^{84} \mod 17 = 15 \\<br />
&amp; 3^{85} \mod 17 = 7 \\<br />
&amp; 3^{86} \mod 17 = 4 \\<br />
&amp; 3^{87} \mod 17 = 10 \\<br />
&amp; 3^{88} \mod 17 = 13 \\<br />
&amp; 3^{89} \mod 17 = 14 \\<br />
&amp; 3^{90} \mod 17 = 4 \\<br />
&amp; 3^{91} \mod 17 = 16 \\<br />
&amp; 3^{92} \mod 17 = 14 \\<br />
&amp; 3^{93} \mod 17 = 6 \\<br />
&amp; 3^{94} \mod 17 = 1 \\<br />
&amp; 3^{95} \mod 17 = 3 \\<br />
&amp; 3^{96} \mod 17 = 1 \\<br />
&amp; 3^{97} \mod 17 = 3 \\<br />
&amp; 3^{98} \mod 17 = 5 \\<br />
&amp; 3^{99} \mod 17 = 15 \\<br />
\end{aligned}<br />
$$<br />
</div></div>



<p class="wp-block-paragraph">此时 6 只出现了 5 次，而且呈现出了明显的周期现象，这个周期就是 $p-1$ 即 16。这时我们穷举的时候每次计算只有 $5\%$ 的概率是正确答案了。在这种情况下我们提高了穷举的难度。</p>



<p class="wp-block-paragraph">目前的数学研究结果让我们可以精心选择一个素数 $p$ 和另一个精心选择的 $g$ 来通过这样的方式来提高穷举的难度，比如我们选择一个长度为 $1024 bit$ 的素数，那么它的周期和 $2^{1024} \approx 1.798 \times 10^{308}$ 是同一个数量级的，那么暴力穷举算法的时间复杂度就是指数级的。那么如果素数的长度是 $2048 bit$ 呢？$4096 bit$ 呢？</p>



<p class="wp-block-paragraph">上面的例子并不严谨，但可以直观地感受一下离散对数问题的难度。稍微专业点的描述一下离散对数的难度就是暂时没有多项式时间或更快的算法能够求解离散对数问题。</p>



<h2 class="wp-block-heading">身份验证</h2>



<p class="wp-block-paragraph">D-H 密钥交换没有提供身份验证的机制，所以我们需要公钥基础设施来保证不会受到中间人攻击。</p>



<h2 class="wp-block-heading">前向安全性</h2>



<p class="wp-block-paragraph">前向安全性即通讯的主密钥泄露不会导致会话密钥的泄露，它可以保证之前的通讯不会因为在未来的某一时刻主密钥泄露而被解密。</p>



<p class="wp-block-paragraph">目前常见的身份认证方式之一就是基于非对称加密的证书验证。在这种方式下为了实现身份认证服务端会使用私钥给一些必要的信息签名发送给客户端，客户端确认服务端的身份后双方协商出会话密钥，协商过程中的信息会用公钥加密，只有私钥才能解密。此时客户端可以直接将会话密钥通过公钥加密后发送给服务端，然后开始加密通讯。这在正常情况下没有任何问题。但是一旦服务端的私钥泄露，那么之前的会话密钥就会被解密，之前的通讯信息也就暴露了。</p>



<p class="wp-block-paragraph">回忆一下，D-H 密钥交换过程中 $p,g,A,B$ 是可以公开的，只有$a,b$ 是秘密的，我们假设 $a,b$ 是随机选取的，并且在通讯结束后会被销毁。如果客户端在确认了服务端身份的之后采用 D-H 密钥交换的方式，而不是直接发送公钥加密后的会话密钥，那么即使未来的某一时刻服务端私钥泄露了，也不会泄露会话密钥，也就无法解密之前的通讯信息。</p>



<p class="wp-block-paragraph">目前这种机制已经被引入 TLS 中。</p>



<h2 class="wp-block-heading">写在最后</h2>



<p class="wp-block-paragraph">搞密码的这群人是何等的怪物（褒义）。</p>



<h2 class="wp-block-heading">参考资料</h2>



<ul class="wp-block-list"><li><a href="https://baike.baidu.com/item/%E8%BF%AA%E8%8F%B2%EF%BC%8D%E8%B5%AB%E5%B0%94%E6%9B%BC%E5%AF%86%E9%92%A5%E4%BA%A4%E6%8D%A2" target="_blank" rel="noreferrer noopener">迪菲-赫尔曼密钥交换_百度百科</a></li><li><a href="https://baike.baidu.com/item/%E5%89%8D%E5%90%91%E5%AE%89%E5%85%A8%E6%80%A7/6357798" target="_blank" rel="noreferrer noopener">前向安全性_百度百科</a></li><li><a href="https://tools.ietf.org/html/rfc8446" target="_blank" rel="noreferrer noopener">RFC 8446 &#8211; The Transport Layer Security (TLS) Protocol Version 1.3</a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/2710/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>数字签名为什么可以防篡改</title>
		<link>https://www.addesp.com/archives/311</link>
					<comments>https://www.addesp.com/archives/311#respond</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Mon, 27 Apr 2020 06:30:15 +0000</pubDate>
				<category><![CDATA[科普]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">http://69a274df.addesp.com/?p=311</guid>

					<description><![CDATA[概述 你可能在电视剧中看到坏人威胁主角的时候会拿出作为人质的亲人写的信，而主角一看笔迹就知道是亲人所写的了。  [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">概述</h2>



<p class="wp-block-paragraph">你可能在电视剧中看到坏人威胁主角的时候会拿出作为人质的亲人写的信，而主角一看笔迹就知道是亲人所写的了。</p>



<p class="wp-block-paragraph">在这里笔迹起到了两个作用：</p>



<ul class="wp-block-list"><li>证明信的内容确实是亲人所写</li><li>证明内容没有被篡改过</li></ul>



<p class="wp-block-paragraph">在计算机的世界中，我们同样需要对信息一样的验证。</p>



<h2 class="wp-block-heading">例子</h2>



<p class="wp-block-paragraph">下面是一段在线聊天对话：</p>



<ul class="wp-block-list"><li>小明：小红，借我 30w 呗，我去买点水喝。</li><li>小红：可以，不过你要给我打一个欠条，拍照发过来。</li><li>小明：没问题，发给你了。</li><li>小红：好的，明天我把带给你。</li></ul>



<p class="wp-block-paragraph">此时，这笔借款交易的安全性如何？</p>



<ul class="wp-block-list"><li>小红可能会&nbsp;PS&nbsp;照片修改借款数字。</li><li>小明事后可能会抵赖说照片是修改过的。</li><li>照片可能在传输过程中阴差阳错地出现错误导致欠条内容改变。</li><li>其它。</li></ul>



<p class="wp-block-paragraph">这时需要解决的问题就是：</p>



<ul class="wp-block-list"><li>如何证明这个照片是小明发给小红的。</li><li>如何证明这个照片没有被修改过。</li></ul>



<p class="wp-block-paragraph">此时我们就需要对照片进行<strong>数字签名</strong>。</p>



<h2 class="wp-block-heading">前置知识</h2>



<h3 class="wp-block-heading">哈希函数</h3>



<p class="wp-block-paragraph">哈希函数是可以将一段任意长度的信息转化为固定长度信息，这个固定长度的信息称为<strong>哈希值</strong>。</p>



<p class="wp-block-paragraph">哈希函数有两个特点：</p>



<ul class="wp-block-list"><li>任何长度的原始信息经过哈希函数后都会变成等长度的信息。</li><li>一旦输入给给哈希函数的信息发生了改变（哪怕是一点点的改变），最终的<strong>哈希值</strong>就会面目全非。</li></ul>



<p class="wp-block-paragraph">下面我们用一种叫做`SHA256`的哈希函数举个例子：</p>



<pre class="wp-block-preformatted">原始信息：100000000000000
哈希值：7186c3316577cf7ee0568c6ff7f3227b5b3e4b498e7eabba4f6e3d908e2162f4

原始信息：100000000000001
哈希值：11d77ab50791e10caffb01cb6ff851f4929edfb0ad79808111d78182b0048540</pre>



<p class="wp-block-paragraph">结果很明显，仅仅做一点点改动哈希值都会发生巨大的变化。</p>



<h3 class="wp-block-heading">非对称加密</h3>



<p class="wp-block-paragraph">非对称加密有两个密钥，一个称为<strong>私钥</strong>，一个称为<strong>公钥</strong>。<br>经过公钥加密的信息只能被相匹配的私钥解密，也就是说同一个公钥不能解密自己加密的信息。私钥加密的信息只有公钥可以解密，也就是说私钥不能解密自己的信息。同时也可以用公钥验证加密的信息是否是相匹配的私钥加密的。</p>



<h2 class="wp-block-heading">数字签名</h2>



<h3 class="wp-block-heading">签名过程</h3>



<ol class="wp-block-list"><li>小明自己生成一对公私钥。</li><li>小明计算出欠条照片的哈希值。</li><li>小明用私钥对哈希值进行加密形成<strong>签名</strong>。</li></ol>



<p class="wp-block-paragraph">签名的过程就完成了。此时小明需要将照片，公钥以及签名发给小红。</p>



<h3 class="wp-block-heading">验证过程</h3>



<ul class="wp-block-list"><li>小红用公钥解密<strong>签名</strong>得到照片的<strong>哈希值</strong>。</li><li>小红用公钥验证得到解密出来的<strong>哈希值</strong>确实是<strong>小明的私钥</strong>加密的。</li><li>小红计算出欠条照片的<strong>哈希值</strong>。</li><li>将两个哈希值进行对比，如果一样则验证成功，反之则失败。</li></ul>



<p class="wp-block-paragraph">可见验证成功需要同时满足两个条件：</p>



<ul class="wp-block-list"><li>解密出的哈希值与收到的照片的哈希值一致。</li><li>用公钥证明了<strong>哈希值</strong>确实是<strong>小明的私钥</strong>加密的。</li></ul>



<p class="wp-block-paragraph">第一个条件保证了照片没有被修改过。第二个条件则保证了借款双方都无法抵赖。</p>



<p class="wp-block-paragraph"><br>你可能会想，如果小明表示小红的公钥不是自己的，或者小红表示自己的公钥不是小明的岂不是还能抵赖？</p>



<h3 class="wp-block-heading">证书机构</h3>



<p class="wp-block-paragraph">此时我们需要第三方来做公正。小明需要将自己的公钥交给证书机构，证书机构审核后会颁发证书，证明这个公钥是小明的。而且这个证书是公开的，也就是说小红也可以拿到。<br>此时假如抵赖小明说你的公钥是假的，那么小红就可以指着证书对他：<strong>说睁大你的X眼看看，这是你颁发给你的证书，上面已经说了这个公钥是你的</strong>。当小红抵赖的时候也可以这么干。</p>



<h2 class="wp-block-heading">总结</h2>



<p class="wp-block-paragraph">数字签名可以切实有效地地保证双方的信息是没有被修改过的，并且可以明确消息来源。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/311/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>浅析跨站请求伪造（CSRF）攻击</title>
		<link>https://www.addesp.com/archives/218</link>
					<comments>https://www.addesp.com/archives/218#respond</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Thu, 23 Apr 2020 02:07:52 +0000</pubDate>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">http://69a274df.addesp.com/?p=218</guid>

					<description><![CDATA[概念 &#038; 案例 &#038; 防御]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">概述</h2>



<p class="wp-block-paragraph">介绍下列内容：</p>



<ul class="wp-block-list"><li>什么是 CSRF 攻击</li><li>漏洞举例</li><li>常见的防御方式</li></ul>



<h2 class="wp-block-heading">什么是CSRF攻击</h2>



<h3 class="wp-block-heading">狭义的CSRF攻击</h3>



<p class="wp-block-paragraph">狭义的CSRF攻击就是指让Client在被Server认证的情况下去访问精心设计的恶意链接完成攻击。</p>



<ol class="wp-block-list"><li>因为 HTTP 是无状态的协议，即 Server 不知道每个请求来源于哪个用户。</li><li>所以服务器有时会在Client存储可以标识用户身份的信息。</li><li>在Client发送请求的时候附上用户身份信息保证Server可以识别出用户。</li><li>如果此时用户点击了一个恶意链接，且恶意链接会发送一个恶意请求到 Server。</li><li>一般情况下会因为不能识别用户身份而而被拒绝。</li><li>但是如果此时 Client 是刚刚被服务端认证过的，则发送恶意请求的同时也会附上刚刚认证的身份信息。</li><li>Server 收到恶意请求后发现Client是认证过的，于是将其识别为合法请求。</li><li>攻击者就完成了一次 CSRF 攻击。</li></ol>



<h2 class="wp-block-heading">广义的CSRF攻击</h2>



<p class="wp-block-paragraph">通过一些手段猜测出请求参数以及用户认证信息（如果需要认证的话），这样Server就会将其识别为合理请求。</p>



<p class="wp-block-paragraph"><br>例如某网站转账的URL为<code>https://www.bank.com/transfer?user=小明&amp;money=1000&amp;for=小红</code>，代表小明转账给小红 1000 元。那么攻击者就可以构造出这个URL—<code>https://www.bank.com/transfer?user=小明&amp;money=9999999999&amp;for=</code>小李直接掏空小明的钱。</p>



<h2 class="wp-block-heading">漏洞举例</h2>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" href="https://www.freebuf.com/vuls/210837.html" data-type="URL" data-id="https://www.freebuf.com/vuls/210837.html" target="_blank">挖洞经验&nbsp;|&nbsp;Facebook的Gmail验证机制存在的CSRF漏洞</a> | CSRF&nbsp;Token缺少验证措施</li><li><a rel="noreferrer noopener" href="https://www.freebuf.com/vuls/131691.html" data-type="URL" data-id="https://www.freebuf.com/vuls/131691.html" target="_blank">Facebook上一个有趣的 CSRF</a> | 授权过程中缺少 state 参数</li><li><a rel="noreferrer noopener" href="https://www.freebuf.com/vuls/223496.html" data-type="URL" data-id="https://www.freebuf.com/vuls/223496.html" target="_blank">挖洞经验&nbsp;|&nbsp;利用 Instagram 版权功能构造 CSRF 漏洞删除其他用户文件</a> | 重要的参数直接写在 GET 请求里</li></ul>



<h2 class="wp-block-heading">常见的防御方式</h2>



<h3 class="wp-block-heading">验证码</h3>



<p class="wp-block-paragraph">在执行一些重要请求之前通过验证码的方式验证用户身份，例如短信验证码，图片验证码等。所以你会发现许多网站即使在登录状态先执行一些操作也需要验证。</p>



<h3 class="wp-block-heading">同源检测</h3>



<p class="wp-block-paragraph">根据 HTTP 协议，在 HTTP 头中有一个字段叫 Referer，记录了该HTTP请求的来源地址。&nbsp;对于 Ajax 请求，图片和 script 等资源请求，Referer 为发起请求的页面地址。对于页面跳转，Referer 为打开页面历史记录的前一个页面地址。因此我们使用 Referer 中链接的 Origin 部分可以得知请求的来源域名。</p>



<p class="wp-block-paragraph"><br>这种方法并非万无一失，Referer 的值是由浏览器提供的，虽然 HTTP 协议上有明确的要求，但是每个浏览器对于 Referer 的具体实现可能有差别，并不能保证浏览器自身没有安全漏洞。使用验证&nbsp;Referer&nbsp;值的方法，就是把安全性都依赖于第三方（即浏览器）来保障，从理论上来讲，这样并不是很安全。在部分情况下，攻击者可以隐藏，甚至修改自己请求的 Referer。<br></p>



<p class="wp-block-paragraph">同源验证是一个相对简单的防范方法，能够防范绝大多数的 CSRF 攻击。但这并不是万无一失的，对于安全性要求较高，或者有较多用户输入内容的网站，我们就要对关键的接口做额外的防护措施。</p>



<h3 class="wp-block-heading">CSRF&nbsp;Token</h3>



<p class="wp-block-paragraph">CSRF 攻击之所以能够成功，是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的 Token。服务器通过校验请求是否携带正确的 Token，来把正常的请求和攻击的请求区分开，也可以防范 CSRF 的攻击。</p>



<p class="wp-block-paragraph"><br>通过一套合适的规则（一般来说这套规则要便于分布式校验）来生成随机的 Token 并跟随 form 表单一起提交，由于 HTTPS 在传输过程中是加密的，所以攻击者无法截获 Token，前提是站点没有 XSS 漏洞。<br></p>



<p class="wp-block-paragraph">但是此方法的实现比较复杂，需要给每一个页面都写入 Token（前端无法使用纯静态页面），每一个 Form 及 Ajax 请求都携带这个 Token，后端对每一个接口都进行校验，并保证页面 Token 及请求 Token 一致。这就使得这个防护策略不能在通用的拦截上统一拦截处理，而需要每一个页面和接口都添加对应的输出和校验。这种方法工作量巨大，且有可能遗漏。</p>



<h3 class="wp-block-heading">双重Cookie验证</h3>



<p class="wp-block-paragraph">在会话中存储CSRF&nbsp;Token比较繁琐，而且不能在通用的拦截上统一处理所有的接口。<br>那么另一种防御措施是使用双重提交Cookie。利用CSRF攻击不能获取到用户Cookie的特点，我们可以要求Ajax和表单请求携带一个Cookie中的值。</p>



<p class="wp-block-paragraph"><br>双重Cookie采用以下流程：</p>



<ul class="wp-block-list"><li>在用户访问网站页面时，向请求域名注入一个Cookie，内容为随机字符串（例如csrfcookie=v8g9e4ksfhw）。</li><li>&nbsp;在前端向后端发起请求时，取出Cookie，并添加到URL的参数中（接上例POST&nbsp;<code>https://www.a.com/comment?csrfcookie=v8g9e4ksfhw</code>）。</li><li>后端接口验证 Cookie 中的字段与 URL 参数中的字段是否一致，不一致则拒绝。</li></ul>



<p class="wp-block-paragraph">攻击者可以获取到URL参数中的Token值，但是无法获取到Cookie中的Token值，因此攻击者无法构造出恶意链接。</p>



<p class="wp-block-paragraph"><br>你可能会想既然我已经截取到了URL参数中的Token值，那么攻击者也就可以猜测出Cookie中的Token值。对，没错，因为上面的流程中URL参数和Cookie中存储的是相同的值，那么如果我对Cookie中的值进行加密呢？那么攻击者就无法推测出Cookie的内容了。<br></p>



<p class="wp-block-paragraph">此方法相对于CSRF&nbsp;Token就简单了许多。可以直接通过前后端拦截的的方法自动化实现。后端校验也更加方便，只需进行请求中字段的对比，而不需要再进行查询和存储Token。</p>



<p class="wp-block-paragraph"><br>当然，此方法并没有大规模应用，其在大型网站上的安全性还是没有CSRF&nbsp;Token高，因为任何跨域都会导致前端无法获取Cookie中的字段（包括子域名之间）。</p>



<h2 class="wp-block-heading">参考资料</h2>



<ul class="wp-block-list"><li><a href="https://tech.meituan.com/2018/10/11/fe-security-csrf.html" data-type="URL" data-id="https://tech.meituan.com/2018/10/11/fe-security-csrf.html" target="_blank" rel="noreferrer noopener">前端安全系列（二）：如何防止CSRF攻击？</a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/218/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>简要说明 HTTPS 是如何保证数据安全</title>
		<link>https://www.addesp.com/archives/284</link>
					<comments>https://www.addesp.com/archives/284#comments</comments>
		
		<dc:creator><![CDATA[ADD-SP]]></dc:creator>
		<pubDate>Sat, 28 Mar 2020 17:48:43 +0000</pubDate>
				<category><![CDATA[科普]]></category>
		<category><![CDATA[HTTPS]]></category>
		<category><![CDATA[网络安全]]></category>
		<guid isPermaLink="false">http://69a274df.addesp.com/?p=284</guid>

					<description><![CDATA[本文简要介绍HTTPS协议是如何保证数据在传输过程中的安全的。]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">概述</h2>



<p class="wp-block-paragraph">本文简要介绍HTTPS协议是如何保证数据在传输过程中的安全的。<br>由于是以介绍为主，所以不会涉及细节，而且<strong>肯定会有一些错误</strong>。如果想要详细了解可自行查阅资料。</p>



<h2 class="wp-block-heading">正文</h2>



<p class="wp-block-paragraph">在HTTPS协议出现前大家用的都是HTTP协议，这种协议传输的都是明文信息，任何人都可以窃取并篡改，毫无安全性可言。</p>



<p class="wp-block-paragraph"><br>HTTP协议的简要通信流程如下图：</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="796" height="582" src="https://www.addesp.com/wp-content/uploads/2020/09/0-10.webp" alt="" class="wp-image-286"/><figcaption><em>HTTP&nbsp;协议简要通信流程</em></figcaption></figure>



<p class="wp-block-paragraph">由于传输的信息都是明文的，所以攻击者就可以窃取并篡改信息，如下图：</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="796" height="582" src="https://www.addesp.com/wp-content/uploads/2020/09/1-8.webp" alt="" class="wp-image-287"/><figcaption><em>中间人攻击</em></figcaption></figure>



<hr class="wp-block-separator"/>



<p class="wp-block-paragraph">你可能会想，我们把信息加密不就可以了么，比如像下图一样</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="866" height="582" src="https://www.addesp.com/wp-content/uploads/2020/09/2-8.webp" alt="" class="wp-image-288"/><figcaption><em>使用对称密钥加密信息</em></figcaption></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>对称加密：双方持有同一个对称密钥，任何一方通过对称密钥加密的信息，对方可以通过相同的对称密钥解密出原文。</p></blockquote>



<p class="wp-block-paragraph">但是攻击者依然可以通过各种方式获取到对称密钥：</p>



<ul class="wp-block-list"><li>如果密钥是通过服务器下发给客户端，则直接截取服务器的消息就行了。</li><li>如果对称密钥是提前保存在双方的电脑上，那就可以通过某种手段入侵客户端或者服务器来窃取对称密钥。</li><li>其它方式。</li></ul>



<p class="wp-block-paragraph">截取到密钥后攻击者仍然可以进行攻击</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="956" height="582" src="https://www.addesp.com/wp-content/uploads/2020/09/3-6.webp" alt="" class="wp-image-289"/><figcaption><em>中间人攻击</em></figcaption></figure>



<hr class="wp-block-separator"/>



<p class="wp-block-paragraph">那么我们就需要对“对称密钥”进行保护了，如下图</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1265" height="729" src="https://www.addesp.com/wp-content/uploads/2020/09/4-3.webp" alt="" class="wp-image-290"/><figcaption><em>保护对称密钥</em></figcaption></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>非对称加密：一方持有私钥，一方持有公钥，使用公钥加密的信息只能被私钥解密。私钥不会用于加密，不过通常会用于加一段签名代表信息是完整，即信息是否丢失了一部分或者因为某种原因而发生的改变。</p></blockquote>



<p class="wp-block-paragraph">这次攻击者看似无法通过截取信息来获得对称密钥了，但是攻击者依然有机会发起攻击。</p>



<p class="wp-block-paragraph">不过先说明一点，目前公钥都是通过服务器下发的证书获得的，所以更接近下图相对来说更接近真实的通信流程</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="916" height="632" src="https://www.addesp.com/wp-content/uploads/2020/09/5-2.webp" alt="" class="wp-image-291"/><figcaption><em>服务器下发证书</em></figcaption></figure>



<p class="wp-block-paragraph">那么攻击者会怎样攻击呢？如下图（图片如果看不清可以右键图片选择“在新的标签页中打开图像”或类似选项）</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="956" height="1462" src="https://www.addesp.com/wp-content/uploads/2020/09/6-2.webp" alt="" class="wp-image-292"/><figcaption><em>中间人攻击</em></figcaption></figure>



<hr class="wp-block-separator"/>



<p class="wp-block-paragraph">这时显然不能对公钥再次加密了，因为无法判断客户端得到的证书是真的，还是攻击者伪造的。<br>这时就需要第三方介入了</p>



<ol class="wp-block-list"><li>合法服务器的证书都是经过审核机构审核的，服务器在下发证书的时候就会下发经过审核的证书</li><li>客户端会存有经过审核的证书的列表。</li><li>客户端收到服务器下发的证书后会验证收到的证书是否经过了审核。</li><li>如果经过了审核则继续通信，反之断开连接或者弹出警告。</li></ol>



<p class="wp-block-paragraph">现在的通信流程图下图，也是HTTPS的大致通信流程</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="916" height="632" src="https://www.addesp.com/wp-content/uploads/2020/09/7-2.webp" alt="" class="wp-image-293"/><figcaption><em>更接近于&nbsp;HTTPS&nbsp;的通信流程</em></figcaption></figure>



<hr class="wp-block-separator"/>



<p class="wp-block-paragraph">不过HTTPS的一大软肋就是第三方证书审核机构，如果审核不严将攻击者的证书列入了合法证书列表，那么HTTPS所作的努力将全部白费。</p>



<p class="wp-block-paragraph"><br>总的来说，HTTPS增加了攻击者的攻击成本，使得数据的传输过程变得更加完全。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.addesp.com/archives/284/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
