开发反模式 - 明文密码

article/2025/11/5 13:31:52
开发反模式 - 明文密码

一、目标:恢复或重置密码

  每个有密码的程序都会碰到用户忘记密码的情况,现今大多数程序都通过E-mail的回馈机制让用户恢复或者重置密码。这个解决方案有一个前提,这个服务有一个前提,就是这个用户能够访问他在注册时留下的邮箱。

二、反模式:使用明文存储密码

  在这种恢复密码的解决方案中,很常见的一个错误是允许用户申请系统发送一封带有明文密码的邮件。这是数据库设计上一个可怕的漏洞,并且会导致一系列安全问题,可能会使得未取得授权的人获得系统访问权限。

  1、存储密码

  首先我们设计一张表如下:

  19164644-3d6ca6ceff7f421792e85b7a0dbb6441.jpg

  类似于这张表,我们插入一条记录的SQL语句如下:

INSERT INTO Account (AccountId,AccountName,Email,Password)
VALUES(100,'admin','admin@126.com','123456')

  使用明文存储密码或者使用明文在网络上传递密码是不安全的。如果攻击者能够截获你用来插入密码的SQL语句,他们就能直接获得密码。在更新密码或者验证用户是否输入正确的密码时这么做,也会导致同样的密码,黑客可以通过下面这几种方法盗取用户密码:

  •   在客户端和服务器端数据库交互的网络线路上截获数据包。这样做比你想象的要容易得多。很多软件能够做到这一点,例如:Wireshark。
  •   在数据库服务器上搜索SQL的查询日志。要这么做的前提是,黑客能够访问到数据库所在的服务器,假设他们真的能登录上服务器上,他们就可以查看那些带有SQL语句的数据库执行日志。
  •   从服务器或者备份介质上读取数据库备份文件内的数据。你的备份文件妥善保管了吗?你在回收或者丢弃备份设备之前彻底清理干净里面的数据了吗?

  2、验证密码

  大多数时候,我所看到的认证查询是将AccountId和Password两列同时放在WHERE子句里进行匹配查找:

  SELECT * FROM AccountWHERE AccountName = 'admin' AND Password = '123456789'

  当账号不存在或者用户输入的密码不正确时,整个查询返回空。你的程序无法区别是账号不正确还是密码不正确。最好是使用一个能区分这两种情况的查询方法,那样就可以根据错误合适地选择处理方式了。

  比如,当发现在短时间内同一个账号有很多失败的登陆请求时,你可能会想暂时冻结这个账号,因为这可能是一次恶意攻击。然而,所面临的问题是你使用的查询语句没办法区分到底是用户名输错了还是密码输错了。

  3、在E-mail中发送密码

  由于密码在数据库中是以明文形式存储的,你可以很简单地在程序中获取密码:

SELECT AccountName,Email,Password FROM Account
WHERE AccountId = 100

  随后你的程序就可以根据用户的请求将密码发送到用户的邮箱里,内容如下:

From : xxx.com
To : admin@126.com
Subject : Password Request
你名为"peter"的账户请求密码提醒
你的密码是"123456"
点击链接登录你的账户:
http://www.xxxxx.com/login

  将明文密码通过邮件发送是非常严重的安全隐患。E-mail可能会被黑客劫持、记录或者使用多种方式存储。就算使用安全协议查看邮件,收发邮件的服务由值得信赖的管理员维护,也不一定能够保证安全。由于E-mail的收发都需要经由网络层传输、数据可能会在其他路由节点上被截获。同时,如果用户的E-mail被破获,那么用户的账号密码也随之沦陷。

三、识别反模式

  任何能够恢复你的密码或者将你的密码通过邮件以明文或可逆转加密的格式发给你的程序,都必然犯了本文的反模式。如果你的程序可以通过一个合法的方式获得用户的明文密码,那么黑客也同样可以。

  1、合理使用反模式

  并不是所有的程序都有被攻击的风险,也不是所有的程序都有敏感的需要保护的信息。比如说,一个可能只有靠几个可靠的内部人员访问的内部程序,认证机制就可能足够了。在那些非正式的环境中,一个简单的登录框就已经足够了。额外简历一个强验证系统可能并不合理。

