总结常见漏洞的代码审计方法

前言

这篇文章主要是总结一下在安全工作中常见漏洞的代码审计方法,以及修复方案,希望能对初学代码审计小伙伴们有所帮助,笔芯♥️

代码审计的思路

通常做代码审计都是检查敏感函数的参数,然后回溯变量,判断变量是否可控并且没有经过严格的过滤,这是一个逆向追踪的过程。而代码审计并非这一种手段,还可以先找出哪些文件在接收外部传入的参数,然后跟踪变量的传递过程,观察是否有变量传入到高危函数里面,或者传递的过程中是否有代码逻辑漏洞,这是一种正向追踪的方式,这样的挖掘方式比逆向追踪挖掘得更全。还有一种方式是直接挖掘功能点漏洞,根据自身的经验判断该类应用通常在哪些功能中会出现漏洞,直接全篇阅读该功能代码。

常见漏洞的代码审计

1. HTTP响应头截断

漏洞描述

HTTP响应截断是由于应用程序未对用户提交的数据进行严格过滤,当用户恶意提交包含 CR(回车,即URL编码%0d或\r)和 LF(换行符,即URL编码%0a或\n)的HTTP请求,服务器可能会创建两个 HTTP 响应,攻击者可以控制第二个响应并加载攻击。 攻击者可控制响应的内容构造XSS攻击,其中响应中包含恶意的JavaScript或其它代码在用户的浏览器中执行,也有可能让用户重定向到攻击者控制的Web内容或在用户的主机上执行恶意操作。

审计方法

检查对响应头字段是否进行安全处理。

如果未对响应头进行任何安全处理,则为确认:

//未对响应头做任何安全处理,审计时为确认
String data;
if (data != null){response.addHeader("Location", "/author.jsp?lang=" + data);
}

再举一例:

//同样的未对响应头做任何安全处理,审计时为确认
String author = request.getParameter(AUTHOR_PARAMETER);
// ...
Cookie cookie = new Cookie("author", author);
response.addCookie(cookie);

如果对响应头做了响应的安全处理,则为误报:

//使用Refenence类对环境变量值进行编码,剔除特殊字符,为误报
if (data != null){String decode = Reference.decode(data);response.addHeader("Location", "/author.jsp?lang=" + decode);
}

修复方案:

1、对用户的输入进行合理验证,对特殊字符(如<、>、’、”等)等进行编码。

2、创建一份安全字符白名单,只接受完全由这些受认可的字符组成的输入出现在 HTTP 响应头文件中。 3、使用源代码静态分析工具,进行自动化的检测,可以有效的发现源代码中的 HTTP 响应截断问题。

2. 硬编码问题

漏洞描述

硬编码问题,是指将敏感数据(包括口令和加密密钥,部分账号的密码以及其他敏感信息等)硬编码在程序中。

审计步骤

1、看扫描出的硬编码是否为常规单词(或通读代码查看是否有硬编码敏感文件)

2、如果是常规单词,则为误报,如:

//fipAddress为硬编码
public class IPaddress
{
private String ipAddress = "172.16.254.1";
public static void main(String[] args)
{
//...
}
}

可以使用 javap -c IPaddress 命令来反编译 class 来发现其中硬编码的服务器 IP 地址,此处反

编译器的输出信息可以直接透漏服务器的明文 IP 地址为172.16.254.1

再举一例:

//SECRET_PASSWORD为硬编码
private String SECRET_PASSWORD = "No fear in my heart!"; 
Properties props = new Properties(); 
props.put(Context.SECURITY_CREDENTIALS, "password");

3、如果是随机字符串,则为确认或待确认,如:

//1546272000000为硬编码
byte[] sr = hBaseClient.buildRowKey(devId, "1546272000000");

再举一例:

//qafgshw1900wxxxx为硬编码
private String accessKeyId = "qafgshw1900wxxxx";

4、追踪key值,如果key为硬编码则为确认,如:

//key值为硬编码
byte[] key = {1, 2, 3, 4, 5, 6, 7, 8};
SecretKeySpec spec = new SecretKeySpec(key, "AES");
Cipher aes = Cipher.getInstance("AES");
aes.init(Cipher.ENCRYPT_MODE, spec);
return aesCipher.doFinal(secretData);

