/catalog/296695a3fdd74f71b4ced1996c9b6856//Document/304898482892869.html/Document/304549706600517.html/Document/304188584996933.html/Document/303818784497733.html/Document/302700517105733.html/Document/302416475320389.html/Document/302077848256581.html/Document/301288627347525.html/Document/300279638184005.html/Document/274792263872581.html/Document/273024381308997.html/Document/272683642789957.html/Document/272351623921733.html/Document/271961406242885.html/Document/271560844214341.html/Document/270477420015685.html/Document/269881559916613.html/catalog/c51244b85e704db9a2a34ca396e9fe27//Document/297463116619845.html/Document/296410729726021.html/Document/294281412902981.html/Document/289614801383493.html/Document/289336711553093.html/Document/288989717336133.html/Document/267736666357829.html

安全测试国家标准解读——数据清洗

下面的系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解,该标准是2020年4月28日,由国家市场监督管理总局、国家标准化管理委员会发布,2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理,大家感兴趣的话可以自己去下载下来学习一下,里面有一些最佳实践是比较好的。

本标准从程序安全和环境安全两个方面提出了提升应用安全性的编程最佳实践。其中,程序安全部分描述软件在资源使用、代码实现、安全功能方面的安全性规范,环境安全部分描述软件的安全管理配置规范。本文我们针对安全功能实现的数据清洗部分进行解读。

应用软件安全编程指南

首先我们来看一下安全功能实现这一部分,这一部分也是我们最经常用到的,主要包括:数据清洗 、数据加密与保护、访问控制 、日志安全 。

安全功能实现

我们先来看一下数据清洗,主要包括输入验证和输出净化这两个方面。
【数据清洗-输入验证】
输入验证部分我从中间摘取了最常见的几条标准。
1. 验证所有输入数据的安全性,包括:数据类型、数据长度、边界值检查,验证文件的安全性。
我们所有的输入数据都是不可信的,都是需要进行验证的。

2. 特别关注如下场景的数据验证:
(1)验证来自HTTP请求中的所有数据:表单域、URL、cookie、HTTP头及URL自身传入。
(2)验证来自重定向输入的数据。
(3)对来自命令行、环境以及配置文件的输入进行校验。
第三条尤为重要,我们在做代码审计项目的过程中经常遇到这样的问题。开发人员认为,从命令行输入的操作一般是由运维人员去操作的,还有一部分是开发人员来操作的。
从人员级别上来看是比较可靠的,所以这样的问题他们不予考虑了。
但是从安全测试的角度来看,只要是人为输入的信息我们都认为是不可信的。包括从环境和配置文件中获取的信息也都认为是不可信的。如果配置文件被篡改的话,程序就存在很大的风险了。

建议从配置文件本身做防护,或者对配置文件中的数据进行校验。


(4)对发送给文件系统、浏览器、数据库或其他系统的命令进行验证,防止采用不可信来源的数据构建命令。

3. 对输入数据进行过滤或标准化处理,然后进行验证。
下面这个图是针对输入验证的示例及与标准正文的对照关系表,最左侧是漏洞示例的内容,中间是语言,右边是对应的本标准的章节号。

针对输入验证的示例及与标准正文的对照关系表

下面是有关于SQL注入的规范和不规范代码示例,这个也是比较常见的,代码审计的时候通过肉眼就能看出来,利用工具也可以扫描出来。我们可以通过SQLmap等工具进行渗透验证。

SQL注入的规范和不规范代码示例

我们可以看到在这个SQL语句中,通过“+”连接了一个字符串,这样我们在用Statement来执行的时候,如果username中加了一些执行的字符,比如加了一个“; delete db user”,这个SQL语句就会执行两条,第一条是select,第二条就是删库。


下面这张图是一个规范的代码,用的PreparedStatementstmt,一种预编译的方式。把参数先用?占位符占位,把这条SQL语句进行预编译,在执行的时候再设置它的值。这样它的值就是一个参数,在一定程度上可以规避SQL注入的漏洞。

但是这种措施也只能适用于一部分,像表名、表字段这类就不适合使用这种方式,还需要用别的方式来处理。

安全规范的代码

这是为大家举的输入验证的例子,标准上还有很多,大家可以去看一下。
【数据清洗-输出净化】
输出净化我为大家精选了常用的3条。

  1. 除非明确对目标编译器是安全的,否则对所有字符进行编码。
    输出之前要对所有字符进行编码,不要让输出的内容以命令的形式输出。

  2. 关注SQL、XML和LDAP查询语句以及操作系统命令,这些命令可能存在潜在的危险字符,需进行语义净化。

  3.  禁止将URL重定向到用户可控的不可信站点。

输出净化这部分最主要的漏洞就是XSS,这个也是OWASP TOP10中一个常见的漏洞。这个漏洞一共有三种,反射型、DOM型和存储型。影响比较大的就是存储型的。

规范和不规范代码示例

规范和不规范代码示例

下图也是规范中给到的一个例子,JSP代码从HTTP请求中读取的用户名直接显示在网页中了,如果这个时候黑客在用户名中添加一个<script>alert('xxx')</script>字段的话,在显示的时候就会产生XSS攻击。

安全规范示例

这个通过代码扫描工具也可以扫描出来,也可以通过渗透测试进行测试。这个问题应该如何避免呢?


可以对用户的输入进行合理验证,对特殊字符进行过滤,如<、>、'、<script>等。这里大家要注意,在过滤的时候,要进行格式归一,比如大小写之类。


有些框架会对输出进行编码,像OWASP ESAPI有些编码方式,可以直接利用这些框架去规避。


另外,我们用的Spring Boot、Spring MVC里面也有一些过滤器,可以专门来做XSS的过滤。


也可以通过设置HttpOnly的属性,避免攻击者利用跨站脚本漏洞进行Cookie劫持。

后面的文章会继续对《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》的其他部分进行解读,欢迎继续关注。