四、解决方案:先哈希后存储

  1、理解哈希函数

  使用哈希函数对原始密码进行加密,哈希是指将输入字符转换为另一个新的、不可识别的字符串函数。使用哈希函数后,连原始输入串的长度也变得难以猜测了,因为哈希函数返回的字符串的长度是固定的。

  目前比较可靠的是SHA-256算法。

  MD5是零一个流行的哈希函数,产生128位哈希串。MD5也被证明是弱加密,因此你最好不要用它来加密密码。

  2、在SQL中使用哈希  

  下面对Account表进行重定义。SHA-256总是一个64字节的字符串,因此这一类型可以改成是固定长度CHAR。

  在SQL Server中,提供了一个方法,让你可以随意调用常用的哈希函数:hashbytes,由于SHA-1在2010年之前是美国国家标准和技术协会的标准,在2010年之后才逐步取消SHA-1的标准,随之跟上的是SHA-225、SHA-256、SHA-384、SHA-512。所以,在我的SQL Server2008中,并没有这一支持。本处仅仅以SHA-1,MD5作为示例(后面也是):

--SHA1
SELECT hashbytes('sha1','123')
--MD5
SELECT hashbytes('md5','123')

  3、给哈希加料

  如果你使用哈希串替代了原始代码,然后攻击者获得了对数据库的访问权限(他翻了你的额垃圾桶,找到了被丢弃的备份CD),他仍旧可以通过试错法获取用户密码。要猜出密码可能会花很长时间,但他可以预先准备自己的数据库-存储可能的密码和对应的哈希串,然后和从你的数据库找到的哈希串进行比较。只要有一个用户选择了字典中存在的单词,攻击者就能够很轻易地通过搜索两边的哈希值来找到对应的密码原文。他甚至可以直接用SQL来做这件事。

  假设它有一张字典表,里面存储了很多密码字符串与加密后的字符串:

  CREATE TABLE DictionaryHashes(password VARCHAR(100),password_hash CHAR(64));

  查询语句:

SELECT a.AccountName,h.Password
FROM Account AS a JOIN DictionaryHashes AS h
ON a.password_hash = h.password_hasn

  防御这种"字典攻击"的一种方法是给你的密码加密表达式加点佐料。具体方法是在将用户密码传入哈希函数进行加密之前,将其和一个无意义的串拼接在一起,即使用户选择了一个在字典中存在的单词作为密码,对加料密码进行哈希得到的串是不太会出现在攻击者的哈希数据库中的,你可以发现增加了随机串得到的哈希值和原始值是不一样的:

  19182914-65cb8848c5b0419d8783ebe0d36dff09.jpg

  每个密码都应该配上不同的随机串,这样攻击者就必须为每个密码都创建一个新的哈希字典。然后他就会回到起点上,因为破解数据库中的密码所花的时间和靠猜达到目的的时间差多。

  佐料的合理长度应该是8个字节。你需要为每个密码随机生成佐料。这样防止黑客破解了一个就几乎等于破解了全部。

  从哈希值恢复密码的一种更优雅的技术叫做彩虹表,它的性能让人吃惊,但引入随机字符串也能防御这种技术。

  4、在SQL中隐藏密码

  现在,你在存储密码之前已经有了一个强哈希函数来对密码进行加密,并且使用了随机字符串来阻止字典攻击,你可能认为这样已经足够安全。但是,密码还是会在SQL表达式中以明文中出现,这意味着如果攻击者截获了网络通信的数据包,或者记录了相关的查询语句的日志给到了错误人手里,密码就泄露了。

  只要不将明文密码放到SQL查询语句中,就能避免这种类型的泄露。你所需要做的就是在程序代码中生成密码的哈希串,然后在SQL查询中使用哈希串。这么做的好处是,几时攻击者截获了数据包,它也没有办法将哈希反转成他所需要的密码。

  也就是说,在C#中加密之后,再在SQL语句中执行。

  在网络程序中,还有另一个地方是攻击者有机会截获网络数据包的:在用户浏览器和网站服务器之间,当用户提交了一个登录表单,浏览器将用户的密码以明文形式发送到服务器端,随后服务器端才能使用这个密码进行之前所介绍的哈希运算。你可以通过在用户的浏览器发送表单数据之前就进行哈希运算来解决这个问题。但是这个方案有一个问题,就是你需要在进行正确的哈希运算之前,还要通过别的途径获得和这个密码相关联的佐料,这部分最好放到服务器端进行。或者在浏览器向服务器端提交密码表单时,使用安全的HTTP(https)连接。

  浏览器端加密一次,服务器端添加佐料再加密一次这个方法也不错。

  5、重置密码,而非恢复密码

  现在密码已经以一个更安全的方法存储了,但是还有一个问题需要解决,就是帮助那个忘记密码的用户找回密码。由于现在数据库中存着的密码是哈希串而不是原始密码,你已经无法恢复他们的密码了。你没有办法比一个攻击者更快速地反转一个哈希值。但是可以允许用户用别的途径获得访问权限。

  方案1

  当用户忘记他们的密码,请求帮助的时候,程序发送一封带有临时生成密码的邮件给用户,而不是直接发给它自己的密码。

  邮件内容如下:

