精华内容
下载资源
问答
  • 启动和停止SQL Server服务三种形式

    千次阅读 2019-01-15 21:48:59
    身份验证模式有两:Windows身份验证和SQL Server身份验证 配置身份验证模式步骤: (1)对象资源管理器中单击右键—>安全性—>配置身份验证模式 (2)修改sa登陆密码—>直接找安全性—>登录名—>sa—>右键—>...

    1、后启动服务:
    后台启动服务
    计算机—>右键—>管理—>服务和应用程序—>服务—>sql server(MSSQLSERVER)
     
    2、SQL Server配置管理器启动服务
    开始—>安装路径—>配置工具—>sql server配置管理器


    3、在运行窗口中使用命令启动和停止服务
    Windows(键)+r
    启动SQL Server服务:net start mssqlserver
    停止SAL Server服务:net stop mssqlserver

     

    身份验证模式有两种:Windows身份验证和SQL Server身份验证
    配置身份验证模式步骤:
    (1)对象资源管理器中单击右键—>安全性—>配置身份验证模式
    (2)修改sa登陆密码—>直接找安全性—>登录名—>sa—>右键—>属性
    (3)启用sa账户—>直接找安全性—>登录名—>sa—>右键—>属性—>状态—>启用
    (4)重新启动服务—>对象资源管理器上单击右键—>重新启动


    使用SQL语句创建数据库
    USE maste--当前指向的操作的数据库
    GO
    Create DATABASE E_Market
    ON PRIMARY  --主文件组
    (
    NAME=’E_Market_data’,--逻辑文件名
    --物理文件名
    FILENAME=’H:\project\E_Market_data.mdf’,
    SIZE=5MB,--初始大小
    MAXSIZE=100MB,--最大容量
    FILEGROWHE=15%--增长率
    )
    LOG ON  --日志文件
    (
    NAME=’E_Market_log’,
    FILENAME=’H:\project\E_Market_log.ldf’,
    SIZE=5MB,
        FILEGROWTH=0—未启动自动增长
    )
    GO
    Select *FROM sysdatabases  --查询数据库


    使用SQL语句删除数据库
    --删除一个名称为E_Market的数据库
    Drop DATABASE E_Market

    --检查想要删除的数据库是否存在
    IF EXISTS(Select * FROM sysdatabases Where name=’ E_Market’)
    Drop DATABASE E_Market

    使用SQL语句创建登录名及为用户赋予权限
    --创建登录名
    USE master
    GO
    Create LOGIN pbMaster WITH PASSWORD=’123456’
    GO

    --创建数据库用户
    USE E_Market
    GO
    Create USER MasterDBUser FOR LOGIN pbMaster
    GO

    --为MasterDBUser赋予查看、新增、修改的操作权限
    USER E_Market
    GO
    CRANT Select,Insert,Update ON UserInfo TO MasterDBUser
    GO

    --将Update权限进行回收
    USER E_Market
    GO
    REVOKE Update ON UserInfo TO MasterDBUser
    GO
     

    展开全文
  • UTF-8非最短形式及编码安全问题

    千次阅读 2017-01-13 23:59:46
    0x00: 前言近日接连几次接触到关于UTF-8的non-shortest form的安全问题,即UTF-8的非最短形式编码的非法多字节数据在系统的不同处理过程中,先后被依照不同标准被解释,而可能造成现有安全机制被绕过的问题。...

    0x00: 前言

    近日接连几次接触到关于UTF-8的non-shortest form的安全问题,即UTF-8的非最短形式编码的非法多字节数据在系统的不同处理过程中,先后被依照不同标准被解释,而可能造成现有安全机制被绕过的问题。

    查找相关中文资料,发现关于编码安全相关内容的文章资料较少,所以在查找其它相关资料后,按照自己的理解写下此文。

    0x01: Unicode与UTF-8

    为防止读者对两者概念有所混淆,不方便下文的理解,故先区分两者的意义。

    总的来说,Unicode是容纳了多国众多不同字符的大一统字符集合,其核心是提供了一个数值与字符映射关系的超大编码表格,是一个抽象的标准;现在使用的Unicode(UCS-2,以下说明默认使用little endian方式存放)大都是用2个字节,也就是16 bit来表示一个字符;
    而UTF-8是一种编码方式,是针对Unicode字符集的一种具体实现,它规定了如何通过一个数值来准确的找到相应的Unicode字符;UTF-8编码使用变长的字节来存储不同的字符,这样做的目的,主要是可以节省存储空间,但是这样就必须解决另一个问题:字符从中间开始匹配的问题;
    对这个问题随意举个栗子:一个字符需要3个字节表示,16进制表示为【0x02a706】,一个字符需要2个字节表示,16进制表示为【0x02a7】,那么我解析字符时,是到0x02a7时结束,还是继续解析,到0x02a706结束呢?
    看下图,UTF-8的解决办法:用不同的比特位模式来标识一个字符的开头,表示该字符解析到第几个字节结束:

    UTF-8 non-shortest form

    从上图可以看到,UTF-8一个字符固定前端的0、10、110、1110和11110位来区分字符是使用多少字节存放的;可以发现,UTF-8编码后,不同字节长度的字符拥有不同的取值范围,不会重合,从而避免了上面提到的”从中间开始解析”的情况;

    对于上图:

    1 每列的意义

    第一列表示Unicode字符的码值范围;
    第二列表示UTF-8编码Unicode字符遵照的比特位排列模式;
    第三列表示UTF-8编码Unicode字符后,Unicode码值实际被使用的bit位数;

    2 区分Unicode字符值与UTF-8编码值

    可以看出当Unicode字符值的范围为”800—FFFF”时,只要2个字节便可表示Unicode字符,用UTF-8编码则需要3个字节(24 bit)来表示。
    第一列Unicode符号值的范围的计算: 只计算用”x”占位的位数

     第一行第二列中有7"x"占位,所以UTF-8编码中使用的有效Unicode码比特位长为7;
     用7071可以表示的二进制范围【00000001111111】,即范围为16进制的【07F】;
    
     第二行第二列中有11"x"占位,所以UTF-8编码中使用的有效Unicode码比特位长为11;用110111,接着上一个最大的数7F,可以表示的二进制范围为
    【000 10000000111 11111111】,即范围为16进制的【807FF】;
    
    第三行第二列中有16"x"占位,所以UTF-8编码中使用的有效Unicode码比特位长为16;用160161,接着上一个最大的数7FF,可以表示的二进制范围为
    【00001000 0000000011111111 11111111】,即范围为16进制的【800—FFFF】;
    
    第四行第二列中有21"x"占位,所以UTF-8编码中使用的有效Unicode码比特位长为21;用210211,接着上一个最大的数FFFF,用来表示的二进制范围到达
    【00001 0000000 0000000010000 11111111 11111111】结束,16进制即为【1000010FFFF】;

    总体看起来像下面这样(注意进制):

    Unicode符号范围      | UTF-8编码方式
    (十六进制)           | (二进制)
    —————————————————————————————————————————————————————————
    0000 0000-0000 007F | 0xxxxxxx
    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    为方便理解,举个栗子:
    中文简体”泽”字,如下图,它的Unicode字符值为”\u6cfd”,即16进制的”0x6cfd”,本来存储它需要2个字节:

    ze

    下面寻找它的UTF-8编码值:

    0x6cfd (二进制表示形式为:01101100 11111101)处在800—FFFF之间,UTF-8编码方式存储则需要3个字节;
    由3个字节所对应的UTF-8编码的比特位模式:1110xxxx 10xxxxxx 10xxxxxx;
    可把16个有效二进制位(分成0110110011111101)对应取代模式中的16"x",得到"泽"的UTF-8编码值为:
    11100110 10110011 10111101,即16进制的【E6B3BD】,故可知"泽"字的UTF-8编码值为:0xE6B3BD

    下图更为直观:

    Unicode_UTF-8

    这样虽然UTF-8编码比Unicode字符集多用了一个字节来表示”泽”,但是清楚的知道”泽”字符占用三个字节,不会多或少解析一个字节,更不会不存在”从中间开始解析”的情况;
    况且,UTF-8编码在表示ASCII码中的字符时,只需要1个字节(用Unicode一律是使用2个字节),可以节省存储空间。

    0x02: UTF-8 non-shortest form

    弄懂了0x01部分的知识,我们可以发现:UTF-8默认都是用最短形式的编码值来表示一个Unicode字符,比如”/”字符,用UTF-8编码表示的话,值就是0x2F;所以0x2F就称为”/”字符的UTF-8编码最短形式值;
    既然有最短形式,就有非最短形式,对于”/”字符的UTF-8编码值,

                 16进制        2进制
    1个字节表示    0x2F         00101111
    2个字节表示    0xC0AF       11000000 10101111
    3个字节表示    0xE080AF     11100000 10000000 10101111
    4个字节表示    0xF08080AF   11110000 10000000 10000000 10101111

    可以看出,一个UTF-8编码的非最短形式的值,就是套用UTF-8编码比特位模式,将用不到的”x”占位都用0填充;

    有的系统不会接受UTF-8非最短形式的编码,比如下图中的Python解析器,解析到上面讲到的”/”符号的非最短形式编码值,会报”非法多字节序列”的错误:

    parsererror

    但是,有的系统又能解析UTF-8的非最短形式编码,双方对相同数据的理解存在歧义,从而有了0x03部分的安全隐患问题。

    0x03: 非最短形式的安全隐患

    1 产生原因

    由于在安全检查时并未将UTF-8非最短形式编码的字符,如0xC0AF看作是 “/”正常字符,但是后续的处理中又将传入非最短形式编码的字符的0xC0AF看作”/”处理,从而引发安全问题。

    2 真实案例

    1. 在实际使用UTF-8非最短形式编码攻击的过程中,往往只将其中的一个Unicode字符进行UTF-8的非最短形式编码,其它尽量保持不变,即可绕过安全检查;
    如攻击中常用的目录遍历的四个字符”/../”:

    "/"的UTF-8最短形式编码值为0x2F(二进制00101111), "."的UTF-8最短形式编码值为0x2E(二进制00101110)
    如果将上述四个攻击字符依次写成2F2E2E2F,那么安全检查将识别出它为"/../",攻击就不会奏效;
    但当我将其中的一个字符"."用UTF-8的非最短形式编码,按照两个字节形式编码成:C0AE(二进制11000000 10101110),其余字符照旧写,则最后"/../"可被写成:2FC0AE2E2F,百分号编码/%c0%ae%c0%ae,与最初的2F2E2E2F值显然不一样,安全检查很可能会被绕过,但是当其它组件解析时,又可能将其解析成"/../",而被他人成功攻击;

    2. Apache Tomcat UTF-8目录遍历漏洞(CVE-2008-2938)
    原理就是上面点1所讲,不再赘述

    3. 另一攻击真实案例Twitter HTTP Response Splitting如下:过程参考

    这个案例虽然主要是利用了CRLF注入HTTP头和一个Firefox通常只解析HTTP响应头中一个ASCII字符的Bug,只是顺带用百分号编码后的UTF-8编码绕过安全检查,并没涉及到UTF-8非最短形式编码引起的问题,但还是附带介绍下,希望读者重视因编码问题引起的程序安全隐患,如下图:

    mutation

    本来一个正常”嘊”(U+560A)字的Unicode字符值为”0x560A”(最后一个字节为0x0A,最短形式表示换行符”\n”,用来断行,实施CRLF注入,实现HTTP响应头的截断攻击),通过UTF-8正常编码后,值就变为了”0xE5988A”,漏洞作者输入百分号编码后的UTF-8编码值%E5%98%8A,然后通过了安全检查,服务器将接收的值”0xE5988A”解码成Unicode字符值”0x560A”,在被放入到HTTP响应头中时,因为上面说的Firefox的一个漏洞,移去了字符值超出ASCII码范围的部分,只留下了0A,故成功的实施了攻击。

    附: 双字节表示的空字符问题
    在C语言等语言程序中,单字节空字符”0x00”是用来标志字符串结尾的;如果使用双字节形式表示的空字符”0xc080”,就有可能使原来防范字符串截断攻击的安全检查失效,造成安全问题。

    3 如何防范
    • 在应用内使用统一的字符集
    • 输入非法数据时报错并终止处理
    • 处理数据时使用正确的编码方式
    • 输出时设置正确的字符编码
    • 在函数参数中明确设置编码方式
    • 避免使用字符编码模糊检测功能
    4 启示

    上述攻击过程读者不必全部理解;需要明白的是:编码安全应当获得足够的重视,如果没有严格管控开发时使用的编码,特别是不对输入、输出部分进行有效的编码和解码,轻则留下程序Bug,重则埋下安全隐患,现有安全措施很可能因此而全部被绕过,安全事件一触即发。

    展开全文
  • 文章目录1、创建数据集的配置文件mydataset.yaml2、创建标注文件3、组织训练集的目录4、选择模型backbone进行模型配置文件的修改5、Train6、Visualize7、已有图像和xml制作标签的过程7.1 check_img.py7.2 check_box....

    1、创建数据集的配置文件mydataset.yaml

    # train and val datasets (image directory or *.txt file with image paths)
    train: ./datasets/score/images/train/
    val: ./datasets/score/images/val/
    
    # number of classes
    nc: 10
    
    names: ["knife","scissors","lighter","zippooil",
    "pressure","slingshot","handcuffs","nailpolish",
    "powerbank","firecrackers"]
    

    2、创建标注文件

    可以使用LabelImg,Labme,Labelbox, CVAT来标注数据,对于目标检测而言需要标注bounding box即可。然后需要将标注转换为和darknet format相同的标注形式,每一个图像生成一个*.txt的标注文件(如果该图像没有标注目标则不用创建*.txt文件)。创建的*.txt文件遵循如下规则:

    • 每一行存放一个标注类别
    • 每一行的内容包括class x_center y_center width height
    • Bounding box 的坐标信息是归一化之后的(0-1)
    • class label转化为index时计数是从0开始的

    每一个标注*.txt文件存放在和图像相似的文件目录下,只需要将/images/.jpg替换为/lables/.txt即可,例如:

    datasets/score/images/train/000000109622.jpg  # image
    datasets/score/labels/train/000000109622.txt  # label
    

    3、组织训练集的目录

    将训练集train和验证集val的images和labels文件夹按照如下的方式进行存放:
    在这里插入图片描述

    4、选择模型backbone进行模型配置文件的修改

    在项目的./models文件夹下选择一个需要训练的模型,如果你选定了一个模型,那么需要修改模型对应的yaml文件,例如我在这里选择的是yolov5s.yaml,改nc=你需要训练的类别数即可:
    在这里插入图片描述

    # parameters
    nc: 10  # number of classes<------------------  UPDATE to match your dataset
    depth_multiple: 0.33  # model depth multiple # 借助efficient net
    width_multiple: 0.50  # layer channel multiple
    
    # anchors
    anchors:# 锚框可以自己聚类,也可以直接用
      - [116,90, 156,198, 373,326]  # P5/32
      - [30,61, 62,45, 59,119]  # P4/16
      - [10,13, 16,30, 33,23]  # P3/8
    
    # YOLOv5 backbone # 主干部分
    #
    backbone:
      # [from, number, module, args]
    
      [[-1, 1, Focus, [64, 3]],  # 0-P1/2
       [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
       [-1, 3, BottleneckCSP, [128]],
       [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
       [-1, 9, BottleneckCSP, [256]],
       [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
       [-1, 9, BottleneckCSP, [512]],
       [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
       [-1, 1, SPP, [1024, [5, 9, 13]]],
      ]
    
    # YOLOv5 head  # 侦测部分
    head:
      [[-1, 3, BottleneckCSP, [1024, False]],  # 9
    
       [-1, 1, Conv, [512, 1, 1]],
       [-1, 1, nn.Upsample, [None, 2, 'nearest']],
       [[-1, 6], 1, Concat, [1]],  # cat backbone P4
       [-1, 3, BottleneckCSP, [512, False]],  # 13
    
       [-1, 1, Conv, [256, 1, 1]],
       [-1, 1, nn.Upsample, [None, 2, 'nearest']],
       [[-1, 4], 1, Concat, [1]],  # cat backbone P3
       [-1, 3, BottleneckCSP, [256, False]],
       [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]],  # 18 (P3/8-small)
    
       [-2, 1, Conv, [256, 3, 2]],
       [[-1, 14], 1, Concat, [1]],  # cat head P4
       [-1, 3, BottleneckCSP, [512, False]],
       [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]],  # 22 (P4/16-medium)
    
       [-2, 1, Conv, [512, 3, 2]],
       [[-1, 10], 1, Concat, [1]],  # cat head P5
       [-1, 3, BottleneckCSP, [1024, False]],
       [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]],  # 26 (P5/32-large)
    
       [[], 1, Detect, [nc, anchors]],  # Detect(P5, P4, P3)
      ]
    
    

    5、Train

    main函数下,修改一些默认参数为自己需要的:

    # Train yolov5s on score for 300 epochs
    
    $ python3 train.py 
    --img-size 640 
    --batch-size 16 
    --epochs 300 
    --data ./data/mydataset.yaml 
    --cfg ./models/score/yolov5s.yaml 
    --weights weights/yolov5s.pt
    --device 0
    

    6、Visualize

    开始训练后,查看train*.jpg图片查看训练数据,标签和数据增强,如果你的图像显示标签或数据增强不正确,你应该查看你的数据集的构建过程是否有问题。

    7、已有图像和xml制作标签的过程

    7.1 check_img.py

    ① 检测图像是否符合要求

    import cv2
    import os
    import shutil
    
    def check_img(img_path):
        imgs = os.listdir(img_path)
        for img in imgs:
            if img.split(".")[-1] !="jpg":
                print(img)
                shutil.move(img_path+"/"+img,"./error/"+img)
    
    def check_anno(anno_path):
        anno_files = os.listdir(anno_path)
        for file in anno_files:
            if file.split(".")[-1] !="xml":
                print(file)
                shutil.move(anno_path+"/"+file,"./error/"+file)
    
    def ckeck_img_label(img_path,anno_path):
        imgs = os.listdir(img_path)
        anno_files = os.listdir(anno_path)
    
        files = [i.split(".")[0] for i in anno_files]
    
    
        for img in imgs:
            if img.split(".")[0] not in files:
                print(img)
                shutil.move(img_path+"/"+img,"./error/"+img)
    
        imgs = os.listdir(img_path)
        images = [j.split(".")[0] for j in imgs]
    
        for file in anno_files:
            if file.split(".")[0] not in images:
                print(file)
                shutil.move(anno_path+"/"+file,"./error/"+file)
    
    
    if __name__ == "__main__":
        img_path = r"E:/Annotations"# 图像路径
        anno_path = r"E:/XML"# XML文件路径
        
        print("============check image=========")
        check_img(img_path)
    
        print("============check anno==========")
        check_anno(anno_path)
        print("============check both==========")
        ckeck_img_label(img_path,anno_path)
        
    

    7.2 check_box.py

    检查标签有没有问题

    import xml.etree.ElementTree as xml_tree
    import pandas as pd
    import numpy as np
    import os
    import shutil
    
    def check_box(path):
        files = os.listdir(path)
        i = 0
        for anna_file in files:
            tree = xml_tree.parse(path + "/" + anna_file)
            root = tree.getroot()
            # Image shape.
            size = root.find('size')
            # Find annotations.
            bboxes = []
            labels = []
            labels_text = []
            difficult = []
            truncated = []
    
            for obj in root.findall('object'):
                if (float(bbox.find('ymin').text) >= float(bbox.find('ymax').text)) or (
                        float(bbox.find('xmin').text) >= float(bbox.find('xmax').text)):
                    print(anna_file)
                    i += 1
                    try:
                        shutil.move(path + "/" + anna_file, "./error2/" + anna_file)
                        shutil.move(r"E:\Annotations" + anna_file.split(".")[0] + ".jpg",
                                    "./error2/" + anna_file.split(".")[0] + ".jpg")
                    except:
                        pass
    
        print(i)
    
    
    if __name__ == "__main__":
        check_box(r"E:\XML")
    

    7.3 rain_val_split.py

    训练集与验证集的划分

    import os
    import random
    
    trainval_percent = 0.1
    train_percent = 0.9
    xmlfilepath = r'E:\XML'
    txtsavepath = 'ImageSets/Main'
    total_xml = os.listdir(xmlfilepath)
    
    num = len(total_xml)
    lists = range(num)
    
    tr = int(num * train_percent)
    train = random.sample(lists, tr)
    
    ftrain = open('./ImageSets/Main/train.txt', 'w')
    fval = open('./ImageSets/Main/val.txt', 'w')
    
    for i in lists:
        name = total_xml[i][:-4] + '\n'
        if i in train:
            ftrain.write(name)
        else:
            fval.write(name)
    
    ftrain.close()
    fval.close()
    
    

    生成了一个文件夹ImageSets,txt内容如下:
    在这里插入图片描述
    在这里插入图片描述

    7.4 myData_label.py

    做训练集与验证集的标签

    
    # _*_ coding:utf-8 _*_
    import xml.etree.ElementTree as ET
    import pickle
    import os
    from os import listdir, getcwd
    from os.path import join
    import cv2
     
    # sets=[('myData', 'train'),('myData', 'val'), ('myData', 'test')]  # 根据自己数据去定义
    sets=[('score', 'train'),('score', 'val')]  # 根据自己数据去定义
    
    class2id = {'knife':0, 'scissors':1, 'lighter':2,'zippooil':3,'pressure':4,
            'slingshot':5,'handcuffs':6,'nailpolish':7,'powerbank':8,'firecrackers':9}
    # classes = ["plane", "boat", "person"] # 根据自己的类别去定义
     
     
    def convert(size, box):
        dw = 1./(size[0])
        dh = 1./(size[1])
        x = (box[0] + box[1])/2.0 - 1
        y = (box[2] + box[3])/2.0 - 1
        w = box[1] - box[0]
        h = box[3] - box[2]
        x = x*dw
        w = w*dw
        y = y*dh
        h = h*dh
        return (x,y,w,h)
     
    def convert_annotation(year, image_id,image_set):
        in_file = open(r'E:\XML\%s.xml'%(image_id),encoding="utf-8")
        out_file = open('./labels/%s/%s.txt'%(image_set,image_id), 'w')
        # print(in_file)
        tree=ET.parse(in_file)
        root = tree.getroot()
        # size = root.find('size')
        # w = int(size.find('width').text)
        # h = int(size.find('height').text)
        print(image_id)
        img = cv2.imread(r"E:/Annotations/"+image_id+".jpg")
    
        sp = img.shape
    
        h = sp[0] #height(rows) of image
        w = sp[1] #width(colums) of image
     
        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            cls_ = obj.find('name').text
            if cls_ not in list(class2id.keys()):
                print("没有该label: {}".format(cls_))
                continue
            cls_id = class2id[cls_]
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
            bb = convert((w,h), b)
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
     
    wd = getcwd()
    
    for year, image_set in sets:
        if not os.path.exists('./labels/'+image_set):
            os.makedirs('./labels/'+image_set)
        image_ids = open('./ImageSets/Main/%s.txt'%(image_set)).read().strip().split()
        list_file = open('./%s_%s.txt'%(year, image_set), 'w')
        for image_id in image_ids:
            list_file.write(r'%s/JPEGImages\%s.jpg\n'%(wd, image_id))  # 写了train或val的list
            convert_annotation(year, image_id,image_set)
        list_file.close()
    
    
    # labels/标注数据有了
    # train val的list数据也有了
    
    

    生成一个文件夹,txt内容如下(darknet格式的标签):
    在这里插入图片描述
    在这里插入图片描述
    接下来就按照上述第三大步把图像文件与标签文件拷贝到相应位置即可训练。

    8、推理

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 形式化验证调研报告

    千次阅读 2018-10-17 14:56:24
    形式化验证调研报告 王立敏 中国科学院信息工程研究所 第五实验室 北京 中国100093 ...形式化方法作为一静态验证方法,正好可以解决这些问题。本文主要梳理了当前形式化方法检测的常见方法,并且列出他们的优...
    形式化验证调研报告
    王立敏
    中国科学院信息工程研究所 第五实验室 北京 中国100093

    摘要2018年初,Spectre和Meltdown漏洞的发现,使得芯片安全备受重视。然而传统的基于仿真的芯片验证方法由于测试样例覆盖不完全,验证过程耗时巨大,逐渐适应不了日益复杂的芯片了。形式化方法作为一种静态验证方法,正好可以解决这些问题。本文主要梳理了当前形式化方法检测的常见方法,并且列出他们的优缺点,以及前人对这些缺点的改良方法。

    关键词
    芯片安全,形式化验证,二元决策图,时序逻辑,Petri网,定理证明,等效性检验,模型检验

    Formal Verification Investigation Report
    Wang Liming1
    Institute of Information Engineering, Chinese Academy of Sciences, Beijing 100093, China

    Abstract At the beginning of 2018, the discovery of Spectre and Meltdown attacks made chip security receive much more concerns. However, due to the serious drawbacks in the simulation-based methods in tradition such as the test cases did not cover all of the inputs and the time consuming of the simulation, this method became inappropriate to validate the chips that became more and more complicated. Formal Methods is a static verification method, which would solve these problems that the simulation-based methods bright. This report would list their advantages and disadvantages, as well as the previous methods that attempt to solve these problems.

    Key words Chip security, Formal verification, Binary Decision Diagrams,Temporal logic, Petri net, Theorem Proving, Equivalence Checking, Model checking

    1 引言

            近些年来,芯片的性能和规模不断提升,集成电路的设计也越来越复杂,使得引入错误和问题的可能性日益增加。但是传统的基于仿真的集成电路验证方法的覆盖率难以达到100%。而形式化方法作为一种静态测试的方法,通过数学的推理证明,理论上可以实现绝对安全,找出难以发现的错误,因此广受研究人员的关注。

    基于仿真的集成电路验证

            目前应用最广泛的依然是基于仿真的验证方法。这种验证方法通常需要一个测试基准,通常同时对待验证的电路和测试基准施加相同的激励,然后通过对比他们的输出来判断电路是否正确。这些输入向量可以事先生成,然后在测试期间从数据库读入,也可以边测试边生成。

            基于仿真的验证只能证明电路在指定的输入向量下输出正确,若要证明电路的正确性,输入向量必须覆盖电路的所有输入组合。但是现在集成电路十分复杂,要实现这一点是十分困难的。令人遗憾的是,许多不安全的因素或者错误都是出现在测试向量难以覆盖的地方[1]。而且这种验证方式主要用于发现逻辑漏洞,而并不能检查出芯片中的安全漏洞。

    基于形式化方法的验证

            基于形式化方法的验证是通过数理逻辑推理的一种方法。一般分为形式等效性检验(Equivalence
    Checking),定理证明(Theorem Proving)以及模型检查(Model
    Checking),如图1所示。

    图1 形式化方法的分类

    图1 形式化方法的分类

            形式等效性检验一般用于检测两个电路设计逻辑相等,电路设计一般使用硬件描述语言(Verilog或者VHDL)进行描述,然后综合成门级电路,接着再进行一系列的优化。这里的每一个步骤都会导致电路设计的改变,因此检查每一步操作前后的电路设计是否逻辑等效是有必要的。有些时候优化操作需要人为干预,因此也需要使用等效性检验来确保这些操作没有引入错误。除此之外,设计完成的芯片也需要与对应的黄金模型进行对比,以确保集成电路设计的正确性。

            定理证明方法是一种将模型抽象为逻辑公式,然后使用自动的逻辑推理技术来验证电路是否正确的技术。但是定理证明方法在使用时需要专业人士事先制定大量的定理和推理策略。因此它在自动化推理方面能力较差,不适用大规模的系统。

            模型检验是一种基于状态迁移系统的自动验证技术。它最早是由Edmund M.
    Clarke和他的研究生E.A. Emerson以及A.P.Sistla提出来的[2]。使用这种方法首先需要提出一系列规格属性,这些属性表示对电路的安全需求,系统只要满足这些属性,就能确保安全。然后建立一个电路系统的模型,即可通过模型检测方法自动地检测模型是否满足这些规格属性。模型检验一般用于电路和协议的验证。

    总结

            基于仿真的集成电路验证需要输入向量,而形式化验证并不需要。前者是先生成输入向量,再验证输出向量,而后者的考虑方向则相反,要先指明什么样的输出是符合要求的,再利用形式化方法去证明它。由于基于仿真的集成电路验证存在覆盖率不能达到100%,以及仿真时间过长等问题,而形式化证明则正好能解决这些问题。因此形式化验证开始被研究人员广泛关注。

    模型的建立

            要使用形式化方法,需要先为电路建立模型,这些模型通常用一些图的数据结构或者公式来表示。形式化模型建立完成后,即可使用形式化算法对其进行检验。

    二元决策图
    2.1.1 二元决策图概述

            二元决策图(Binary Decision Diagrams,BDD)可以很好地表示一个布尔函数。所谓布尔函数,即定义域和值域都是布尔值的函数,布尔函数在电路设计和密码学方面有广泛的应用。由于电路的输入和输出都是二进制值,这意味着电路可以表示成一个布尔函数,因此使用BDD结构来表示电路是十分合适的。

    2.1.2一个例子

    表1 f(x1,x2,x3)的真值表

    x1 x2 x3 f(x1,x2,x3)
    0 0 0 0
    0 0 1 0
    0 1 0 0
    0 1 1 1
    1 0 0 1
    1 0 1 0
    1 1 0 0
    1 1 1 1

            假设有一个电路,电路的功能如公式(1)所示。
    (1)f(x1,x2,x3)=x1x2+x1x2x3 f(x1,x2,x3)=x1x2+x1\overline{x2}\overline{x3} \tag{1}

            其真值表如表1所示。于是可得出该电路的BDD图,如图2,x1,x2,x3为变量,实线表示变量赋值为1,虚线表示变量赋值为0。

            由表1真值表可得,当x1,x2,x3分别赋值为0时,f(x1,x2,x3)的值也为0。则如图2在BDD图中沿着x1,x2,x3,0之间的虚线最终也会到达0的地方。如图中所示这样变量有序的BDD图也可以称作有序二元决策图(Ordered Binary Decision Diagrams ,OBDD)图。

            可以发现,当x1赋值为0,x2也赋值为0时,无论x3赋何值,最终结果也是0,因此可以将BDD再做精简。如图3中简化后的BDD所示,可以将这条路径中的x3节点删除,直接将x2用虚线连接至0处,这个过程可称为BDD的简化,而最终的简化结果则称为简化的有序二元决策图(Reduced
    Ordered Binary Decision Diagrams,ROBDD)。

    图2 f(x1,x2,x3)的BDD图

    图2 f(x1,x2,x3)的BDD图

    图3 f(x1,x2,x3)的简化BDD图

    图3 f(x1,x2,x3)的简化BDD图
    2.1.3基于二元决策图的电路表示

            对于组合逻辑电路而言,可以直接使用上述方法生成BDD结构。但是对于时序逻辑电路而言,则需要根据其特点生成有限自动机(Finite State Machine,FSM),再使用BDD来表示FSM的状态变迁过程,在形式等效验证和符号模型检验中常采用这一方法来表示电路。

            BDD本身不能减少状态空间,随着变量数的增加,状态空间数依然呈指数级上涨,但是它也有许多优点,比如表达形式简洁,并且配合图算法可实现快速的操作,用于表示电路十分合适。

    时序逻辑

            时序逻辑是逻辑领域中一个重要的组成部分,它在形式化验证中有十分重要的应用

    表2 时序逻辑的操作

    符号 操作 解释
    θUψ Until 若θUψ在路径上为真,则θ一直保持真直到ψ为真
    θRψ Release 若ψ为真,直到θ为真(或者θ永远不为真)则θRψ在路径上为真,
    Next 若Xθ在路径上为真,则下一个时刻θ为真
    Future 若Fθ在路径上为真,则θ最终一定为真
    Globally 若Gθ在路径上为真,则任何时刻,θ都为真
    All 表示对于任意路径
    Exists 表示存在这样的路径

            可以使用如表2所示的符号来描述硬件系统的行为,例如我们要表示“信号A一直不变,直到上升沿才翻转”这一操作,则我们令p为“信号A不变”,q为“时钟到达上升沿”,则该操作可表示为当满足pUq使信号A翻转。

            比较常用的时序逻辑是线性时序逻辑(Linear temporal logic,LTL)以及计算树逻辑(Computation tree logic,CTL)。线性时序逻辑是个线性结构,每一个时刻都只对应一个后继,计算树逻辑则是一个树状的分支结构。LTL可用于重点对象的分析,并且它可以使用公平的概念,但是对于一些可返回到初始状态的复杂系统,LTL则无法表示。CTL则相反,它无法使用公平的概念,但是却可以表达一些较为复杂的系统[3]。LTL和CTL各有自己的优势,E. A. Emerson 和 Joseph Y. Halpern 在 1986年提出了CTL*,统一了LTL和CTL。在传统的模型检验中,通常采用时序逻辑来描述电路。

    Petri网

            Petri网是一种重要的数学工具,Petri网对系统的并发性,异步性和不确定性具有很强的描述能力,一般主要是使用Petri网的可达图[4]。

    Petri网通常为四元组N= <P,T,F,M0>

    P:库所(Place)的有限集

    T:迁移(Transition)的有限集

    F:F ⊆ (P x T) ∪ (T x P),表示边的集合。∪前后分别表示输入函数集以及输出函数集。

    M0:P->N,表示初始状态集

    库所(Place)表示系统的状态。一般用圈圈表示。

    迁移(Transition)则表示资源的消耗使用,一般用黑色矩形表示。

            连接库所与变迁的有向弧表示输入输出函数。用令牌Token表示库所中的资源数量,一般用●表示。

            资源会沿着有向弧流动,当资源足够时,便会触发某些操作的执行来使用和消耗资源。即令牌会不断沿着迁移流动,令牌在迁移之前积聚叫做迁移的使能(enabled),令牌积累到足够数量之后便能通过迁移,这一过程也叫迁移的激发(fire)。

            图4表示一个互斥系统的Petri网,双方发出进入临界区的请求,当其中一方进入临界区时,另一方只能等待。图中的小黑点表示Token,最中间的库所t表示哪一方可优先访问临界区,当Idle中的Token传递到Wait时,t中个Token也会流到可优先进入临界区的那一方,于是便可以激发迁移Access,当经过Free之后,Token又将回到Idle和t中。

    图4 互斥模型的Petri网

    图4 互斥模型的Petri网

    1.形式化方法

    形式等效验证(Equivalence Checking)

            假设我们有Spec1和Spec2两个模型。若需要验证综合优化前后两个模型是否逻辑相等,则Spec1和Spec2可分别表示综合优化前后的设计。若需要验证设计的正确性,Spec1通常为黄金模型,Spec2则为我们的设计。Spec1和Spec2通常使用相同的数据结构,例如BDD,再根据具体的需求使用诸如布尔SAT求解程序(求解可满足性问题)之类的算法来进行等效性检验。

            虽然等效检验的检测效果不错,在工业上也得到了应用,但是在使用过程中依然需要高层次的专业人员去制定等效检验框架[5]。而且在复杂的电路中,等效性检验也存在状态空间数呈指数级增长的问题。虽然学术界提出了各种优化的方法,比如将复杂的等效检验切割成小的可比较集合进行处理[6],或者利用算法优化减少空间消耗[7],但是状态空间爆炸问题依然没有很好地解决。

    定理证明(Theorem Proving)

            定理证明方法十分严格,跟数理逻辑结合十分紧密。一般使用高阶逻辑(Higher-Order
    Logic,HOL) 系统来进行证明。

            要验证一个大的系统,通常采用目标制导的方式。将系统用HOL表示出来之后,再分为若干个子命题分别证明。定理证明方法对硬件模块的验证一般会用到抽象技术和层次化验证技术

            在证明之前需要对系统进行建模,Mike Gordon在论文[8]中提出可以直接利用HOL来为硬件建模。一个器件模块只有输入输出,这些输入输出可以用HOL中的谓词和函数表示,而模块之间的连接可用合取表示。

            抽象技术主要用于将系统的详细信息掩盖掉,只考虑需要关注的性质,这样可以方便算法的处理。根据关注对象的不同,可以分为不同的抽象。例如结构抽象掩盖了内部结构信息而只描述了设备的规范,而行为抽象则只对模块的部分行为进行定义,数据抽象则是通过一个映射,将现实中的数据抽象为一个较小的抽象数据集,比如布尔真值。

            层次化验证技术是将大的模型划分为小的模型,构建成一个树状结构,每一个子节点都是父节点的细化。下一层的正确性可以证明上一层的正确性,因此自下而上地证明可以确保根节点的模型的正确性。

            定理证明方法在工业上也有一定的使用,但是定理证明方法需要对系统用严格语义的数学符号进行描述和推理,因此对用户而言十分复杂。而且并没有办法确保事先人为制定的规则和定理的正确性,因此最终的正确性也值得怀疑,即前提若有错误,则最终的验证结果就不一定正确。

    模型检验(Model Checking)

            模型检验是目前最为流行的形式化检测方法。但是它依然存在状态空间爆炸的问题,模型检测方法的发展几乎都是为了解决状态空间爆炸问题以及不同系统的适用性问题展开的。

            状态空间爆炸问题一直制约着模型检验方法的发展,为此科研人员一直寻找合适的方法来解决这一问题,例如符号模型检验,偏序规约技术,以及近些年来十分热门的SAT技术。

    3.2.1符号模型检验

            符号模型检验的提出是解决状态空间爆炸问题的一个里程碑,它采用OBDD来描述电路。这使得模型检验可检查的系统规模大大增加,可以超过1020个状态。

            McMillan最先将OBDD引入模型检验技术[9],提出了符号模型检验,最初时符号模型检验只是基于CTL公式的。该方法将CTL公式转化成OBDD图,并在OBDD上搜索状态空间。之后Clarke等人又提出了基于LTL的符号模型[10]。

            符号模型检验中,存在许多优化方法,最常见的两种方法是偏序规约技术[11]和抽象模型[12]。

            由于系统中可能存在两个并行的模块,而这些并行模块的运行组合有许多种,其中的一部分运行组合实际上是重复的。因此若能将并行的模块的运行次序固定下来,在验证过程中就可以减少许多重复的路径。

            抽象技术多用于需要数据处理的系统,符号模型检验的数据处理能力较弱,若是需要表达复杂的数据结构,则验证的复杂性会十分的高。因此可以将精确的数据值和抽象的数据集合做个映射,产生一个较小的抽象数据集,以此来简化符号模型检验的状态空间。

    3.2.1 SAT技术

            基于BDD的符号模型检验虽然使得可检验的系统规模增加了许多,但是状态空间爆炸问题并没有彻底解决,在BDD中,状态空间依然是指数级增长的。BDD可通过简化生成ROBDD来减少状态空间,但是可优化的余地依然比较少。随着SAT技术的发展,它也被引入到模型检验领域[13]。

            SAT是NP完全的方法,因此它也是指数爆炸型的,为此Clarke等人提出了限界模型检验[14]。模型检验是通过对整个系统建模,并证明我们的模型是否满足我们定义的属性规格。而限界模型检验,则通过广度搜索的方法,从长度为1的路径开始搜索,搜索的路径长度逐渐递增,若能在长度为K的路径中搜索到不符合属性规格的路径,则停止搜索并报告这一反例。

            虽然限界模型检验搜索到反例后即可停止这一机制使得其遍历的状态大大减少,但是它只检查了整个状态空间的一个子集,只能证明在限界中的那部分状态符合属性规格,而无法证明整个状态空间符合属性规格。

            为了解决这一完整性问题,目前学术界较为流行的做法是逼近所求的解,即迭代地计算可达状态的不动点,来验证这整个模型是否最终满足规约。

            Yakir Vizel等人于2015年整理了各种适用于SAT的优秀的算法,这些算法包括冲突驱动从句学习(Conflict-Driven
    Clause Learning),随机局部搜索(Stochastic Local Search)[15]。

            SAT技术在经过EDA社区与科研人员的相互促进之下,在过去十年中取得了很大的进步。虽然SAT在工业界也得到了应用,但是它依然无法很好地解决模型检验的状态空间爆炸问题和限界模型检验的完整性问题,此外并行SAT技术也是一个十分有前景的方向。

            而为了解决不同系统的适应性问题,如第2部分所述,研究人员提出了许多不同的建模方式。传统的模型检验方法一般采用时序逻辑来描述电路。

    4 讨论

            传统的基于仿真的验证方式虽然存在有覆盖不完全,耗时间等问题。而形式化验证则正好可以解决这些问题,然而这并不意味着形式化方法可以完全替代传统的仿真验证。形式化方法依然存在许多的局限性,目前最好的办法是将传统的仿真验证与形式化验证结合起来。

            虽然在工业界和学术界的共同促进之下,形式化验证技术有了长足的进步。但依然存在不少进步的空间。模型验证是目前自动化水平最优的,很少需要手动干预,但是状态空间爆炸的问题依然令人十分困扰。为了提高形式化验证的速度,研究人员依然在尝试攻克检测技术的并行化的问题,这也是目前较为火的一个方向。此外为了能够使用到工业界,形式化验证必然还是需要提高检测技术的自动化水平,例如门级信息流的方法[16]利用关键信息只能从低安全级流向高安全级这一特性,简化了形式化方法建模的流程,使其可以自动生成模型。此外,纵观整个形式化验证方法的发展历程,可以发现许多形式化验证的突破,都是因为将一些已经存在的理论成果移植应用到工程中去,因此我们也可以从这一方面去考虑如何改进形式化验证的方法。

            形式化方法是个十分有前景而又十分重要的研究方向,不仅可以用于检测出难以发现的逻辑错误,也可以检查电路中隐藏的硬件木马,甚至发现较为隐秘安全漏洞。因此上述的一些形式化方法的局限依然值得我们在日后重点研究。

    参考文献

    [1] LAM W K. Hardware Design Verification: Simulation and Formal Method-Based
    Approaches (Prentice Hall Modern Semiconductor Design Series)[M]. Upper Saddle
    River, NJ, USA: Prentice Hall PTR, 2005.

    [2] CLARKE E M, EMERSON E A. Design and synthesis of synchronization skeletons
    using branching time temporal logic[J]. : 20.

    [3] 张瑞雪, 郝春梅, 王旭. 计算机形式验证方法研究综述[J]. 中国电子商务, 2011(5):
    69–69.

    [4] 蒋屹新, 林闯, 邢栩嘉. 基于线性时态逻辑的Petri网模型检测[J]. 系统仿真学报,
    2003, 15(z1): 6–10.

    [5] KREIKER J, TARLECKI A, VARDI M Y等. Modeling, Analysis, and Verification -
    The Formal Methods Manifesto 2010 (Dagstuhl Perspectives Workshop 10482)[J].
    HERBSTRITT M. 2011.

    [6] KUEHLMANN A, KROHM F. Equivalence Checking Using Cuts and Heaps[J]. : 6.

    [7] PARUTHI V, KUEHLMANN A. Equivalence checking combining a structural
    SAT-solver, BDDs, and simulation[C]//IEEE Comput. Soc, 2000: 459–464.

    [8] HAN J, STONE G. The implementation and verification of a conditional sum
    adder[J]. 1988.

    [9] MCMILLAN K L. Symbolic checking,An approachto the state explosion
    problem[J]. : 212.

    [10] CLARKE E, GRUMBERG O, HAMAGUCHI K. Another look at LTL model
    checking[C]//International Conference on Computer Aided Verification. Springer,
    1994: 415–427.

    [11] PELED D. All from one, one for all: on model checking using
    representatives[G]//COURCOUBETIS C. Computer Aided Verification. Berlin,
    Heidelberg: Springer Berlin Heidelberg, 1993, 697: 409–423.

    [12] CLARKE E M, GRUMBERG O, LONG D E. Model checking and abstraction[J]. ACM
    transactions on Programming Languages and Systems (TOPLAS), 1994, 16(5):
    1512–1542.

    [13] 王瑞. 基于SAT的符号化模型检验技术研究[D]. 国防科学技术大学, 2014.

    [14] CLARKE E, BIERE A, RAIMI R等. Bounded Model Checking Using Satisfiability
    Solving[J]. : 20.

    [15] VIZEL Y, WEISSENBACHER G, MALIK S. Boolean Satisfiability Solvers and Their
    Applications in Model Checking[J]. Proceedings of the IEEE, 2015, 103(11):
    2021–2035.

    [16] HU W, MAO B, OBERG J等. Detecting Hardware Trojans with Gate-Level
    Information-Flow Tracking[J]. Computer, 2016, 49(8): 44–52.

    Blog:形式化验证调研报告

    展开全文
  • 单例模式的5种写法

    千次阅读 2019-03-11 21:37:58
    单例模式的五写法 1、饿汉式静态变量 线程安全 将变量使用static final修饰,在类加载的时候即完成对象的加载和初始化,用类加载机制保证了线程安全。 但是该方法提前实例化单例变量,不符合懒加载的模式。并且当...
  • 安全性测试(一)--网页安全检查

    千次阅读 2016-04-06 14:29:01
    本文摘抄自一个做过... 网页安全检查 数据库安全检查 系统安全检查 接口安全检查 二. 检查范围详解  (一) 网页安全检查  1. 输入的数据没有进行有效的控制和验证 数据类型允许的字符集最大和最小
  • 形式化验证技术

    千次阅读 2014-10-13 21:46:50
    形式化验证就是基于已建立的形式化规格,对所规格系统的相关特性进行分析和验证,以评判系统是否满足期望的特性。形式化验证并不能完全确保系统的性能正确...模型检验是一基于有限模型并检验该模型的期望特性的一
  • java中数据的5种存储位置

    万次阅读 多人点赞 2018-05-09 07:25:39
    (1) 寄存器。这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在... 这是一特别...
  • angular2中DomSanitizer的5种用法记录

    千次阅读 2018-01-08 16:08:25
    跨站脚本(Cross-site scripting,通常简称为XSS)是一网站应用程序的安全漏洞攻击,是代码注入的一。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端...
  • java中数据的5种存储位置(堆与栈)

    千次阅读 2018-06-01 19:01:40
    任何语言所编写的程序,其中的各类型的数据都需要一个存储位置,Java中数据的存储位置分为以下5种:1.寄存器最快的存储区,位于处理器内部,但是数量极其有限。所以寄存器根据需求进行自动分配,无法直接人为控制。2...
  • 今天重点介绍一下多功能手机安检门也叫**多功能金属安检门 智能型金属安检门 电子设备探测门 手机探测门 手机检测门 电子产品安检门 电子设备安检门 新一代金属安检门** 区别于原有的传统**金属安检门**; 多功能...
  • 5种最有前途的编程语言

    万次阅读 2016-08-20 10:12:31
    )的形式出现,Revel是使用Go语言创建的一个高效率、全堆栈的web框架。Revel能够处理路由、缓存、参数分析、模板等等web参数。 Go强大的并发请求处理能力得益于goroutines和channels特性。goroutine是一个并发...
  • 《关注HTML5安全

    千次阅读 2012-09-09 17:01:58
    在今天的2012中国软件开发者大会上,我做了名为《关注HTML5安全》的主题演讲。我个人认为,随着HTML5的普及和发展,HTML5安全会成为近期带来的严重问题。之所以大家还没有感受到的原因是什么?1、目前HTML5应用还...
  • HTML5安全:内容安全策略(CSP)简介

    千次阅读 2015-11-13 14:31:05
    HTML5安全:内容安全策略(CSP)简介 分类: 前端 应用开发2012-07-08 22:57 10023人阅读 评论(4) 收藏 举报 脚本浏览器javascriptgooglefunctionsafari  前言:HTML5出现后,网络安全更加受到...
  • 手机探测安检门的选择方法

    万次阅读 2019-05-20 16:14:35
    各位网友大家好 今天很高兴博睿勤小编为大家分享一下手机探测安检门的选择方法! 手机探测安检门也叫手机安检门 手机探测门 手机检测门 电子产品金属安检门 电子设备金属安检门 电子设备金属探测门等等各种与电子类...
  • HTML5安全风险详析之三:WebSQL攻击

    万次阅读 2012-10-08 17:49:04
    一、WebSQL安全风险简介 数据库安全一直是...WebSQL的安全问题通常表现为两个部分: 第一是SQL注入:和本地数据库一样,攻击者可以通过SQL注入点来进行数据库攻击。 另外一方面,如果Web App有XSS漏洞,那么本地数
  • Spring Boot十种安全措施

    千次阅读 2019-03-04 14:02:27
    Spring Boot大大简化了Spring应用程序的开发。它的自动配置和启动依赖大大减少了开始一个...安全性问题与代码质量和测试非常相似,已经日渐成为开发人员关心的问题,如果你是开发人员并且不关心安全性,那么也许认为...
  • MBR是以前的分区形式,GPT是一新的分区形式,现在逐渐取代MBR分区形式。 GPT带来了很多新特性,但MBR仍然拥有最好的兼容性。GPT并不是Windows专用的新标准—— Mac OS X,Linux,及其他操作系统同样使用GPT...
  • Set、Map、List三集合的差别

    万次阅读 多人点赞 2019-05-30 16:15:27
    1.集合类型主要有3:set(集)、list(列表)和map(映射)。 2.三者关系 3.Set set接口时Collection接口的一个子接口,是无序的,set中不包含重复的元素,也就是说set中不存在两个这样的元素a1.equals(a2)结果为...
  • 本文试图概述几方法,程序员可用这几方法来创建高效的线程安全类。 并发性 只有当要解决的问题需要一定程度的并发性时,程序员才会从多线程应用程序中受益。例如,如果打印队列应用程序仅支持一台打印机和...
  • 信息安全导论复习(1-5章)

    万次阅读 2017-06-01 01:32:54
    第1章 信息化发展与信息安全 目录 1.1 信息化发展 1.1.1 信息化对我国的重要影响 1.1.2 信息化发展对信息安全的需求 1.2 信息安全的基本属性 1.2.1 保密性 1.2.2 完整性 1.2.3 可用性 1.3 信息安全概念的演变 1.3.1 ...
  • 使用HTML5抓取 Audio & Video

    万次阅读 2014-03-13 14:09:11
    原文地址: http://www.html5rocks.com/en/tutorials/getusermedia/intro/  本地化的文章: http://www.html5rocks.com/zh/tutorials/getusermedia/intro/ 其中已经有中文版本的本地化内容,点击 本地化 下面的 ...
  • HTML5本地存储里储存对象

    万次阅读 2014-05-12 00:03:00
    HTML5本地存储里储存对象 W3schools 在HTML5里,网页可以把数据存储到用户得本地浏览器里。 ...以前,这些数据保存在cookies...数据存储依靠name/value得形式,一个网页只能访问它自己存储得数据。 不像cookies那样
  • 转载国外课栈网 “技术释疑”,持续更新 电子邮件安全协议是保护您的电子邮件免受外部干扰的结构。您的电子邮件需要其他...安全套接字层(SSL)及其后续版本的传输层安全性(TLS)是最常见的电子邮件安全协议,可以...
  • html5跨域访问接口或者一般处理程序

    千次阅读 2017-07-14 16:23:06
    百度到的基本就是三解决方法,第一就是:使用代理,这个我没太明白是怎么个意思,只知道好像不是前端的事情; 第二是:扔给后台解决, 第三是:jsonp 第四是:模拟表单提交,这个别人大概的提取了下...
  • 功能安全中的有些概念比较绕,比如故障(fault),错误(error),失效(failure),今天就这三个概念进行下探讨。  一,故障  功能安全中定义的故障是指可引起要素或相关项失效的异常情况。  故障可以分为永久故障...
  • Linux教程(第5版)孟庆昌版 课后答案

    万次阅读 多人点赞 2020-06-15 10:18:50
    性能高和安全性强;便于定制和再开发;互操作性强;全面的多任务和真正的64位操作系统。 1.6 解释核心版本和发行版本的含义。Linux 2.1.1版和2.2.1版中,哪一个版本是稳定的? 答:核心版本主要是Linux的内核,由...
  • Docker是一容器技术,它可以将应用和环境等进行打包,形成一个独立的,类似于iOS的APP形式的“应用”,这个应用可以直接被分发到任意一个支持Docker的环境中,通过简单的命令即可启动运行。Docker是一最流行的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 254,080
精华内容 101,632
关键字:

安全检查5种形式