追踪key值,如果追踪不到或者为安全形式,则为误报,如

//无法再继续追踪key值,为误报
public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {//key为密钥byte[] keyBytes = decryptBASE64(key);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);
}

再来一栗:

//存储密钥。KeyStore.getInstance("PKCS12")为密钥库,为误报
try{KeyStore keyStore = KeyStore.getInstance("PKCS12");keyStore.load(null, null);KeyGenerator keyGen = KeyGenerator.getInstance("AES");keyGen.init(128);Key key = keyGen.generateKey();keyStore.setKeyEntry("secret", key, "password".toCharArray(), null);keyStore.store(new FileOutputStream("output.p12"), "password".toCharArray());
} catch (Exception ex){ex.printStackTrace();
}

修复方案

推荐使用配置文件或者通过配置中心来下发这些敏感配置,密码和密钥应存储在单独的加密配置文件或密钥库中。

3. SQL注入

漏洞描述

注入攻击的本质,是程序把用户输入的数据当做代码执行。这里有两个关键条件:

第一是用户能够控制输入;

第二是用户输入的数据被拼接到要执行的代码中从而被执行。

sql 注入漏洞则是程序将用户输入数据拼接到了 sql 语句中,从而攻击者即可构造、改变 sql 语义从而进行攻击。

漏洞举例

(1) 直接通过拼接 sql

