DVWA靶场实战(五)——File Upload
DVWA靶场实战(五)
五、File Upload:
1.漏洞原理:
File Upload中文名叫做文件上传,文件上传漏洞是指用户上传了一个可执行脚本文件(php、jsp、xml、cer等文件),而WEB系统没有进行检测或逻辑做的不够安全。但文件上传功能本身没有问题,问题在于上传后如何处理以及解析文件。一般情况下,WEB应用都会允许上传一些文件,如头像、附件、等信息,如果Web应用没有对用户上传的文件有效的检查过滤,那么恶意用户就会上传一句话木马等Webshell,从而达到控制Web网站的目的。
存在文件上传功能的地方就有可能存在文件上传漏洞,比如上传相册、头像上传、视频、图片分享、论坛发帖和邮箱等可以上传附件的地方也是上传漏洞的高危地带,另外像文件管理器这样的功能也有可能被攻击者所利用。
一般文件上传的漏洞可以是木马、病毒、恶意脚本或Webshell等。
2.漏洞利用:
一般利用方式分为以下几种:
(1)上传webshell文件,攻击者可以通过这些网页后门执行命令并控制服务器。
(2)上传文件是钓鱼图片或包含了脚本的图片时,图片中的脚本,在某些版本的浏览器上会被作为脚本执行,从而被利用于钓鱼或者欺诈。
(3)上传病毒、木马文件,用于诱骗用户和管理员下载执行权限或者自动运行。
(4)上传文件是其他恶意脚本时,攻击者可直接执行脚本进行攻击。
3.常见防御方式:
(1)检查文件上传路径(避免0x00截断、IIS6.0文件解析漏洞、目录遍历)。
(2)文件扩展名检测(避免服务器以非图片的文件格式解析文件),验证文件扩展名通常有“黑名单”和“白名单”两种方式。
(3)文件MIME验证(比如GIF图片MIME为image/gif,CSS文件的MIME为text/css等)。
(4)图片二次渲染(最变态的文件上传漏洞防御方式,基本上完全避免了文件上传漏洞)。
(5)文件重命名(比如随机字符串或时间戳等方式,防止攻击者得到webshell的路径)。
(6)隐藏上传路径。
(7)文件内容检测(避免图片中插入webshell)。
4.绕过方式:
(1)前端验证:
主要是通过JavaScript代码进行检测,是最简单的绕过。绕过方法以下两种:
·只需要在浏览器内禁用JS就可以了。
·使用Burpsuite代理后上传符合要求的文件类型,后抓包修改文件类型。
(2)后端——扩展名检测:
针对文件的扩展名后缀进行检测,主要通过黑白名单进行检测,若不符合过滤规则,则不允许上传。
①黑名单检测:
一般专门有blacklist文件或列举出黑名单,里面包含常见的危险脚本文件。常见的绕过方式有以下几种:
A.大小写绕过:服务端没有将后缀名转换为统一格式进行比对,导致可以上传的后缀为pHp的文件,又因为Windows操作系统大小写不敏感,所以.pHp会被当做php文件解析。重点函数语句“$file_ext = strtolower($file_ext); //转换为小写”。
B.修改后缀名绕过:黑名单不允许上传.asp,.php,.jsp,.exe后缀的文件,但可以上传诸如“asa/cer/aspx”“php/php3/php4/php5/phtml/pht”“jspx/jspf”“exee”.当然前提是Apache的httpd.conf中配置如下代码:
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
当我们修改文件名后,可以发现上传成功。
C.重写(双写)绕过:服务端将黑名单的后缀名替换为空,但只能进行一次。上传.pphphp后缀,替换一个php为空,则后缀名变为.php,成功绕过。
D.利用Windows的命名机制:shell.php,shell.php【空格】,shell.php:1.jpg,shell. php::$DATA,shell.php:1.jpg在Windows中,后缀名后面的点和空格都会被删除掉。
E.解析漏洞:
·.htaccess文件解析漏洞
·apache解析漏洞
·IIS7.0或IIS7.5或nginx的解析漏洞
·IIS6.0解析漏洞
F.截断上传:
·截断类型:PHP%00截断
·截断原理:由于00代表结束符,所以会把00后面的字符都截断
·截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
②白名单检测:
白名单检测的原理一般是有一个专门的whitelist文件,里面会包含的正常文件有“jpg”“png”“gif”。绕过方式有以下几种:
A.解析漏洞:
·.htaccess文件解析漏洞
·apache解析漏洞
·IIS7.0/IIS7.5/Nginx的解析漏洞
·IIS6.0解析漏洞
B.截断上传:
·截断类型:PHP%00截断
·截断原理:由于00代表结束符,所以会把00后面的字符都截断
·截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
C.文件包含
(3)后端检测——00截断:
原理:虽然web应用做了校验,但是由于文件上传后的路径用户可以控制,攻击者可以利用手段添加字符串标识符0x00的方式来将后面的拼接的内容进行截断,导致后面的内容无效,而且后面的内容又可以帮助我们绕过黑白名单的检测。
思路:在C语言中,空字符有一个特殊的含义,代表字符拼接结束。这里我们使用的是PHP语言,属于高级语言,底层靠C语言来实现,也就是说空字符的字符串拼接结束功能在PHP中也能实现。但是我们在URL中不能直接使用空,这样会造成无法识别;我们通过查看ASCII对照表,也发现第一个就空字符,它对应的16进制是00,这里我们就可以用16进制的00来替代空字符,让他后面的内容。
绕过:使用burpsuite进行抓包,因为这里是通过URL进行传递的文件上传后存储路径,所以需要对16进制的00进行URL编码,编码的结果就是%00,通过这种方式,就可以用%00截断后面的内容,让拼接的文件名不再进行生效。
(4)后端检测——MIME检测:
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定的应用程序来打开。
常见的MIME类型:
MIME类型 | 代表文件类型 |
text/plain | 纯文本 |
text/html | HTML文档 |
text/javascript | JS代码 |
application/xhtml+xml | XHTML文档 |
image/gif | GIF图像 |
image/jpge | JPGE图像 |
image/png | PNG图像 |
video/mpeg | MPEG动画 |
Application/octet-stream | 二进制数据 |
Application/pdf | PDF文档 |
检测方式:在文件上传过程中,服务端会针对我们的上传的文件生成一个数组,这个数组其中有一项就是这个文件的类型file_type;服务端对文件检测时,就是通过检测脚本中的黑白名单和这个数组中的file_type进行对比,如果符合要求就允许上传这个文件。
MIMIE绕过原理:部分web应用系统判断文件类型是通过content-type字段,黑客可以通过抓包,将content-type字段改为常见的图片类型,如image/gif,从而绕过校验。
(5)后端检测——内容检测图片马绕过:
原理:一般内容验证使用getimagesize函数检测,判断文件是否是一个有效的文件图片,如果是,则允许上传,否则的话不允许上传。
图片马制作:直播一张内容,这里为a.png,和一个一句话木马,通过以下命令合成一个图片马3.php:a.php内容“<?php phpinfo(); ?>”,命令为“copy a.png /b + a.php /a 3/php”,这条命令的意思就是:通过copy命令,把a.png图片文件,以二进制文件形式添加到a.php文件中,以ASCII文本形式输出为3.php文件。
(6)后端检测——文件头检测漏洞:
原理:在每一个文件(包括图片,视频或其他的非ASCII文件)的开头(十六进制表示)实际上都会一片区域来显示这个文件的实际用法,这就是文件头标志。我们可以通过16进制编辑器打开文件,添加服务器允许绕过检测的文件头。
常见文件头:
·GIF:47 49 46 38 39 61
·PNG:89 50 4E 47 0D 0A 1A 0A
·JPG:FF D8 FF E0 00 10 4A 46 49 46
在进行文件头绕过时,我们可以把上面的文件头添加到我们的一句话木马内容最前面,达到绕过文件头检测的目的。
(7)解析漏洞:
①.htaccess文件解析漏洞:
漏洞利用前提:web具体应用没有禁止.htaccess文件的上传,同时web服务器提供商允许用户上传自定义的.htaccess文件。
原理:.htaccess文件(或者“分布式配置文件”),全程Hyertext Access(超文本入口)。提供了针对目录改变配置的方法,即,在一个特定的文档目录放置一个包含或多个指令的文件,以作用于此目录及其所有的子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
利用方式:上传覆盖.htaccess文件,重写解析规则,将上传的带有脚本的图片以脚本方式解析。
.htaccess文件内容:
<FilesMatch "evil.gif">
SetHandler application/x-httpd-php #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
</FilesMatch>
②Apache解析漏洞:
原理:Apache解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。比如test.php.a.b的“.a”和“.b”这两种后缀是apache不可识别解析,apache就会把test.php.a.b解析成test.php。
③IIS6.0解析漏洞:
IIS6.0解析漏洞分两种:
1)目录解析:
以xx.asp命名的文件夹里的文件都将会被当成ASP文件执行。
2)文件解析:
xx.asp;.jpg像这种畸形文件名存在“;”后面的直接忽略,也就是说当成xx.asp文件执行
注:IIS6.0默认的可执行文件除了asp还包含这三种.asa,.cer,.cdx。
④IIS7.0 / IIS7.5 / Nginx的解析漏洞:
原理:Nginx拿到文件路径(更专业的说法URL)/test.jpg/test.php后,一看后缀是.php,便认为该文件是php文件,转交给php去处理。php一看/test.jpg/test.php不存在,便删去最后的/test.php,又看/test.jpg当成要执行的文件了,又因为后缀为.jpg,php认为这不是php文件,于是返回Access denied。这其中涉及到php的一个选项:cgi.fix_pathinfo,该默认值为1,表示开启。开启这一选项PHP可以对文件路径进行修理。
举个例子,当php遇到文件路径/1.jpg/2.txt/3.php时,若/1.jpg/2.txt/3.php不存在,则会去掉最后的/3.php,然后判断/1.jpg/2.txt是否存在。若存在,则把/1.jpg/2.txt当做文件/1.jpg/2.txt/3.php,若/1.jpg/2.txt仍不存在,则继续去掉/2.txt,以此类推。
漏洞形式:www.xxxxx.com/UploadFiles/image/1.jpg/1.php
另外两种解析漏洞:
www.xxxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxxx.com/UploadFiles/image/1.jpg/%20\0.php
(8)二次渲染漏洞:
原理:在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站的对应的标签进行显示。
绕过:
①配合文件包含漏洞:
将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的那部分数据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中存在了一句话,在配合文件包含漏洞获取webshell。
②配合条件竞争:
这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合就删除,可可利用条件竞争来进行爆破上传。
注:如何判断图片是否被二次处理,主要是用16进制编辑器打开图片查看上传后保留了哪些数据,查看哪些数据被改变了。
5.实战:
(1)Low:
代码分析:
<?php if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
$html .= '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
$html .= "<pre>{$target_path} succesfully uploaded!</pre>";
}
} ?>
从代码来看,这里没有什么防御措施,所以我们直接上传木马就可以getshell了。然后我们制作一个木马尝试上传,直接显示上传成功。
上传成功以后,这里我们可以看见给我们爆了上传文件的存储路径。然后我们访问,在原本路径上加上“../../hackable/uploads/1.php succesfully uploaded!”就可以了。空白页面,证明上传成功。
然后我们在哥斯拉中尝试链接,显示“Success!”说明添加成功。
(2)Medium:
代码分析:
<?php if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; // Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) { // Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
$html .= '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
$html .= "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
$html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
} ?>
对文件上传的类型做了大小限制,要求必须是image/jpeg或者image/png类型的。
我们先打开burpsuite,接着开始上传一句话木马,这次我们修改为2.php避免冲突,然后进行抓包的操作,得到下面这个包进行修改就可以了。
这里显示成功了,就说明上传成功,我们尝试访问这个链接,发现空白,就证明上传成功,也成功运行了一句话木马。
我们进行链接,链接成功,攻击成功。
(3)High:
代码分析:
<?php if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; // Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) { // Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
$html .= '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
$html .= "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
$html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
} ?>
可以看见这里又添加一个getimagesize(string filename)函数,它会通过读取文件头,返回图片的长、宽等信息,如果没有相关图片文件头,函数会报错。这里读取的文件名中最后一个“.”后的字符串,期望通过文件名来限制文件类型,因此要求文件名形式必须是“.jpg”“.jpeg”“.png”之一。同时,getimagesize函数更像是限制了上传文件的文件头必须为图像类型。
首先新建一个文件夹,将准备好的一句话木马和图片放入文件夹,在路径栏目输入“CMD”打开此文件夹的CMD命令窗口。
输入如下指令“copy [一句话木马名称]/b+[图片名称]/a [新图片名称]”,显示如下即为成功。
上传显示如下即为成功上传,我们得到路径“../../hackable/uploads/111.jpg”,访问路径,得到如下的图片。
然后我们切换到Command Injection输入命令“127.0.0.1|move …/…/hackable/uploads/111.jpg …/…/hackable/uploads/111.php”将文件名修改。
然后我们这里连接哥斯拉,显示“Success!”表示成功。
(4)Impossible:
代码分析:
<?php if( isset( $_POST[ 'Upload' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; // Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
//$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
$target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
$temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
$temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; // Is it an image?
if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
( $uploaded_size < 100000 ) &&
( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
getimagesize( $uploaded_tmp ) ) { // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img ); // Can we move the file to the web root from the temp folder?
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
// Yes!
$html .= "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
}
else {
// No
$html .= '<pre>Your image was not uploaded.</pre>';
} // Delete any temp files
if( file_exists( $temp_file ) )
unlink( $temp_file );
}
else {
// Invalid file
$html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
} // Generate Anti-CSRF token
generateSessionToken(); ?>
这个级别的文件上传对上传的文件进行了重命名(MD5的加密),还增加了token值的校验,对文件的内容也做了严格的检查。
DVWA靶场实战(五)——File Upload的更多相关文章
- 【DVWA】Web漏洞实战之File Upload
File Upload File Upload,即文件上传漏洞,一般的上传漏洞可能是未验证上传后缀 或者是验证上传后缀被bypass 或者是上传的文件验证了上传后缀但是文件名不重命名. LOW 直接上 ...
- DVWA全级别之File Upload(文件上传)
File Upload File Upload,即文件上传漏洞,通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带 ...
- DVWA 黑客攻防演练(五)文件上传漏洞 File Upload
说起文件上传漏洞 ,可谓是印象深刻.有次公司的网站突然访问不到了,同事去服务器看了一下.所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映 ...
- DVWA File Upload 通关教程
File Upload,即文件上传.文件上传漏洞通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带来的危害常常是毁 ...
- DVWA靶场之File Inclusion(文件包含)通关
文件包含,未经过严格过滤,将一些恶意构造带入了包含函数,可以使用一些包含函数来包含一些其他乱七八糟的东西,要么导致任意文件读取,要么命令执行 文件包含包括远程文件包含(RFI)和本地文件包含(LFI) ...
- DVWA(九):File Upload 全等级文件上传
File Upload 文件上传,通常是由于对上传文件的类型没有进行严格的过滤.限制造成的,一般思路是 通过上传木马获取服务器的webshell(通过网络端口对网站服务器某种程度上的操作权限 也叫网站 ...
- jquery file upload示例
原文链接:http://blog.csdn.net/qq_37936542/article/details/79258158 jquery file upload是一款实用的上传文件插件,项目中刚好用 ...
- upload-lab 靶场实战
文件上传/下载 漏洞 冲冲冲,好好学习 2020.02.13 淦靶场之前,先来点知识铺垫铺垫. 文件上传漏洞 前端Js绕过. MIME类型绕过 后缀名大写写绕过 / php4 .php5 00截断 覆 ...
- DVWA靶场之Brute Force(暴破)通关
DVWA最经典PHP/MySQL老靶场,简单回顾一下通关流程吧 DVWA十大金刚,也是最常见的十种漏洞利用:Brute Force(暴破).Command Injection(命令行注入).CSRF( ...
- miniFTP项目实战五
项目简介: 在Linux环境下用C语言开发的Vsftpd的简化版本,拥有部分Vsftpd功能和相同的FTP协议,系统的主要架构采用多进程模型,每当有一个新的客户连接到达,主进程就会派生出一个ftp服务 ...
随机推荐
- 16.MongoDB系列之分片管理
1. 查看当前状态 1.1 查看配置信息 mongos> use config // 查看分片 mongos> db.shards.find() { "_id" : & ...
- git-secret:在 Git 存储库中加密和存储密钥(下)
在之前的文章中(点击此处查看上一篇文章),我们了解了如何识别包含密钥的文件,将密钥添加到 .gitignore ,通过 git-secret 进行加密,以及将加密文件提交到存储库.在本篇文章中,将带你 ...
- java程序员在交接别人的工作时如何保证顺利交接?
序言 各位好啊,我是会编程的蜗牛,作为java开发者,尤其是在职场混迹了多年的老手,肯定会遇到同事离职的情况,或者自己跳槽的情况,这些都免不了需要做好交接工作,不管是别人交接给我们,还是我们交接给别人 ...
- Elasticsearch Analyzer 内置分词器
Elasticsearch Analyzer 内置分词器 篇主要介绍一下 Elasticsearch中 Analyzer 分词器的构成 和一些Es中内置的分词器 以及如何使用它们 前置知识 es 提供 ...
- Redisson源码解读-分布式锁
前言 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid).Redisson有一样功能是可重入的分布式锁.本文来讨论一下这个功能的特点以及源 ...
- 部署redis
1. 下载redis 下载地址:https://redis.io/download/ 下载版本:6.2.7 应用包:redis-6.2.7.tar.gz 2. 上传服务器并解压 将redis安装包上传 ...
- Eclipse Python IDE安装
时隔一年,曾经的AI工程师微专业课程也忘了大半,如今终于有闲心重温人工智能的相关知识与项目.先从Eclipse安装开始. 首先下载JDK,进入JDK官网下载最新版本的JDK并安装:https://ww ...
- 嵌入式-C语言基础:指针函数
指针函数:返回指针的函数,即函数返回一个地址.例如:int * a(int x,int y);由于()的优先级比*高,因此a先与()结合,a(int x,int y)显然是一个函数,函数前面带一个in ...
- spring运行报500 bean不存在
spring运行报500 bean不存在 bean不存在 步骤: 查看bean是否注入成功 junit单元测试 问题,不一定在我们底层,是spring出现了问题 SpringMVC整合 ...
- (C++) std::move std::forward及使用
概念 std::ref :针对std::thread,需要把实参显式转换为引用类型: std::move :无条件把参数转换为右值:但是右值赋值给新变量时,实际还要看是否满足右值条件,如const s ...