From:admin
To:admin@126.com
Subject:password reset
你要求重置你账户的密码。
你的临时密码是"admin123",
1个小时之后,这个密码将不能使用,
点击如下链接直接登录你的账号并设置你的密码:
http://www.xxx.com/login

  方案2

  在数据库记录下这个请求,并且为其分配一个唯一的令牌作为标识,而不是发送带有新密码的邮件

  CREATE TABLE PasswordResetRequest(token CHAR(32)  PRIMARY KEY,account_id intexpiration TIMESTAMP NOT NULL,FOREIGHKEY (account_id) REFERENCES Account(account_id))SET @token = MD5('admin' || CURRENT_TIMESTAMP);INSERT INTO PasswordResetRequest(token,account_id,expiration)VALUES(@token,123,CURRENT_TIMESTAMP + INTERVAL 1 HOUR)

  随后,你可以在E-mail中包含这个令牌,你也可以使用别的途径发送这个令牌,比如短信,只要能将消息送达到这个请求重置密码的账号所有者即可。使用这种方法,如果一个陌生人非法地请求一次密码重置,系统指挥发送E-mail给这个账号的实际拥有者。

  密码重置页面临时链接邮件:

From:admin
To:admin@126.com
Subject:password reset
你要求重置你账户的密码。
在1个小时内点击下面连接来改变密码
1个小时之后,这个链接将不能使用
http://www.xxx.com/reset_password?token=f5kajkjkdsjfs1dnjpoqw

  当程序收到一个重置密码页面发来的请求,令牌的值必须存在于密码重置请求表中,并且该执行的过去时间点必须是一个将来的时间点而不是过去的时间点,同时,该行的Account_id引用Account表,因此,这个令牌被约束为只能重置一个指定的账号。

  当然,如果其他人访问了这个页面,也会造成问题。可以通过一些简单的方法来减小风险,比如这个特殊页面的有效期非常短,并且这个页面上不会显示哪个账号的密码要求被重置。

posted on 2013-10-19 19:00  逆心 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/kissdodog/p/3378176.html


http://chatgpt.dhexx.cn/article/lIXSaKaQ.shtml

相关文章

MD5明文密码加密