@RequestMapping("/SqlInjection/{id}")
public ModelAndView SqlInjectTest(@PathVariable String id){
String mysqldriver = "com.mysql.jdbc.Driver";
String mysqlurl = 
"jdbc:mysql://127.0.0.1:3306/test?user=root&password=123456&useUnicode=true&c
haracterEncoding=utf8&autoReconnect=true";#直接通过拼接 sql
String sql = "select * from user where id=" + id;
ModelAndView mav = new ModelAndView("test2"); 
try{
Class.forName(mysqldriver);
Connection conn = DriverManager.getConnection(mysqlurl);
PreparedStatement pstt = conn.prepareStatement(sql);
ResultSet rs = pstt.executeQuery();

再来一例:

//没有做任何其他安全处理措施
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from user where username = '" + username+"' and password='"+password+"'");

(2) 预编译使用有误

漏洞举例:

//只使用了占位符
@RequestMapping("/SqlInjection/{id}")
public ModelAndView SqlInjectTest(@PathVariable String id){
String mysqldriver = "com.mysql.jdbc.Driver";
String mysqlurl = 
"jdbc:mysql://127.0.0.1:3306/test?user=root&password=123456&useUnicode=true&c
haracterEncoding=utf8&autoReconnect=true";
String sql = "select * from user where id= ?";
ModelAndView mav = new ModelAndView("test2"); 
try{
Class.forName(mysqldriver);
Connection conn = DriverManager.getConnection(mysqlurl);
PreparedStatement pstt = conn.prepareStatement(sql);
//pstt.setObject(1, id); //一般使用有误的是没有用这一句,编码者以为在上面的sql语句中直
接使用占位符就可以了。
ResultSet rs = pstt.executeQuery();

审计步骤:查看预编译的完整性,关键函数定位 setObject()、setInt()、setString()、setSQLXML()关联上下文搜索 set* 开头的函数。

(3) %和_(oracle 中模糊查询)问题

@RequestMapping("/SqlInjection/{id}")
public ModelAndView SqlInjectTest(@PathVariable String id){
String mysqldriver = "com.mysql.jdbc.Driver";
String mysqlurl = 
"jdbc:mysql://127.0.0.1:3306/test?user=root&password=123456&useUnicode=true&c
haracterEncoding=utf8&autoReconnect=true";
String sql = "select * from user where id= ?";
ModelAndView mav = new ModelAndView("test2"); 
try{
Class.forName(mysqldriver);
Connection conn = DriverManager.getConnection(mysqlurl);
PreparedStatement pstt = conn.prepareStatement(sql);
pstt.setObject(1, id); //使用预编译
ResultSet rs = pstt.executeQuery();

审计步骤:定位相关 sql 语句上下文,查看是否有显式过滤机制。

修复方案:上面的代码片段即使这样依然存在 sql 注入,原因是没有手动过滤%。预编译是不能处理这个符号的,以需要手动过滤,否则会造成慢查询,造成 dos。

(4) order by 问题

String sql = “Select * from news where title =?”+ “order by ‘” + time + 
“’asc”

审计步骤:定位相关 sql 语句上下文,查看是否有显式过滤机制。

修复方案:类似上面的这种 sql 语句 order by 后面是不能用预编译处理的只能通过拼接处理,所以需要手动过滤。

(5) 有关$符号的情况

#{}:相当于jdbc中的preparedstatement,传入的字符串,需要赋值后使用,可以有效防止sql注入

${}:是输出变量的值,传入的变量,直接在sql中执行,无法防止sql注入 简单的说就是#{}传过来的参数带单引号’',而${}传过来的参数不带单引号。

但是orderby是动态SQL,只能用${},用#{}会多个’ '导致sql语句失效。此外还有一个like 语句后也需要用${}。

//需要转义的字符串仍使用$
delete from ${tableName}

修复方案:对于可以使用#{}的情况,直接使用#{}即可解决问题对于不能使用#{}的情况(如orderby),需要增加额外的过滤逻辑,以此判断输入内容是否正常,如字段类型、字段长度等

4. maven不安全模块

漏洞描述

Maven,是一个Java开发比较常用的项目管理工具,可以对Java项目进行构建、依赖管理。当它配置一个不安全的模块时,即存在安全风险。

审计方法

查看配置的版本是否属于安全版本区间。 如果是,则确认:

//3.9版本是存在漏洞的版本。安全版本是3.11以上
<dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast-client</artifactId><version>3.9</version>
</dependency>

修复方案

配置为安全版本即可(同时应注意解决兼容性问题)

5. 服务端请求伪造(SSRF)

漏洞描述

SSRF是攻击者让服务端发起指定的请求,攻击的目标一般是从外网无法访问的内网系统。SSRF形成的原因大都是由于代码中提供了从其他服务器应用获取数据的功能但没有对目标地址做过滤与限制。比如从指定URL链接获取图片、下载等。一般利用http协议来探测端口,利用file协议读取任意文件。

利用场景

SSRF漏洞一般位于远程图片加载与下载、图片或文章收藏功能、URL分享、通过URL在线翻译、转码等功能点处。

关键词/接口/类包

// Java
HttpURLConnection.getInputStream
URLConnection.getInputStream
Request.Get.execute
Request.Post.execute
URL.openStream
ImageIO.read
OkHttpClient.newCall.execute
HttpClients.execute
HttpClient.execute

审计方法

1、内网系统的SSRF直接为误报(内网系统之间互调互传)

2、检查请求的URL是否为外部可控,即由外部传入

3、检查请求的返回,是否对请求的返回数据做了安全处理

漏洞示例

//请求URL为外部可控,返回数据直接展示
String url = request.getParameter("picurl");
StringBuffer response = new StringBuffer();URL pic = new URL(url);
HttpURLConnection con = (HttpURLConnection) pic.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
//发起请求,触发漏洞
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {response.append(inputLine);}
in.close();
modelMap.put("resp",response.toString());
return "getimg.htm";

再举一例:

//HttpClients函数的SSRF漏洞代码,审计时为确认:
String url = request.getParameter("url");
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet); //发起请求

修复方案

  1. 使用白名单校验HTTP请求url地址
  2. 避免请求url外部可控
  3. 避免将请求响应及错误信息返回给用户
  4. 禁用不需要的协议及限制请求端口,仅仅允许http和https请求等

6. 路径遍历

目录/路径遍历、任意文件上传/下载

漏洞描述

在下载文件相关的代码中,若不对HTTP请求中的待下载文件名进行检查,则有可能产生任意文件下载漏洞。攻击者可以指定文件名、文件路径等文件操作的参数,越权访问正常情况下无法到达的系统资源。

审计方法

  1. 判断是否存在上传下载行为
  2. 判断路径是否可被外部控制,如果外部可控则向下
  3. 判断是否对文件路径做了安全措施,如果做了安全措施为误报

漏洞示例

没有对路径做任何安全处理,如:

//没有对路径做任何安全处理措施
path = "config/"+path;
File file = new File(path);
System.out.println(path);
response.setHeader("Content-Disposition", "attachment;filename=\\""+ new String(path.getBytes(), "ISO8859-1") + "\\"");
response.setContentLength((int) file.length());
byte[] buffer = new byte[4096];// 缓冲区
BufferedOutputStream output = null;
BufferedInputStream input = null;

再举一例:

//对下载的文件未做安全处理
public Response getImage(@javax.ws.rs.PathParam("image") String image) {File file = new File("resources/images/", image);if (!file.exists()) {return Response.status(Status.NOT_FOUND).build();}return Response.ok().entity(new FileInputStream(file)).build();
}

修复方案

  1. 使用getCanonicalPath()、getAbsolutePath()等方法获取规范路径
  2. 对文件操作参数进行输入验证,过滤特殊字符
  3. 通过文件头判断来限制文件类型,而不是通过文件后缀来判断
  4. 服务器安全配置策略文件。将所能读取的文件限定在特定的目录下

7. 命令注入

漏洞描述

命令注入是指通过提交恶意构造的参数破坏命令语句结构,当对用户输入的命令没有进行限制或者过滤不严导致用户可以执行任意命令时,就会造成命令执行漏洞。通常表现为攻击者能够篡改程序执行的命令或命令执行的环境,从而直接或间接的控制了所执行的命令。

常见的命令执行方法

// Java
Runtime.exec
ProcessBuilder.start
GroovyShell.evaluate

审计方法

  1. 检查是否是系统命令,如果不是系统命令而是常规字符串拼接,则为误报
  2. 检查所执行的命令是否为外部可控制,如果外部不可控(例如命令拼接参数不为外部控制)则为误报
  3. 外部可控制的情况下检查命令的拼接参数是否做了安全措施,如果未做安全措施即为确认

漏洞示例

(1) 没有对外部传入的命令拼接参数做任何安全处理措施,如:

//没有对外部传入的命令参数command做任何安全处理
System.out.println("Command: ping"+ command);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("cmd.exe /C ping "+command);
int res = proc.waitFor();
if(res !=0){System.out.println("process error: "+ res);
}
InputStream in = (res == 0)? proc.getInputStream() : proc.getErrorStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
buffer=new StringBuffer();
String line;
while((line = reader.readLine())!=null){buffer.append(line+"\\n");
}

再举一例:

//同样没有对外部传入的命令拼接参数input做任何安全处理
Runtime r = Runtime.getRuntime();
r.exec("/bin/sh -c some_tool" + input);

(2) 对外部传入的命令拼接参数做安全限制,如:

//对外部传入的命令拼接参数做了限制//正则限定为合法IP地址
if (!Pattern.matches("([1-9]|[1-9]\\\\d|1\\\\d{2}|2[0-4]\\\\d|25[0-5])(\\\\.(\\\\d|[1-9]\\\\d|1\\\\d{2}|2[0-4]\\\\d|25[0-5])){3}", command)){//如果不是IP则匹配不成功,则为F,!F则为T,T则执行此代码块result.put("message", "Error!");return DataUtil.toJson(result);
}
System.out.println("Command: ping"+ command);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("cmd.exe /C ping "+command);
int res = proc.waitFor();
if(res !=0){System.out.println("process error: "+ res);
}
InputStream in = (res == 0)? proc.getInputStream() : proc.getErrorStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
buffer=new StringBuffer();
String line;
while((line = reader.readLine())!=null){buffer.append(line+"\\n");
}

修复方案

  1. 构建白名单,只允许其中的字符出现在输入中
  2. 应有应用程序来控制命令,并使用绝对路径来执行命令
  3. 严格的权限限制,程序执行外部命令使用最小权限原则
  4. 严格的参数校验

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,需要点击下方链接即可前往获取 

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击)

同时每个成长路线对应的板块都有配套的视频提供: 

 大厂面试题

视频配套资料&国内外网安书籍、文档

当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料

所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~ 

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击) 

特别声明:

此教程为纯技术分享!本教程的目的决不是为那些怀有不良动机的人提供及技术支持!也不承担因为技术被滥用所产生的连带责任!本教程的目的在于最大限度地唤醒大家对网络安全的重视,并采取相应的安全措施,从而减少由网络安全而带来的经济损失。

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

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

相关文章

【Crypto】RSA

文章目录 题目步骤1.计算 &#x1d45b;2.计算欧拉函数 &#x1d719;(&#x1d45b;)3. 扩展欧几里得算法求逆元 &#x1d451; 解题感悟 题目 p473398607161 q4511491 e17 求d 步骤 1.计算 &#x1d45b; 公式&#xff1a;npq n47339860716145114912135733555619387051 …

初识STM32单片机-TIM定时器

初识STM32单片机-TIM定时器 一、定时器概述二、定时器类型2.1 基本定时器(TIM6和TIM7)2.2 通用定时器(TIM2、TIM3、TIM4和TIM5)2.3 高级定时器(TIM1和TIM8) 三、定时中断基本结构和时基单元工作时序3.1 定时器基本结构3.2 预分频器时序3.3 计数器时序3.3.1 计数器有无预装时序(…

Hono 框架使用经验谈

Hono&#x1f525;是一个小型、快速并开源的 Serverless Web 框架&#xff0c;用 TypeScript 写就。它适用于任何JavaScript运行时&#xff1a;Cloudflare Workers&#xff0c;Fastly ComputeEdge&#xff0c;Deno&#xff0c;Bun&#xff0c;Vercel&#xff0c;Netlify&#x…

动手学操作系统(一、搭建实验环境)

动手学操作系统&#xff08;一、搭建实验环境&#xff09; 文章目录 动手学操作系统&#xff08;一、搭建实验环境&#xff09;1. 在VMware虚拟机中安装ubuntu20.042. 安装Bochs3. 启动计算机Reference &#x1f680; 环境配置 &#x1f680; 笔者的环境使用的是 ubuntu 20.04…

python多线程的使用

Python 多线程探索 在 Python 编程中&#xff0c;多线程是一项强大的技术&#xff0c;它允许我们同时执行多个任务&#xff0c;从而提高程序的效率和响应性。 一、线程的基本概念 线程是进程中的一个执行单元&#xff0c;可以与其他线程共享进程的资源。 二、创建线程 在 P…

Linux:confluence8.5.9的部署(下载+安装+破ji)离线部署全流程

0.环境 Confluence也是比较吃运存了&#xff0c;我建议运行运存给到4g或者4g以上就可以了&#xff0c;核数可以给到1核或以上 我部署在centos7.9操作系统上&#xff0c;ip地址为&#xff1a;192.168.6.1&#xff0c;yum仓库使用的是自己的镜像文件&#xff0c;本章所有使用到…

爱普生XC1011SD为电气稳定控制系统组合式传感器推出解决方案

在现代电力系统中&#xff0c;确保系统的安全和稳定运行至关重要。为了应对这一需求&#xff0c;我们推出了XC1011SD组合式传感器解决方案&#xff0c;它专为电气稳定控制系统设计&#xff0c;提供了卓越的性能和可靠性。 XC1011SD是一款集成陀螺仪传感器和双轴加速度计于一体的…

炸裂!AI五分钟模仿爆款IP故事,涨粉速度太绝了!

‍ ‍大家好&#xff0c;我是向阳。 今天我要分享一个利用AI技术模仿爆款账号的小技巧&#xff0c;帮助大家迅速增加粉丝。这个方法简单实用&#xff0c;尤其适用于副业和本地生活领域。接下来&#xff0c;我将为大家详细讲解操作步骤。让我们开始吧。 副业赚钱&#xff1a;模…

合约构成-成员变量、函数、事件event、修饰器modifier及构造函数

合约的基本结构 合约中的成员变量合约中的成员函数Event&#xff08;事件&#xff09;、modifier(修饰器)与constructor&#xff08;构造函数:实例产生的时候执行&#xff09; Event事件 modifier construcor 1、成员变量 概念&#xff1a;存储合约状态的变量 声明方法&a…

北京证券公司港股通交易佣金手续费最低是多少?万0.8?港股通纳入规则是怎么样的?

港股通交易佣金概述 港股通的交易佣金可能会因证券公司和投资者的不同而有所差异。 北京证券公司的港股通交易佣金最低可能万分之零点八&#xff08;0.008%&#xff09;&#xff0c;但这需要投资者与证券公司客户经理了解&#xff0c;进行沟通和申请。 一般来说&#xff0c;…

CSS学习笔记:Less

什么是Less&#xff1f; Less是一个CSS预处理器&#xff0c; Less文件后缀是.less 扩充了CSS 语言&#xff0c;使CSS具备一定的逻辑性、计算能力 可以通俗地理解&#xff1a;Less是一种更好用的CSS 注释 运算 嵌套 Less嵌套的作用&#xff1a;快速生成后代选择器 变量 问…

软考中级-软件设计师-真题详解【2023年上半年】

2023上半年真题记忆点详解 本片不涉及解题法&#xff0c;只整理记忆背诵点&#xff0c;记住即可拿分。 上午题部分&#xff1a; 片内总线&#xff1a;用于芯片内部各主要部件连接&#xff1b; 系统总线&#xff1a;用于CPU、主存、外设见的数据传输&#xff1b; 通讯总线&…

04 FreeRTOS 队列(queue)

1、队列的特性 队列可以理解为一个传送带&#xff0c;一个流水线。 队列可以包含若干个数据&#xff1a;队列中有若干项&#xff0c;这被称为"长度"(length) 每个数据大小固定 创建队列时就要指定长度、数据大小 数据的操作采用先进先出的方法(FIFO&#xff0c;First…

干货分享 —— 如何开展web项目自动化测试!

前言 自动化(Automation)是指机器设备、系统或过程(生产、管理过程)在没有人或较少人直接参与的情况下&#xff0c;根据人的要求&#xff0c;通过自动检测、信息处理、分析判断、操纵和控制&#xff0c;达到预期目标的过程。自动化测试是指测试过程是在没有人为或较少人为干预…

从零构建vue3+ts+vite项目打包及项目依赖配置

❗️❗️❗️❗️ 写在最前: 本文是根据B站作者 月光分层 视频vuets 工程化配置以及作者笔记稍作整理 &#x1f496;&#x1f496;作者B站地址https://space.bilibili.com/14110850 &#x1f496;&#x1f496;视频教程地址vuets 工程化配置 &#x1f496;&#x1f496;作者微信…

【计算机毕业设计】安卓054基于Android校园助手

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

LAMP源码编译安装——CentOS7

文章目录 LAMP是什么LAMP软件组件LinuxApacheMySQLPHP 源码安装Apache一、准备工作二、安装环境依赖包三、配置软件模块四、编译及安装五、优化配置文件路径六、添加httpd系统服务&#xff08;有两种方法&#xff09;方法一&#xff1a;方法二&#xff1a; 七、修改httpd 服务配…

公告:关于博主的重要通知

大家好&#xff0c;我是博主夏目。 本期不分享知识&#xff0c;博主想说明一下博主的一些重要提示。 分享的内容&#xff0c;从不收费&#xff0c;也未向任何人进行收费。 意在分享知识&#xff0c;传播文化&#xff0c;结交更多志同道合的朋友。 截至目前&#xff0c;从未…

《C++ Primer Plus》第十二章复习题和编程练习

目录 一、复习题二、编程练习 一、复习题 1. 假设String类有如下私有成员&#xff1a; // String 类声明 class String { private: char* str;int len;// ... };a. 下述默认构造函数有什么问题&#xff1f; String::String() { } // 默认构造函数b. 下述构造函数有什么问题…

VirtualBox+Ubuntu22.10+Docker+ROS2

Docker 拉取ros2镜像 docker pull osrf/ros:foxy-desktop 运行 docker run -it --nameros2 -p 50022:22 osrf/ros:foxy-desktop 进入容器安装组件 apt-get update apt-get install vim apt-get install git apt-get install net-tools # 安装ssh apt-get install openssh…