没有HTTPS的login,如何保护?
对于Web应用程序,当HTTPS不可用作安全措施时,是否仍然可以使login有点安全? 例如:
- Tokenizelogin,使重复攻击困难?
- 以某种方式encryption从HTML密码字段发送的密码?
特别是我使用CakePHP和AJAX POST调用触发身份validation(包括提供的用户名和密码)。
问题更新:
- HTTPS不可用。 期。 如果你不喜欢这种情况,那么把它看作一个理论问题。
- 没有明确的要求,你有任何HTTP,PHP和浏览器(cookies,JavaScript等)在现实生活中提供(没有神奇的RSA二进制文件,PGP插件)。
- 问题是,什么是最好的,你可以做出这种情况,这比发送密码明文更好。 了解每个这样的解决scheme的缺点是一个加号。
- 欢迎任何比普通密码更好的改进。 我们不瞄准100%l33tG0Dhx0r-proff解决scheme。 难以破解比复杂的破解更好,这比揭示密码的琐事更好。
HTTPS 对维护网站和浏览器之间的安全连接至关重要 。 公共WiFinetworking使用户处于危险之中 ,如果使用得当, HTTPS是唯一可以保护用户帐户免受此漏洞攻击的工具 。
如果您的主机不支持HTTPS,那么即使您的服务器不支持SSL / TLS ,也可以使用像Cloudflare Universal SSL这样的服务来确保所有浏览器都使用HTTPS连接到您的站点。 Cloudflare和您的网站之间的连接仍然是不受保护的,但是这个Cloudflare服务旨在保护用户免受公共WiFinetworking上的威胁。 从渗透testing者的angular度来看,不提供HTTPS是非常值得怀疑的,如果您在提供stream量时没有提供基本的安全要求,那么您还缺less哪些其他安全要求? HTTPS证书可以通过Let's Encrypt或Start SSL免费获得,没有合法理由不支持HTTPS。
HTTPS至关重要,因为它不仅仅是“encryption密码”。 另一个重要angular色是它应该防止用户login到模拟真实服务器的恶意服务器。 仅使用一个系统来保护密码仍然违反了OWASP A9 – 传输层保护不足,因为您仍然会以明文forms传输会话证书,这是攻击者需要的( Firesheep )。
-
基于JavaScript的密码学不能用来构build安全的传输层 。
-
“Tokenizelogin”:如果攻击者嗅探stream量,他们将拥有纯文本的用户名/密码,然后他们可以用这些新的凭据login。 (重播攻击)
-
“以某种方式encryption传输的密码”:在用户login后,攻击者可以嗅探stream量以获取有效的会话ID (cookie),然后使用该密码代替login。如果整个会话受到SSL / TLS保护,则这不是问题。
还有其他更复杂的攻击会影响到这个系统和我们当前的SSL基础设施。 SSLStrip攻击更加详细。 我强烈build议观看Moxie Marlinspike的Blackhat 2009演讲 ,这将导致HTTP-Strict-Transport-Security标准 。
由于您无法在Web服务器上执行SSL,而且您也不是安全专家,因此请查找可以使用的现有安全身份validation服务,并让他们同时处理SSL和处理凭据的复杂性。
特别是,我build议你使用免费的第三方authentication服务,如OpenID 。 他们有PHP的库,其中一个用于CakePHP 。
编辑:(关于风险)
虽然使用第三方安全身份validation服务(使用HTTPS本身)可以在不使用HTTPS(在您的服务器上)的情况下减轻身份validation本身的问题,但并不能完全消除攻击的可能性。
最常见的两种攻击是重放攻击和会话劫持 ,攻击者可以在以后重新使用真正的login会话令牌,或者为自己的恶意目的使用有效的会话令牌。
通过让会话令牌到期,可以缓解重放攻击,最好使用随机数来防止会话重放,并降低会话劫持的风险。 使用随机数,如果成功劫持,合法会话会产生一个错误,因为随机数已经过期(已被使用),所以他们自己的会话不再有效。
如果在与服务器进行传输时不能使用HTTPS对会话令牌进行encryption,则不能完全防止诸如会话劫持或中间人攻击之类的主动攻击。 在某些情况下这可能是可以接受的,例如非商业使用的小用户群的网站。
简而言之,没有SSL端点到端点的encryption,就不可能安全地做到这一点。
其中一个主要的原因是,你不能在浏览器中安全的encryption。 看到这个参考 – JavaScriptencryption被认为是有害的 。
此外,您无法确定证书的来源是否确实是您要与之通话的人。 这意味着没有SSL就没有办法确保没有人在中间的攻击 。
所以不,你不能这样做。
另外,甚至不要尝试。 获取SSL。 你可以得到免费的证书。 主持人通常会给你一个每月几个$$$的专用IP。 而且,如果你真的关心安全性,那么至less要使用一个专用IP地址的虚拟机。
甚至尝试这种做法,最好是默默无闻 ,而最糟糕的是没有。 SSL是一个解决的问题。 为什么不使用该解决scheme。 安全是不是可以猜测。 使用适当的技术。 不要试图发明自己的。 它不会工作…
正如您所build议的那样,每次创build页面时,您都可以生成唯一的标记。 同样的道理将需要与表单数据一起发回,不能重复使用。 如果你可以依靠它被用户启用,你也可以使用JavaScript来保证密码的安全。
但是,这个scheme仍然不安全。 攻击者仍然可以看到穿越线路的一切。 他们可以拦截令牌并在用户提交之前向您发送回复。 或者他们可以等待某人login,窃取该人的凭据(因为他们是通过电报发送的),并且稍后自行login请求。
底线 – 您需要使用HTTPS来保证网站的安全。
您可以使用Javascriptencryption密码并在服务器上解密。
我build议在服务器上生成一个RSA密钥对,并将公钥与定时盐一起发送到浏览器,然后使用Javascript中的公钥对密码进行encryption,并结合salt。
你可以在这里find一个JavaScript的RSA实现
您应该在authenticationcookie中包含IP地址和整个X- FORWARDED -FOR hedaer,以防止cookie在代理后面被盗用。
如果您处理敏感数据,您可以在Javascript中生成一个随机的AES密钥 ,然后将其与RSAencryption的密码一起发送到服务器。
然后,您可以使整个应用程序使用来自单个页面的encryption的AJAX请求,而不是使用auth cookie。
请注意,无法防止没有SSL的活跃中间人攻击。 一个积极的攻击者可以完全用自己的代理取代你的网站,而且没有任何办法来防止这种攻击。 (因为不可能有任何已知的好代码)
您可以使用大多数浏览器支持的HTTP摘要式身份validation,并且不会通过线路清楚地发送密码。
缺点是通过浏览器显示丑陋的login框。 如果您坚持使用表单,那么您可以在表单authentication中实现与HTTP摘要完全相同的协议:发送包含领域和挑战的隐藏字段,并让客户端在JavaScript中添加现时并计算摘要。 这样你就可以使用一个众所周知的,经过validation的繁殖协议,而不是自己动手。
HTTP摘要只需要散列操作。
怎么样HTTP摘要authentication ? 它在发送给服务器之前,通过MD5哈希用户名,密码和一个随机数(等等)来提供安全性。 MD5不是很安全,但是这对于简单的HTTP安全来说是一个很好的方法。
当然,这并不能防止黑客更改信息,但它会保护您的密码。
HTTPS有许多用例,其中大部分用于防御中间人(Man-in-the-the-middle)攻击。 任何有黑客心态的人都会不寒而栗地告诉你,除了已经build立起来的方式之外别无他法。 事实是,仅仅因为你使用TLS(现代HTTPS使用的标准),并不意味着你使用得很好。 另外,仅仅使用TLS并不能防止有人利用已知的弱点。 就像您可能正在寻找创造性的方式来保护您的数据一样,有些人正在寻找创造性的方式来利用您的安全措施。
那么该怎么办?
首先,如果您要放弃TLS,了解它的工作原理是很有帮助的。 这完全是关于握手。
一旦客户端和服务器同意使用TLS,他们就通过握手过程协商一个有状态的连接[7]。 在握手过程中,客户端和服务器就用于build立连接安全性的各种参数达成一致:
- 当客户端连接到请求安全连接的启用TLS的服务器并提供支持的密码套件(密码和散列函数)的列表时,握手开始。
- 从这个列表中,服务器select一个它也支持的密码和散列函数,并通知客户这个决定。
- 服务器以数字证书的forms发回其标识[矛盾]证书通常包含服务器名称,可信authentication中心(CA)和服务器的公共encryption密钥。
- 客户端可以联系发布证书的服务器(如上所述的可信CA)并在继续之前确authentication书的有效性。
- 为了生成用于安全连接的会话密钥,客户端使用服务器的公钥对随机数进行encryption,并将结果发送给服务器。 只有服务器应该能够用它的私钥解密它。
- 从随机数开始,双方产生encryption和解密的密钥材料[矛盾]握手结束,开始安全连接,使用密钥材料encryption和解密,直到连接closures。
如果以上任一步骤失败,则TLS握手失败,并且不会创build连接。
来源: 维基百科
那么,这可能吗? 是。 我被教导任何事情都是可能的。 这可能是昂贵的,但总是可能的。
我想充分披露,我不是一个安全专业,只是一个发烧友。 我不build议将其用于生产级别的项目或除了您自己的教诲以外的任何项目。 你应该明确检查这个SOpost ,它提供了一个很好的解释,在设置自己的安全协议的障碍。
但是,如果你想继续前进,下面是一些想到的想法。 无论您在这个项目中使用哪个指导,这些都是现实。
-
所有主要的现代浏览器都支持HTTPS。 即使在这种情况下,HTTPS加载时间比普通的HTTP要慢。 如果没有大规模生产,很可能你的替代实施将成为安全的一小部分,而速度明显较慢。 除非您使用浏览器function,否则这将成为本地实现的一个缺点,这将使我们回到使用TLS(这是现代HTTPS所使用的function)。
-
如果您在浏览器端使用JavaScript以不可预知的方式encryption密码,而浏览器端没有使用TLS,那么MiTM攻击将非常困难,请不要在那里rest。 您还应该保护来回发送的数据。 否则,被encryption的密码确实是无关紧要的。 当然,攻击者可能不知道bobsmith109的密码,但他不需要它,因为他可以嗅探networking上的每一个活动。 他知道bobsmith109login的次数,大概可以追溯他的IP以及其他任何你敏感的数据。
-
不pipe你采取什么安全措施,都有深度的安全。 所以你可以做的一件事是确保你在数据库中encryption你的数据,同时也需要强密码。
我重申,我不是一个安全专业人员, 强烈地劝阻你,这是为了满足你的好奇心。 如果没有一个非常庞大的安全专业人员为项目贡献数年(如果不是数十年的话),这是SSL / TLS可以夸耀的,那么在天文学上就不太可能创build一个可行的TLS替代品。 也就是说,如果你select了前进的话,一个好的起点是看看上面的握手模型,看看如何在没有TLS的情况下实现这个版本。
我会不愿意在我的post中分享使用HTTPS的大多数现实障碍正在被积极抵制。 最大的成本之一 – 非常接近成为一个非问题。 一个免费的证书颁发机构将在2015年第二季度推出,其中包括Mozilla和Akamai等一些大型的枪支。 这是一篇文章 。
看看“安全远程密码协议” 。
而不是自己来制定它,让我引用他们的网站:
安全远程密码协议执行安全的远程人身临时密码validation,抵御被动和主动networking攻击。
和:
该协议将零知识certificate技术与非对称密钥交换协议结合在一起,并且提供了相对于较强扩展方法(诸如增强型EKE或B-SPEKE)抵抗被盗检验器攻击的显着改进的性能。
尽pipe斯坦福大学没有提供PHP和JavaScript本身的实现,但它们链接到一些第三方实现。
其中一个链接导致“Clipperz” ,这是一个在线密码pipe理器。 它也可以在GitHub上作为社区版本使用。 他们在那里托pipe他们的“javascript-crypto-library” ,它实现了协议和“密码pipe理器”本身,后者包含用PHP和Python编写的后端。
我不能说提取代码的相关部分是多么困难,但也许你可以重用他们的实现(它是根据AGPL许可的)。
编辑2014/10/24:
维基百科关于SRP的文章列举了更多的实现。 相关的PHP / JS:
- srp-client(JS)
- srp-6a-demo(PHP / JS)
您可以尝试使用公钥encryption(也许是GPG)并利用浏览器caching来复制它。
这不是一件安全的事情,即使只是把SSL放在一个复杂的攻击者身上也是不够的,你需要使用HSTS,公钥pipe理等等来考虑今天的安全网站。
其余的答案只是一个思考的食物。
- 创build一个公私密钥对。 保持私人安全。
- 创build一个包含公钥和
encrypt
函数的js文件,find一个安全的encryptionalgorithm。 这个函数应该使用额外的时间戳来encryption给定的string(序列化forms),以避免复制攻击。 - 使用
Cache-Control:public, max-age=31536000
服务此文件Cache-Control:public, max-age=31536000
HTTP标头。 我们试图减轻攻击者何时试图replace脚本。 该文件将始终从浏览器caching中提供。 - 使用
encrypt
function通过Javascript发送所有表单。 用与上面相同的标题服务这些。 - 在服务器端,
decrypt
数据,检查时间戳,如果它仍然有效。 你的事情,如果不是,丢弃它。 - 创build一个cookie标记,只能在很短的时间内使用一次。 如果攻击者抓到一个cookie,他就没有太多的时间去做东西了。 但是,如果攻击者速度够快,那么他可能会将原始用户logging下来。
- 更改每个响应的cookie。 但是,当用户一次发送多个请求,然后以相反的顺序到达时,你会做什么? 哪个cookie有效? 这会以虚假的安全感为代价,产生大量的问题。
任何监听器将无法使用来回的数据,并且在caching到期/用户清除caching之前,他们将无法更改/注入现有的 JS
文件。 但是,任何复杂的攻击者都可以replace整个HTML
文件,这将丢弃我刚刚提到的所有安全性测量。 如果你至less可以通过HTTPS
提供这个文件/表单,那么你可能会放弃它,把它们放在Github页面上或其他任何地方。 但是,如果您将该文件放在其他某个域中,则需要为接收域设置CORS
以使其正常工作。
另一个尝试
一次性密码发送到电子邮件。
- 用户填写他们的电子邮件,点击一个链接,然后发送一个链接到他们的电子邮件与令牌,使他们login。
- 用户点击链接
- 服务器检查令牌,将用户login。
- 像前面的例子一样滚动cookies。
总而言之,无论你做什么,都是不安全的 。 鉴于一个快速,复杂的攻击者,没有任何阻碍。
获取SSL,如果基础设施不支持,请更改它。 如果您的经理不相信SSL,请说服他/她。 不要造成错误的安全感。 根据您的位置保护您的用户数据,您在法律上被要求保护您的用户的数据。
那么让我们来谈谈如何使用SSL来保护网站安全。
没有HTTPS的login,如何保护?
由于您的服务器和您的客户端之间没有安全通道:
- 因为没有安全的渠道,任何人都可以窥探你的stream量。
- 因为任何人都可以窥探这个stream量,所以你是面对MITM攻击的。
- 因为你对MITM攻击是开放的,所以不能保证你的客户会看到一个合法的页面。
- 因为页面是不合法的,你的页面实际上没有被服务(中间的人正在服务页面),所有使用服务器端的技巧都是无用的。
你能做什么? Theorically?
- 客户端和服务器端都需要使用encryption技术来减lesssnooping / MITM。
- 假设你不能握手,
- 假设你的客户已经拥有了你的钥匙,并知道如何说服你的服务器一样的胡言乱语。
- 如何通过HTTP的一些SSL,但包装在一些乱码base64编码的消息?
但是等等…既然你说没有神奇的二进制文件或插件,甚至没有RSA,我不知道这是否可能,除了(一些潜在的非常弱)的内部encryption。
–
在尝试回答之前,我想提一下,这里的其他答案都是关于HTTPS / STS的。 HTTPS是坚定的,可信的,也许是你最好的select – 我相信你已经厌倦了听到它。 现在,我不是安全专家,但是这个问题是我想到的,而且我碰巧创造了一个方法。 我从来没有用过它,我要求所有人尽可能地去打洞。 它只能防止中间人攻击。
这个想法是在没有握手的情况下实现共享的秘密部分,即使这意味着在另一个安全的服务(如电子邮件,假设他们使用TLS来读取它)上捎带。
第1部分:安装
-
也许select一个对称密码,Rijndael。
-
select哈希algorithm,SHA256 / 512是我的最爱。
-
创build一个大的盐,一些随机的数据,理想情况下有点强壮。 512字节也许。 我们称之为GSALT。 (将其视为一个名为GSALT的variables)。 这将是一个全球盐。 可能是好的configuration文件材料。
-
在你的数据库中,用户数据应该包含一个用户名字段,一个userhash字段,一个密码字段,一个salt字段,一个key字段和keyhash字段(加上你想要的任何东西,我只覆盖相关的字段)。 我将解释每个字段应包含的内容:
- 用户名:用户在注册时select的实际用户名。
- salt:随机生成的string,长度至less为32个字符。 我喜欢让他们64.这可能是浪费,但我是偏执狂。 我们称之为LSALT。
- 密码:GSALT +实际密码+ LSALT的散列。 依次排列。
- userhash:应该包含GSALT +用户名的散列。 索引的速度。
- 键:应该包含一个随机string(基本上是另一个盐,但是我们将半公开使用)
- keyhash:包含GSALT +实际密码+密钥的散列。 依次排列。
第2部分:注册新用户
- 在registry单中,提示input用户名,电子邮件,但没有密码。
- 一旦validation和接受,生成一个密码服务器端,并将其发送到他们的电子邮件。
- 在您的数据库中,生成第一步中提到的不同值(userhash,password,salt,key,keyhash等)
第3部分:身份validation
- 用login名包含全局salt。
- 在login尝试中:
- 通过散列GSALT +用户名来创builduserhash
- 通过散列GSALT +密码创build一个passhash
- 发送userhash并通过传送到服务器
- 在接收这些的服务器上:
- find匹配userhash的用户logging
- 从该logging获取密码和盐值,并通过散列密码+用户盐(LSALT)validation此用户名是否具有正确的密码。
- 如果匹配,则用户通过身份validation。 产生一个随机数(一个随机数字或一个体面大小的string,使其不能被猜到)
- 使用keyhash值作为encryption密钥对nonce进行encryption,并在其有效负载中生成一个具有nonce的标记。 此令牌应使用单独的服务器端唯一密钥(请参阅JWTscheme)。
- 发送密钥,encryption的随机数和令牌。
- 客户端收到密钥,encryption的随机数和令牌。
- 客户端哈希GSALT +实际密码+密钥来产生解密现时所需的encryption密钥。
- 丢弃除客户端上的随机数和令牌之外的所有其他值。
- 对于每个客户端请求,使用nonce作为关键字来encryption内容。 用令牌发送encryption内容。 不要encryption令牌。 只需将令牌作为请求数据的单独值发送即可。
- 服务器收到encryption的请求和令牌,解密令牌,然后使用随机数解密请求的内容。
- 服务器生成一个响应,使用随机数对它进行encryption,并将其发送…来回/等等
问题
- 双方的计算都很昂贵。
- 它不能抵御很多其他的攻击,并且可能更容易受到旁道攻击。
- 全球盐基本上是永远的交易:/
- 我不是安全专家,这可能不是密封的。 “不要推出自己的encryptionscheme”是有原因的。
- 一个足够专门的黑客可以build立一个彩虹桌,或者蛮力检查你的哈希密码。
- 这是作弊,因为我们使用电子邮件来规避一个麻烦的地区。
不过,这是一个有趣的思想实验! 我希望它可以帮助某人(特别是如果这意味着推动他们使用HTTPS)
我所见过的最安全的HTTP连接最好的解决scheme是使用md5sum(或其他散列)的Javascript实现来避免以明文forms传输密码。 您可以在Javascript中创build一个窗体onsubmit处理程序,用原始值的散列replace密码字段。 这为不安全的连接增加了适度的安全性,但是依靠浏览器中运行的Javascript来正常工作。
答案是短的,如果你真的关心安全,你总是有不同级别的官僚选项。
绝对安全不存在。 头号瑕疵总是在客户端,与木马和键盘logging器 。 SSL没有帮助。
1) 令牌生成器 :银行使用它们,然后暴雪使用。 它可以是一个设备或应用程序。 那么..这很贵。
2) SMS引脚 。 有趣而又实惠的解决 市场上有很多优惠的价格,每个人都有可以接收的电话。
3)如果你必须使用HTTP,你可以强制第三方oauth服务,如谷歌或Facebook 。 没有令牌生成器,这是最好的。
我想你关心密码到服务器的安全传输? 我的答案是:不要传输密码到服务器:)
事实上,您可能不会传输任何从浏览器(用户)到服务器的身份validation用户,因为正在窥探httpstream量的攻击者也将能够重新传输数据并进行身份validation。
提案:
明显的解决scheme是使用源自服务器的单向,一次性事务validation; 像一个只能使用一次的交易号码。 最终,您仍需要一个安全通道才能将用户的交易号码列表同步。
你可以使用google authenticator ,但是你需要一个安全的通道来设置参数。 如果你认为电子邮件是安全的,这将是一个方法。
我的系统上有同样的问题。 我已经采取了一些步骤来尝试提高安全性,同时又不会由于复杂的机制而影响用户体验。 我注意到,绝大多数用户使用相同的浏览器(但不一定是相同的IP地址),或从几个浏览器(例如桌面或移动设备)login同一台机器。 我决定我可以用它来识别一个模式。
1)在注册过程中,用户需要拥有强大的密码(防止字典攻击),安全问题/答案和标准的电子邮件validation(作为真人的certificate)
2)在login过程中,5次login尝试失败(不是以前)后,将显示一个validation码以防止暴力攻击。
3)最后,我创build了一个包含用户操作系统,浏览器(一般不是版本)和语言的成功login后的用户代理string部分的散列 – 形成一种二级密码。 如果下次login时useragent哈希值显着不同,则会要求用户回答安全问题。 然后,如果回答满意,新的UAstring将被散列并添加到他们的“安全机器”列表中,这样他们就不会再被询问。 这与Steam游戏系统采用的机制类似。
这已经在大约700个用户中使用了一年多,并且还有防止“login共享”的额外好处 – 多个用户为了方便而使用相同的凭证的问题!
试试这个:在login页面的每个请求上,发送一个随机数和一个时间戳。 在发布到服务器时,发送以下四个详细信息:
用户名,密码和明文的时间戳。 然后用分隔符(例如:换行符)连接上述内容,并使用用户密码作为encryption链接块密码模式进行encryption。
在服务器端使用用户名来查找密码并validationencryption的string。
由于密码永远不会被清楚地传送,所以它是安全的,并且可以使用时间戳来避免重新提交相同的数据。
为了避免通过中间人攻击获取会话密钥来劫持会话,密码或密码的哈希值可以由客户端上的应用存储在内存中,并用于生成唯一的会话密钥供服务器validation。
看看OAuth 1.0也不是一个坏主意。
如果您不能使用HTTPS,或者您不想使用HTTPS,请考虑使用jCryption 。 jCryption为通过HTTP请求(POST,GET等)发送的数据提供encryption。
您可以在这里testing技术: http : //www.jcryption.org/#examples
如果你使用的是Firebug,你会看到所有的数据都被encryption了。
它有jQuery库来encryption前端数据和一个PHP库来解密后端的数据。
使用散列机制来存储密码,并且总是比较散列的密码,甚至没有人知道真正的密码。 这是非常简单的,但它是有效的。但是,没有什么是完全安全的,有一些办法打破scurity层。
没有一个trusted third party
很难确保沟通的安全,但是,对于你来说有一些安全的技巧:
不要将用户的敏感信息暴露给公共networking。
每个敏感信息都应该散列好或公钥encryption。 注意:如果select用公钥encryption用户敏感信息,请确保用户validation公钥。 例如,您可以通过短信甚至自动呼叫向用户发送某种公钥指纹。
login成功后生成SHARED SECRET
在安全login事务之后,应该生成共享密钥。 生成过程可以参考SSL Handshake
。 注意:共享密钥一旦生成,就必须再运行。 它唯一的function是在Server
和Broswer
之间encryption/解密数据
那里应该是一个两步validation,以避免重复的攻击
愿这些技巧能帮助你