MD5 一、加密缘由 首先看一下未使用MD5加密的数据库 这样的话如果黑客攻击数据库的时候得到数据库的资料(主要密码)就会导致用户的财产等受到危害,所以需要对密码进行加密操作 二、加密的算法MD5 2.1、运用了单向加密算法(下…

Unity基础: 对Anchors锚点的使用

在UI对象上是用RectTransform组件来控制位置和大小的,在RectTransform中有一个Anchors属性。Anchors属性可以将当前对象的四个角锚点定位到父对象的某个位置,并且Anchor还允许子对象的宽高随着父对象的宽高一起拉伸。 上面一个示例中显示的就是将一个Ima…

(笔记)yolov5自适应anchors

训练一开始会先计算Best Possible Recall (BPR),当BPR < 0.98时&#xff0c;再在kmean_anchors函数中进行k 均值和遗传学习算法更新anchors。 情况一&#xff1a; 在进行yolov5训练的时候&#xff0c;会输出&#xff1a; Analyzing anchors... Best Possible Recall (BPR…

Roson讲Qt#16 QML中的anchors(锚)

QML中有一个数据类型叫Item&#xff0c;Item里面有很多属性&#xff0c;其中一个就是anchors. anchors翻译过来叫“锚”&#xff0c;锚可能不好理解&#xff0c;在我看来&#xff0c;可以把anchors当成是一个控件浓缩而成的一个点&#xff0c;可以通过设置点的上下左右等属性来…

Qml基于锚(anchors)的布局

锚(anchors)布局&#xff0c;每一个项目都可以认为有一组无形的锚线 left,horizontalCenter,right,top,verticalCenter,baseline和bottom. 如上图&#xff1a;图中没有显示baseline&#xff0c;它是一条假想的线&#xff0c;文本坐落在这条线上。对于没有文本的项目它与top相同…

RPN之生成anchors

看不懂anchor生成方法&#xff0c;就看不懂参数。 faster_rcnn的anchors生成 在这里我就不看faster_rcnn的anchors生成源代码了&#xff0c;我们用numpy自己去实现&#xff0c;在128*128大小的图片中生成anchors. 开始上代码 import numpy as np import matplotlib.pyplot …

Qml anchors锚点布局

关于qml的锚点布局的一些分享&#xff0c;并不能算是教学之类的。 锚点布局会自动设置宽度高度&#xff0c;并且优先级比 width height更高 import QtQuick 2.13 import QtQuick.Window 2.12 import QtQml 2.13Window {width: 640height: 480visible: truetitle: qsTr("a…

yolo_anchors.txt超参数值设置

keras-yolov3在训练自定义图片集之前&#xff0c;设置合理的yolo_anchors.txt值&#xff0c;有利于模型训练的收敛&#xff0c;一般都带有默认的参数如下&#xff1a; 在实际项目中&#xff0c;yolo_anchors的值可以根据kmeans.py计算获取&#xff0c;通过聚类得到最佳anchors数…

QML之anchors锚布局

QML的布局方式一般采用两种&#xff0c;一种就是直接设置&#xff0c;X与Y坐标的值。一种是采用相对位置布局&#xff0c;anchors锚布局。使用锚布局的能够使界面更紧凑&#xff0c;更有整体化。我个人相对比较喜欢使用锚布局&#xff0c;选取一个最合适的参考点&#xff0c;其…

YOLOV5源代码学习之check_anchors()函数

该函数主要在train.py中调用 为了方便直观的阅读代码&#xff0c;对代码中的变量值进行了输出 def check_anchors(dataset, model, thr4.0, imgsz640):# Check anchor fit to data, recompute if necessaryprefix colorstr(autoanchor: )print(f\n{prefix}Analyzing anchors.…

QML入门教程(3): anchors的用法

QML的布局方法是anchors,锚。 例如界面上四个按钮,可以用绝对坐标 (x, y) 设置他们的位置, 代码如下: import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5Window {visible: truewidth: 320height: 480title: qsTr("Hello World")co…

目标检测2——借Detectron2源码理解Anchors与RPN

文章目录 1.Regionn Proposal Network背景2.Regionn Proposal Network的结构3.Anchors4.Regionn Proposal Network的训练参考资料 欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 1.Regionn Proposal Network背景 RPN&#xff0c;Region …

QML基础:锚anchors

正文 除了传统的Grid、Row和Column外,Qt Quick还提供了一种使用锚点的方法来布局。可以将每个元素视为具有7条不可见的“锚定线”的集合:left、horizontalCenter、right、top、verticalCenter、baseline和bottom。 baseline(上图未展示)对应于文本所在的虚线。对于没有文…

细说目标检测中的Anchors

本文转载自AI公园。 作者&#xff1a;Raghul Asokan 编译&#xff1a;ronghuaiyang 导读 给大家再次解释一下Anchors在物体检测中的作用。 今天&#xff0c;我将讨论在物体检测器中引入的一个优雅的概念 —— Anchors&#xff0c;它是如何帮助检测图像中的物体&#xff0c;以及…

anchors布局

anchors布局 import QtQuick 2.2 import QtQuick.Window 2.2 Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Rectangle {width: 300;height: 200;color: "blue";Rectangle {id: rectl;anchors.left: parent.left;anchors.leftMar…

PDU Session Anchors

在同一时刻&#xff0c;UE可以建立多条到同一个DN或不同DN的PDU会话&#xff1b;建立到同一个DN的多个PDU会话时&#xff0c;通过不同的UPF&#xff1b;每条PDU会话对应的SMF可以不同。 为了支持到DN的可选择路由功能或支持SSC mode 3模式&#xff0c;SMF可以控制PDU session的…

kmeans++聚类生成anchors

kmeans聚类生成anchors 说明 使用yolo系列通常需要通过kmeans聚类算法生成anchors&#xff0c; 但kmeans算法本身具有一定的局限性&#xff0c;聚类结果容易受初始值选取影响。 因此通过改进原kmeans_for_anchors.py实现 kmeans聚类生成anchors。具体实现如下&#xff1a; i…

anchors如何获得_Yolov3通过k-means聚类得到自己数据的anchors

本文代码参考: https://github.com/lars76/kmeans-anchor-boxes Yolov3中默认的9个anchors是作者通过对voc数据聚类得到的。 anchors 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 不过&#xff0c;当我们训练自己的数据时&#xff0c;如果也采用默认的anchors&#xff0c;可…

Unity 锚点 Anchors

锚点介绍 锚点是Rect Transform组件中的属性&#xff0c;用于描述当前物体相对于父物体的对齐方式。 选中一个UI元素&#xff0c;就会显示其父物体的矩形框以及相对于父物体的锚点。 锚点只能位于父物体的矩形框之内。 锚点表现为四个相对出现的小三角形&#xff0c; 它们时而…

QML anchors 锚布局

锚布局 锚布局有7种锚线 anchors.leftanchors.rightanchors.topanchors.bottomanchors.horizontalCenteranchors.verticalCenteranchors.baseline 5种锚边距 anchors.leftMarginanchors.rightMarginanchors.topMarginanchors.bottomMarginanchors.margins 3种锚偏移 anchor…