“永远不要相信用户的输入”是对设计人员和编码人员说的,是进行安全设计和安全编码的重要准则。换句话说,任何输入数据在证明其无害之前,都是有害的。许多危险的漏洞就是因为过于相信用户的输入是善意的而导致的。

文章“我的网络安全观点之六:漏洞无处不在”中的例子中,程序直接引用输入数据作为页面模板文件名装载并显示处理,这是一个典型的信息泄漏的漏洞。还有一种常见的漏洞是直接引用输入数据构造查询数据库的SQL语句,下面举一个例子(稍有黑客常识的人都应该熟悉这个例子):
    以下是一段验证用户密码的程序:
===========================================================================
...
q.SQL.Clear;
q.SQL.Add('SELECT COUNT(*) FROM EMP '
  + ' WHERE CODE = ''' + Request.ContentFields.Values['UserCode'] + ''''
  + ' AND PASSWORD = ''' + Request.ContentFields.Values['Password'] + '''');
q.Open;
if q.Fields[0].AsInteger > 0 then
  //合法用户
else
  //非法用户;
q.Close; 
...
===========================================================================
    攻击者不需要知道合法用户的密码就能直接进入系统,攻击方法是在登录页面的用户名输入框中随便输入一个字符串例如aaa,在密码输入框中输入
1' or '1'='1
按照此输入,程序中的SQL语句变为
SELECT COUNT(*) FROM EMP
WHERE CODE = 'aaa'
AND PASSWORD = '1' or '1'='1'
查询条件变成了恒等式,于是通过了验证。造成这个漏洞的原因在于程序对输入数据未作处理直接将其用于SQL语句。如果程序中某个UPDATE语句或DELETE语句存在类似漏洞,则有可能造成数据丢失。为修补以上漏洞,应该对用户输入数据进行规范性检查和过滤。然后以如下方式进行验证:
===========================================================================
...
sUserCode := 对Request.ContentFields.Values['UserCode']进行规范后的结果;
sPassword := 对Request.ContentFields.Values['Password']进行规范后的结果;
q.SQL.Clear;
q.SQL.Add('SELECT PASSWORD FROM EMP '
  + ' WHERE CODE = ' + QuotedStr(sUserCode));
q.Open;
if q.FieldByName('PASSWORD') = sPassword then
  //合法用户
else
  //非法用户;
q.Close; 
...
===========================================================================
    以上程序中,QuotedStr实际上也是对数据的一种规范处理。
    (注:我会制订关于用户输入数据检查和处理的规范,加进我们的详细设计规范和编码规范)
    
    如果我们能对所有用户输入进行详细的检查,那么软件中的漏洞就会大大减少。因为无论是什么样的漏洞,攻击者要利用此漏洞实施攻击,总要向系统输入一些数据才能实施攻击,堵住了非法和恶意的输入,就堵住了很多类型的攻击。
    
    对于WEB程序开发人员来说,“永远不要相信用户的输入”这条准则可以引申为“永远不要相信客户端信息”,客户端信息包括请求的URL、cookie、提交的表单等,总之TWebRequest的所有属性都不要相信。例如,有的设计者期望通使用客户端的JavaScript脚本进行输入数据检查,在服务端就省略了检查,这种做法是错误的。因为JavaScript可能被浏览器禁用,或者被客户端防火墙禁用,或者某种特殊的浏览器忽略了你的JavaScript,这些都会使客户端JavaScript失效或部分失效。正确的做法是在客户端和服务端都作相同的检查,客户端的检查的目的是为了界面的友好、节省用户的时间,服务端的检查才是为了数据的完整和安全。

有些开发人员会说对输入数据进行如此多的检查会影响性能,实际上,大多数输入检查并不对性能造成大的损害,即使有损害,一个稍慢但是相对安全的系统也比一个快速但容易受到攻击的系统要好。如果客户对你的系统性能不满意,应寻找其它途径提高性能,不要通过减少安全检查来提高性能,因为当客户的系统因为漏洞被攻破以后,你面临的就不是几句抱怨,而是一场灾难了。

对待用户输入,实际上也是一个转变观念的问题,就像我在“我的网络安全观点之五:敌人无处不在”中描述的,周围的世界不可思议的充满了敌意,我们必须怀疑一切,以前那种充满善意和无知的程序运行环境一去不复返了,取而代之的是恶意和数不清的黑客工具。

永远不要相信用户的输入相关推荐

  1. 要求用户提供输入,直到他们给出有效的答复

    本文翻译自:Asking the user for input until they give a valid response I am writing a program that accepts ...

  2. android edittext输入邮箱,[Android教程]EditText怎样限制用户的输入?数字/字母/邮箱

    有输入必有验证.为了防止用户随便输入确保提交数据的合法性,程序不得不在文本输入框(EditText)中增加限制或验证. 关于输入类型有数字.字母.邮箱.电话等形式,这些具体得根据业务来.那么Andro ...

  3. win10创建新的计算机用户名和密码忘了,Win10 2004中要使用本计算机用户必须输入用户名和密码选项不见了如何恢复?...

    大家可能也会遇到这个问题,发现打开用户账户窗口的时候,原先"用户账户"配置界面中的"""要使用本计算机,用户必须输入用户名和密码"选项不见了 ...

  4. 【Linux】14.ubuntu忘记root密码、用户密码输入次数过多锁住的问题

    忘记root密码.用户密码输入次数过多锁住的问题 1.忘记root密码 参考 https://www.linuxidc.com/Linux/2016-05/131256.htm (1) 忘了root密 ...

  5. Java黑皮书课后题第5章:*5.42(金融应用:求销售额)如下重写编程练习题5.39:①使用for循环替代do-while循环②允许用户自己输入COMMISSION_SOUGHT而非将它固定为常量

    5.42(金融应用:求销售额)如下重写编程练习题5.39:①使用for循环替代do-while循环②允许用户自己输入COMMISSION_SOUGHT而非将它固定为常量 题目 题目概述 编程练习题5. ...

  6. python 输入10个整数_2019-07-18 python练习:编写一个程序,要求用户输入10个整数,然后输出其中最大的奇数,如果用户没有输入奇数,则输出一个消息进行说明。...

    #方法1:有缺陷 # -*- coding:utf-8 -*- ''' @project:pycharm-project @auther:lenovo @file:10-max-odd.py @IDE ...

  7. php的toast,使用toast组件实现提示用户忘记输入用户名或密码功能

    微信小程序现在越来越流行,所需要的开发功能越来越多,本文主要介绍了微信小程序使用toast消息对话框提示用户忘记输入用户名或密码功能,结合实例形式详细分析了toast组件实现消息提示功能的相关操作技巧 ...

  8. SwiftUI3.0用户登录输入非空校验经典案例

    SwiftUI3.0用户登录输入非空校验经典案例 在oc和swift里面,通过UITextFiled的代理方法,可以实施监听到用户输入的每个字符,使用正则表达式,进行判断,是否合法.在swiftUI通 ...

  9. 使用DataGridView数据窗口控件,构建用户快速输入体验

    使用DataGridView数据窗口控件,构建用户快速输入体验 在"随风飘散" 博客里面,介绍了一个不错的DataGridView数据窗口控件<DataGridView数据窗 ...

最新文章

  1. ACE中的Proactor介绍和应用实例
  2. 【推荐系统入门】一窥推荐系统的原理
  3. 启动spark集群,JAVA_HOME is not set
  4. 设置SpringMVC默认首页启动
  5. for循环删除集合陷阱
  6. 【5月8 】NVIDIA 迁移学习工具包(TLT)最佳实践
  7. iphone/ipad 横竖屏切换
  8. Nginx 412 Precondition Failed
  9. MATLAB制图代码
  10. vue项目中获取今天,昨天,明天时间方法
  11. malloc失败的一个原因
  12. Java8流处理正序倒序排序
  13. Power bi 4.14 桑基图
  14. FLASK RESTFUL TOKEN用户验证笔记
  15. WordCount的理解与MapReduce的执行过程
  16. 记录一下大三暑假来广州的实习生活
  17. 如何正确使用步道乐跑
  18. 华为设备Ping命令
  19. 在excel图表上添加数据标签
  20. CSS 网站小图标 雪碧图

热门文章

  1. 【Android APT】编译时技术 ( 编译时注解 和 注解处理器 依赖库 )
  2. 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 修改 7zr 交叉编译脚本 Android.mk | 交叉编译 lib7zr.so 动态库 )
  3. 【Android Protobuf 序列化】Protobuf 使用 ( protobuf-gradle-plugin 插件简介 | Android Studio 中配置插件 | AS 中编译源文件 )
  4. 【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)
  5. 【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )
  6. 微信小程序中换行,空格(多个空格)写法
  7. iOS开发-登录界面开发(6)Toast-Swift的使用-Swfit4.1_Xcode9.3.1
  8. c# C++接口封装 汽车模拟仿真
  9. [翻译]No.9352 SharePoint Pages(1)之SharePoint页面体系架构
  10. 从JVM看类的加载过程与对象实例化过程