永远不要相信用户的输入

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

    文章“我的网络安全观点之六:漏洞无处不在”中的例子中,程序直接引用输入数据作为页面模板文件名装载并显示处理,这是一个典型的信息泄漏的漏洞。还有一种常见的漏洞是直接引用输入数据构造查询数据库的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失效或部分失效。正确的做法是在客户端和服务端都作相同的检查,客户端的检查的目的是为了界面的友好、节省用户的时间,服务端的检查才是为了数据的完整和安全。

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很好,以下是一个史上最佛系的程序: ``` while True: try: num = float(input()) print(100 / num) break except: pass ``` 这个程序会不停地等待用户输入,但是不会给出任何提示。当用户输入一个数字后,程序会尝试将其转换为浮点数,并计算 100 除以该数字。如果计算正常,程序会输出结果并退出。如果计算出错,程序会继续等待用户输入,直到得到一个可以正常计算的数字。 ### 回答2: 编写一个最佛系的程序,听上去似乎是一项很简单的任务,但它并不是那么容易实现。 我们需要一个程序,它能够在用户输入时,实现无提示的操作,并且在获得用户输入后,计算100除以输入值,并输出结果,同时不会报错。 首先,我们需要明确的是,要实现无提示操作是比较困难的。因为,在通常情况下,程序执行时,都会输出一些信息,以便与用户进行交互。但我们目标是最佛系的程序,所以我们需要把这些提示信息全部去掉。 接下来,我们需要计算100除以输入值,并且不会报错。这个需要使用异常处理,否则当用户输入0时会抛出一个 division by zero 的异常。在Python中,我们可以使用try-except语句来实现异常处理。可以这样写: ```python try: num = int(input()) result = 100 / num print(result) except ZeroDivisionError: exit() ``` 在这段代码中,我们首先使用 input() 函数获取用户输入,并且使用 int() 函数将其转换成整型,接着计算100除以输入值。 如果输入为 0,那么我们就会遇到 ZeroDivisionError 异常,这时候程序就会退出。如果输入的是其他值,则程序会正常计算并输出结果。 最后,我们需要使程序在输出结果后自动退出。在Python的解释器中,只需要调用 exit() 函数即可。那么,完整的程序就是: ```python try: num = int(input()) result = 100 / num print(result) except ZeroDivisionError: exit() else: exit() ``` 当然,最佛系的程序不仅仅是实现功能,还需要考虑代码的可读性和可维护性。所以,我们仍然需要适量地添加注释,并且优化代码的结构和风格。 ### 回答3: 编写一个史上最佛系的程序需要关注用户体验和程序的健壮性两个方面。 首先,为了实现用户输入时无提示,需要使用 Python 内置函数 input() 来获取用户输入。然后,为保证代码的稳定性,需要使用异常处理模块来避免程序在用户输入非数字时崩溃。最后,在计算100除以输入值之后,程序需要无条件退出。 下面是程序的具体实现: ``` while True: try: num = float(input()) result = 100 / num print(result) break except: pass ``` 首先,程序进入一个无限循环中。接着,使用 try... except... 语句,尝试将用户输入的字符串转换为浮点数类型。如果转换失败,就会执行 except 子句,其中的 pass 指令表示不做任何处理,直接进入下一次循环。如果转换成功,那么就会执行计算 100 除以输入值的操作,并输出结果,然后使用 break 指令退出循环并结束程序。 由于我们在 except 语句中什么也没有做,这个程序不会输出任何提示信息或错误信息,也不会报任何错误。这就是最佛系的程序设计了:它既简单稳定,又让用户无感知获得计算结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值