php怎么对空格转义,你是如何学会正则表达式的?
全力以赴地进入数据集是从事数据科学工作的任何人的使命之一。通常,这意味着要进行数字运算,但是当我们的数据集主要基于文本时,我们该怎么办?我们可以使用正则表达式。在本教程中,我们将仔细研究如何在Python中使用正则表达式(regex)。
正则表达式(regex)本质上是文本模式,可用于自动搜索和替换文本字符串中的元素。这可以使清理和使用基于文本的数据集变得更加容易,从而省去了手动搜索大量文本的麻烦。
正则表达式可以在多种编程语言中使用,并且已经存在很长时间了!
不过,在本教程中,我们将学习Python中的正则表达式,因此需要基本熟悉关键的Python概念,例如if-else语句,while和for循环等。在本教程结束时,您将熟悉Python regex的工作原理,并能够使用Python regex模块中的基本模式和功能re来分析文本字符串。您还将获得有关正则表达式如何与熊猫配合使用以处理大型文本语料库的介绍。
让我们深入研究有关每个人最不喜欢的电子邮件类型的一些数据:垃圾邮件和欺诈。
我们的任务:分析垃圾邮件
在本教程中,我们将使用Kaggle的欺诈电子邮件语料库。它包含1998年至2007年之间发送的数千种网络钓鱼电子邮件。它们非常有趣,易于阅读。
您可以在这里找到完整的语料库。但是,我们将从使用一些电子邮件学习基本的正则表达式命令开始。如果需要,您也可以使用我们的测试文件,也可以在完整的语料库中尝试使用。
介绍Python的Regex模块
首先,我们将通过打开测试文件,将其设置为只读并读取来准备数据集。我们还将其分配给变量fh(用于“文件句柄”)。
请注意,我们在目录路径之前加r。此技术将字符串转换为原始字符串,这有助于避免某些机器读取字符的方式引起的冲突,例如Windows上目录路径中的反斜杠。
现在,假设我们要找出电子邮件的来源。我们可以自己尝试使用原始Python:
但这并没有给我们确切的需求。如果您看一下我们的测试文件,我们可以找出原因并修复它,但是,让我们使用Python的re模块并使用正则表达式来做吧!
我们将从导入Python的re模块开始。然后,我们将使用一个名为的函数re.findall(),该函数返回在正在查看的字符串中定义的模式的所有实例的列表。
外观如下:
这与原始Python的长度基本相同,但这是因为这是一个非常简单的示例。您尝试做的越多,Python正则表达式就可以为您节省更多的精力。
在继续之前,让我们仔细看看re.findall()。此函数采用形式为的两个参数re.findall(pattern, string)。在这里,pattern代表我们要查找的子字符串,并string代表我们要在其中查找的主字符串。主字符串可以包含多行。在这种情况下,我们让它fh使用选定的电子邮件来搜索所有文件。
该.*是一个字符串模式的简写。正则表达式通过使用这些速记模式来查找文本中的特定模式而起作用,因此让我们看一下其他一些常见示例:
常见的Python正则表达式模式
我们re.findall()上面使用的模式包含一个完整拼写的字符串"From:"。当我们确切地知道我们要查找的内容(精确到实际字母以及它们是否为大写或小写)时,这很有用。如果我们不知道我们想要的字符串的确切格式,我们将会迷路。幸运的是,正则表达式具有解决此情况的基本模式。让我们看看在本教程中使用的那些:
1)w匹配字母数字字符,表示az,AZ和0-9。它还与下划线_和破折号-相匹配。
2)d 匹配数字,表示0-9。
3)s 匹配空白字符,包括制表符,换行符,回车符和空格字符。
4)S 匹配非空格字符。
5).匹配除换行符外的任何字符n。
掌握了这些正则表达式模式后,您将在继续进行解释的同时快速理解上面的代码。
使用正则表达式模式
现在,我们可以.*在re.findall("From:.*", text)上面的行中解释的用法。让我们.先来看:
通过在.旁边添加一个From:,我们可以在其旁边查找另一个字符。因为.查找除以外的任何字符n,所以它捕获了我们看不到的空格字符。我们可以尝试更多的点来验证这一点。
看起来加点确实为我们获得了线的其余部分。但是,这很繁琐,而且我们不知道要添加多少点。这是星号符号*出现的位置。
*匹配模式左侧的零个或多个实例。这意味着它将寻找重复模式。当我们寻找重复的模式时,我们说搜索是“贪婪的”。如果我们不寻找重复的模式,则可以将搜索称为“非贪婪”或“懒惰”。
让我们构建一个贪婪的搜索.用*。
因为*匹配在其左侧指示的模式的零个或多个实例,并且.位于此处的左侧,所以我们能够获取From:字段中的所有字符,直到行尾。这将用精美简洁的代码打印出整行。
我们甚至可以更进一步,仅隔离名称。让我们使用它re.findall()来返回包含模式的行列表,"From:.*"就像之前一样。match为了整洁,我们将其分配给变量。接下来,我们将遍历列表。在每个循环中,我们将re.findall再次执行,匹配第一个引号以仅选择名称:
注意,我们在第一个引号旁边使用了反斜杠。反斜杠是一个特殊字符,用于转义其他特殊字符。例如,当我们想将引号用作字符串文字而不是特殊字符时,可以使用反斜杠将其转义,例如:\"。如果我们不使用反斜杠转义上面的模式,它将变为"".*"",Python解释器将其读取为两个空字符串之间的句点和星号。它将产生错误并破坏脚本。因此,至关重要的是我们在这里用反斜杠将引号引起来。
匹配第一个引号后,.*获取行中的所有字符,直到下一个引号也被转义为模式。这使我们得到的名称只是带引号的名称。该名称也打印在方括号中,因为re.findall返回的匹配项在列表中。
如果我们想要电子邮件地址怎么办?
看起来很简单,不是吗?仅模式不同。让我们来看一看。
这是我们仅匹配电子邮件地址的前部分的方式:
电子邮件总是包含一个@符号,因此我们从它开始。电子邮件中@符号前的部分可能包含字母数字字符,这w是必需的。但是,由于某些电子邮件包含句点或破折号,所以这还不够。我们添加S以查找非空白字符。但是,w\S只会得到两个字符。添加*以查找重复。因此,模式的前部如下所示:\w\S*@。
现在查看@符号后面的模式:
域名通常包含字母数字字符,句点和短划线,因此a .可以。为了使它更贪婪,我们使用扩展了搜索范围*。这使我们可以匹配任何字符,直到行尾。
如果我们仔细观察这条线,会发现每封电子邮件都封装在尖括号<和>中。我们的模式.*包括右括号>。让我们对其进行补救:
电子邮件地址以字母数字字符结尾,因此我们将模式设置为w。因此,在@符号后面有.*\w,这表示我们想要的模式是一组以字母数字字符结尾的任何类型的字符。不包括>。
因此,我们的完整电子邮件地址格式如下所示:\w\S*@.*\w。
!这需要花费很多时间。接下来,我们将介绍一些通用re功能,这些功能在开始重新组织语料库时将非常有用。
常用的Python正则表达式函数
re.findall()无疑是有用的,但它不是我们可以使用的唯一内置函数re:
1)re.search()
2)re.split()
3)re.sub()
在使用它们为我们的数据集添加一些顺序之前,让我们一一看一下。
研究()
While re.findall()匹配字符串中某个模式的所有实例并在列表中返回它们,re.search()匹配字符串中一个模式的第一个实例,并将其作为re匹配对象返回。
像一样re.findall(),re.search()也有两个参数。第一个是要匹配的模式,第二个是要在其中找到模式的字符串。在这里,我们将结果分配给match变量以保持整洁。
由于re.search()返回re匹配对象,因此无法通过直接打印来显示名称和电子邮件地址。相反,我们必须首先对该group()函数应用该函数。我们已经在上面的代码中打印了这两种类型。如我们所见,group()将match对象转换为字符串。
我们还可以看到,打印match显示的属性超出字符串本身,而打印match.group()仅显示字符串。
re.split()
假设我们需要一种快速的方法来获取电子邮件地址的域名。我们可以通过三个正则表达式操作来做到这一点,如下所示:
第一行很熟悉。我们返回一个字符串列表,每个字符串包含From:字段的内容,并将其分配给变量。接下来,我们遍历列表以查找电子邮件地址。同时,我们循环访问电子邮件地址,并使用该re模块的split()功能将每个地址切成两半,用@符号作为分隔符。最后,我们打印它。
re.sub()
另一个方便的re功能是re.sub()。就像函数名称所暗示的那样,它替换字符串的一部分。一个例子:
我们之前已经在第一行和第二行看到了任务。在第三行,我们re.sub()在上应用address,这是From:电子邮件标题中的完整字段。
re.sub()需要三个参数。第一个是要替换的子字符串,第二个是我们要替换的字符串,第三个是主字符串本身。
正则表达式与pandas
现在,我们掌握了Python正则表达式的基础知识。但是通常对于数据任务,我们实际上并没有使用原始的Python,而是使用了pandas库。现在,将我们的正则表达式技能带入熊猫工作流程,将其提升到一个新的水平。
如果您以前从未使用过熊猫,请不要担心。我们将逐步遍历代码,以免您迷路。但是,如果您想更详细地了解熊猫,请查看我们的熊猫教程或我们提供的有关numpy和熊猫的完全交互式课程。
使用Python Regex和Pandas对电子邮件进行排序
我们的语料库是一个包含数千封电子邮件的单个文本文件(不过,同样,在本教程中,我们使用的是一个只有两个电子邮件的较小文件,因为在整个语料库上打印正则表达式工作的结果会使这篇文章过长)。
我们将使用正则表达式和熊猫将每封电子邮件的各个部分分类为适当的类别,以便可以更轻松地阅读或分析语料库。
我们将每封电子邮件分为以下类别:
1)sender_name
2)sender_address
3)recipient_address
4)recipient_name
5)date_sent
6)subject
7)email_body
这些类别中的每一个都将成为我们的熊猫数据框(即我们的表格)中的一列。这将使我们更轻松地分别处理和分析每个列。
我们将继续处理我们的小样本,但是值得重申的是,正则表达式使我们可以编写更简洁的代码。简洁的代码减少了我们的机器必须执行的操作数量,从而加快了我们的分析过程。使用我们的两封电子邮件的小文件,并没有太大的区别,但是,如果您尝试使用和不使用正则表达式来处理整个语料库,您将开始看到其优势!
准备脚本
首先,让我们导入所需的库,然后再次打开文件。
除了re和之外pandas,我们email还将导入Python的软件包,这将有助于电子邮件的正文。仅使用正则表达式时,电子邮件的主体相当复杂。它甚至可能需要足够的清理才能保证有自己的教程。因此,我们将使用完善的email软件包来节省一些时间,让我们专注于学习正则表达式。
我们还创建了一个空列表emails,用于存储字典。每本词典将包含每封电子邮件的详细信息。
现在,让我们开始应用正则表达式!
注意:为简洁起见,我们剪裁了上面的打印输出。如果您在自己的机器上打印此文件,它将显示其中包含的所有内容,contents而不是...像上面那样结束。
我们使用re模块的split函数将整个文本块分割fh为单独的电子邮件列表,然后将其分配给变量contents。这很重要,因为我们希望通过使用for循环遍历列表来逐一处理电子邮件。但是,我们如何知道按字符串分割"From r"?
我们之所以知道这一点,是因为在编写脚本之前我们已经查看了文件。我们不必细读其中的数千封电子邮件。只是前几个,看看数据的结构是什么样子。只要有可能,最好在开始使用代码之前先关注实际数据,因为您经常会发现诸如此类的有用功能。
我们已经截取了原始文本文件的屏幕截图:
电子邮件以“ From r”开头
绿色方框是第一封电子邮件。蓝色方框是第二封电子邮件。如我们所见,这两封电子邮件均以开头"From r",并以红色框突出显示。
我们在本教程中使用欺诈电子邮件语料库的原因之一是,当数据杂乱无章,不熟悉且没有文档时,我们不能仅仅依靠代码来整理数据。这将需要一双人眼。正如我们刚刚显示的,我们必须研究语料库本身以研究其结构。
像这样杂乱无章的数据可能需要大量清理。例如,即使我们使用本教程将要构建的完整脚本来计算此集合中的3977封电子邮件,但实际上还有更多。某些电子邮件实际上并不以开头"From r",因此不会单独计算。(不过,为了简洁起见,我们将继续处理该问题,并用分隔所有电子邮件"From r"。)
还要注意,我们contents.pop(0)用来摆脱列表中的第一个元素。这是因为"From r"字符串在第一封电子邮件之前。拆分该字符串后,它将在索引0处生成一个空字符串。我们将要编写的脚本是为电子邮件设计的。如果我们尝试在空字符串上使用它,则可能会引发错误。摆脱空字符串可以使我们避免破坏脚本。
使用For循环获取每个名称和地址
接下来,我们将使用contents列表中的电子邮件。
在上面的代码中,我们使用for循环来遍历,contents因此我们可以依次处理每封电子邮件。我们创建了一个词典,emails_dict其中包含每封电子邮件的所有详细信息,例如发件人的地址和姓名。实际上,这些是我们发现的第一批物品。
这是一个三步过程。首先从寻找From:领域开始。
在第1步中,我们From:使用re.search()函数查找整个字段。该.装置除了任何字符n,并且*其延伸到行的结尾。然后,我们将其分配给变量sender。
但是,数据并不总是那么简单。它可能包含惊喜。例如,如果没有From:字段怎么办?该脚本将引发错误并中断。我们在步骤2中避免了这种情况下的错误。
为了避免由于缺少From:字段而导致的错误,我们使用一条if语句来检查sendernot None。如果是,我们分配s_email和s_name的值,None以便脚本可以继续运行而不是意外中断。
如果您在自己的文件中使用本教程,则可能已经意识到使用正则表达式会变得混乱。例如,这些if-else语句是在编写主体时对主体使用反复试验的结果。编写代码是一个反复的过程。值得注意的是,即使本教程看起来很简单,实际实践也需要进行更多的实验。
在第2步中,我们使用之前的regex模式\w\S*@.*\w,该模式与电子邮件地址匹配。
我们将对名称使用其他策略。每个名称都由左侧:子字符串的冒号()"From:"和<右侧电子邮件地址的左尖括号()界定。因此,我们使用它:.*<来查找名称。我们摆脱:并<从每个结果的时刻。
现在,让我们打印出代码的结果以查看它们的外观。
同样,我们有匹配对象。每次我们将re.search()字符串应用于字符串时,都会生成匹配对象。我们必须将它们变成字符串对象。
我们这样做之前,记得,如果没有From:现场,sender将具有的价值None,因此也将s_email和s_name。因此,我们必须再次检查这种情况,以便脚本不会意外中断。让我们看看如何首先构建代码s_email。
在步骤3A中,我们使用一条if语句检查s_emailnot None,否则它将引发错误并破坏脚本。
然后,我们只需将s_emailmatch对象转换为字符串并将其分配给sender_email变量。我们将其添加到emails_dict字典中,这将使我们日后将细节转换为pandas数据框变得异常容易。
我们s_name在步骤3B中所做的几乎完全相同。
正如我们以前那样,我们首先检查s_name是不是None在步骤3B。
然后,在将字符串分配给变量之前,我们两次使用re模块的re.sub()函数。首先,我们删除冒号和它与名称之间的所有空白字符。我们:s*用一个空字符串代替""。然后,我们删除空格字符和名称另一边的尖括号,再次用空字符串替换它。最后,在将字符串分配给之后sender_name,我们将其添加到字典中。
让我们检查一下结果。
完善。我们已经隔离了电子邮件地址和发件人的姓名。我们还将它们添加到字典中,该字典将很快投入使用。
现在我们已经找到了发件人的电子邮件地址和名称,我们将执行完全相同的步骤来获取字典的收件人的电子邮件地址和名称。
首先,我们找到To:领域。
接下来,我们抢先在场景recipient是None。
如果recipient不是None,则用于re.search()查找包含电子邮件地址和收件人姓名的匹配对象。否则,我们传递r_email和r_name的值None。
然后,将匹配对象转换为字符串并将其添加到字典中。
由于From:和To:字段的结构相同,因此我们可以对两者使用相同的代码。我们需要为其他字段定制略有不同的代码。
获取电子邮件的日期
现在确定发送电子邮件的日期。
我们Date:为From:和To:字段获取具有相同代码的字段。
并且,就像我们对这两个字段所做的一样,我们检查Date:分配给date_field变量的字段是否不是None。
我们已经打印了出来,date_field.group()以便我们可以更清楚地看到字符串的结构。它包括日期,DD MMM YYYY格式的日期和时间。我们只想要日期。日期的代码与姓名和电子邮件地址基本相同,但更为简单。也许唯一令人困惑的是正则表达式模式\d+\s\w+\s\d+。
日期以数字开头。因此,我们用d它来解释它。但是,作为日期的DD部分,它可以是一位或两位数字。在这里+变得重要。在Python正则表达式中,+匹配其左侧1个或多个模式实例。d+因此,无论日期是DD还是一两位数字,它都将与日期的DD部分匹配。
在那之后,有一个空间。这是由占的s,它查找空白字符。因此,该月由三个字母组成w+。然后它撞到另一个空间s。年份由数字组成,因此我们d+再次使用。
完整模式\d+\s\w+\s\d+起作用的原因是它是一个精确的模式,在两侧均以空格字符为界。
接下来,我们None像以前一样检查值。
如果date不是None,则将其从匹配对象转换为字符串,并将其分配给变量date_sent。然后,将其插入字典中。
在继续之前,我们应该注意一个关键点。+并且*看起来相似,但它们可以产生非常不同的结果。让我们以日期字符串为例。
如果使用*,则将匹配零个或多个匹配项。+匹配一个或多个事件。我们已经打印了两种情况的结果。有很大的不同。如您所见,+获取完整日期,而*获取空格和数字31。
接下来,是电子邮件的主题行。
获取电子邮件主题
和以前一样,我们使用相同的代码和代码结构来获取所需的信息。
现在我们对Python正则表达式的使用越来越熟悉了,不是吗?它与以前的代码大致相同,不同之处在于,我们"Subject: "用空字符串代替仅获取主题本身。
获取电子邮件的正文
要插入字典的最后一项是电子邮件的正文。
将标头与电子邮件正文分开是一项非常复杂的任务,尤其是当许多标头以一种或另一种方式不同时。在原始的无组织数据中很少发现一致性。对我们来说幸运的是,这项工作已经完成。Python的email软件包非常擅长此任务。
请记住,我们已经较早导入了该软件包。现在,我们将其message_from_string()功能应用于item,以将完整的电子邮件转换为emailMessage对象。Message对象由标头和有效负载组成,它们分别对应于电子邮件的标头和正文。
接下来,我们将其get_payload()功能应用于Message对象。此功能隔离电子邮件的正文。我们将其分配给变量body,然后将其插入到emails_dict键下的字典中"email_body"。
为什么使用电子邮件软件包而不是正文
您可能会问,为什么使用emailPython软件包而不是regex?这是因为目前还没有很好的方法来处理Python正则表达式,而这不需要大量的清理工作。这意味着可能需要另外一份教程。
值得检查一下我们如何做出这样的决定。但是,我们需要先了解[ ]正则表达式中的方括号,然后才能这样做。
[ ]匹配放置在其中的任何字符。例如,如果我们要查找"a","b"或"c"字符串,则可以将其[abc]用作模式。我们上面讨论的模式也适用。[\w\s]会找到字母数字或空格字符。例外是.,它成为方括号内的文字周期。
现在,我们可以更好地了解我们是如何决定使用电子邮件软件包的。
窥视数据集可发现电子邮件标题在字符串"Status: 0"或处停止"Status: R0",并"From r"在下一封电子邮件的字符串前结束。因此,我们可以Status:\s*\w*\n*[\s\S]*From\sr*用来仅获取电子邮件正文。[\s\S]*适用于大块的文本,数字和标点符号,因为它可以搜索空白或非空白字符。
不幸的是,有些电子邮件包含多个"Status:"字符串,而另一些则不包含"From r",这意味着我们会将电子邮件拆分成多于或少于电子邮件列表中词典的数量。它们与我们已经拥有的其他类别不匹配。使用熊猫时,这会产生问题。因此,我们决定利用该email软件包。
创建词典列表
最后,将字典追加emails_dict到emails列表中:
我们可能要emails在此时打印列表以查看其外观。如果您只是一直在使用我们的小样本文件,那么这将是反高潮的,但是在整个语料库中,您将看到正则表达式的强大功能!
我们还可以print(len(emails_dict))查看列表中有多少个词典,因此还有电子邮件。如前所述,整个语料库包含3977。
这是完整的代码:
如果使用我们的示例文本文件运行它,将会得到以下结果:
我们已经打印出emails列表中的第一项,它显然是带有键和值对的字典。因为我们使用了for循环,所以每个字典都具有相同的键但值不同。
我们已替换为item,"email content here"以便我们不会打印出电子邮件的全部内容并阻塞屏幕。如果您要使用实际数据集在家打印此文件,则会看到整个电子邮件。
用熊猫处理数据
有了列表中的词典,我们使熊猫图书馆的工作变得无比轻松。每个键将成为列标题,每个值将成为该列中的一行。
我们要做的就是应用以下代码:
通过这一行,我们emails使用pandas DataFrame()函数将字典列表转换为数据框。我们也将其分配给变量。
而已。现在,我们有了一个复杂的熊猫数据框。这实际上是一个整洁的表格,其中包含我们从电子邮件中提取的所有信息。
让我们看一下前几行。
该dataframe.head()函数仅显示前几行,而不显示整个数据集。这需要一个论点。一个可选参数允许我们指定要显示多少行。在这里,n=3让我们查看三行。
我们还可以精确地找到我们想要的东西。例如,我们可以找到从特定域名发送的所有电子邮件。但是,让我们学习一种新的正则表达式模式,以提高找到所需项目的精度。
管道符号会|在其任一侧寻找字符。例如,a|b寻找a或b。
|可能看起来与相同[ ],但是它们确实有所不同。假设我们要匹配要么"crab","lobster"或"isopod"。大数据分析Python的正则表达式Regular Expressions使用方法https://www.aaa-cg.com.cn/data/2301.html使用crab|lobster|isopod会比有意义[crablobsterisopod],不是吗?前者将寻找每个单词,而后者将寻找每个字母。
现在,我们|来查找从一个或另一个域名发送的所有电子邮件。
我们在这里使用了相当长的代码。让我们从内而外开始。
emails_df['sender_email']选择标记为的列sender_email。接下来,str.contains(epatra|spinfinder)返回True是否在该列中找到子字符串"epatra"或"spinfinder"。最后,外部emails_df[]返回行的视图,其中该sender_email列包含目标子字符串。好漂亮!
我们也可以查看来自各个单元的电子邮件。为此,我们经历了四个步骤。在步骤1中,我们找到"sender_email"列包含字符串的行的索引"@spinfinder"。注意我们如何使用正则表达式来执行此操作。
在步骤2中,我们使用索引查找电子邮件地址,该loc[]方法作为具有多个不同属性的Series对象返回该电子邮件地址。我们在下面将其打印出来以查看其外观。
在第3步中,我们从系列对象中提取电子邮件地址,就像从列表中提取项目一样。您可以看到它的类型现在是class。
步骤4是提取电子邮件正文的位置。
在步骤4中,emails_df['sender_email'] == "bensul2004nng@spinfinder.com"找到该sender_email列包含value 的行"bensul2004nng@spinfinder.com"。接下来,['email_body'].values查找email_body同一行中的列的值。最后,我们打印出该值。
如您所见,我们可以通过多种方式使用正则表达式,它也可以与大熊猫一起使用!如果您的正则表达式工作包含大量的反复试验,请不要气,,尤其是在您刚刚入门时!
其他资源
自从几年前正则表达式从生物学跃升为工程学以来,正则表达式已取得了巨大的发展。如今,正则表达式已在不同的编程语言中使用,其中除了其基本模式之外还有一些变体。我们已经学习了很多Python正则表达式,并且如果您想将它提高到一个新的水平,那么我们的Python数据清理高级课程可能是一个不错的选择。
您还可以在官方参考资料中找到一些帮助,例如Python 有关其模块的文档re。Google有更快的参考资料。
如果您愿意,也可以开始探索Python regex与其他形式的regex Stack Overflow帖子之间的区别。
如果您需要数据集进行试验,则Kaggle和StatsModels很有用。
最后,这是我们制作的Regex速查表,它也非常有用。
https://www.toutiao.com/i6829923957647344142/
常见的web安全漏洞有哪些?
前言:
在互联网时代,数据安全与个人隐私受到了前所未有的挑战,各种新奇的攻击技术层出不穷。如何才能更好地保护我们的数据?本文主要侧重于分析几种常见的攻击的类型以及防御的方法。
一、XSSXSS (Cross-Site Scripting),跨站脚本攻击,因为缩写和 CSS重叠,所以只能叫 XSS。跨站脚本攻击是指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或JavaScript进行的一种攻击。
跨站脚本攻击有可能造成以下影响:
利用虚假输入表单骗取用户个人信息。利用脚本窃取用户的Cookie值,被害者在不知情的情况下,帮助攻击者发送恶意请求。显示伪造的文章或图片。XSS 的原理是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码,当用户浏览该页之时,嵌入其中 Web 里面的脚本代码会被执行,从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的。
XSS 的攻击方式千变万化,但还是可以大致细分为几种类型。
1.非持久型 XSS(反射型 XSS )
非持久型 XSS 漏洞,一般是通过给别人发送带有恶意脚本代码参数的 URL,当 URL 地址被打开时,特有的恶意代码参数被 HTML 解析、执行。
举一个例子,比如页面中包含有以下代码:
<select> <script> document.write('' + '<option value=1>' + location.href.substring(location.href.indexOf('default=') + 8) + '</option>' ); document.write('<option value=2>English</option>'); </script> </select>
攻击者可以直接通过 URL (类似:https://xxx.com/xxx?default=<script>alert(document.cookie)</script>) 注入可执行的脚本代码。不过一些浏览器如Chrome其内置了一些XSS过滤器,可以防止大部分反射型XSS攻击。
非持久型 XSS 漏洞攻击有以下几点特征:
即时性,不经过服务器存储,直接通过 HTTP 的 GET 和 POST 请求就能完成一次攻击,拿到用户隐私数据。攻击者需要诱骗点击,必须要通过用户点击链接才能发起反馈率低,所以较难发现和响应修复盗取用户敏感保密信息为了防止出现非持久型 XSS 漏洞,需要确保这么几件事情:
Web 页面渲染的所有内容或者渲染的数据都必须来自于服务端。尽量不要从 URL,document.referrer,document.forms 等这种 DOM API 中获取数据直接渲染。尽量不要使用 eval, new Function(),document.write(),document.writeln(),window.setInterval(),window.setTimeout(),innerHTML,document.createElement() 等可执行字符串的方法。如果做不到以上几点,也必须对涉及 DOM 渲染的方法传入的字符串参数做 escape 转义。前端渲染的时候对任何的字段都需要做 escape 转义编码。2.持久型 XSS(存储型 XSS)
持久型 XSS 漏洞,一般存在于 Form 表单提交等交互功能,如文章留言,提交文本信息等,黑客利用的 XSS 漏洞,将内容经正常功能提交进入数据库持久保存,当前端页面获得后端从数据库中读出的注入代码时,恰好将其渲染执行。
举个例子,对于评论功能来说,就得防范持久型 XSS 攻击,因为我可以在评论中输入以下内容
主要注入页面方式和非持久型 XSS 漏洞类似,只不过持久型的不是来源于 URL,referer,forms 等,而是来源于后端从数据库中读出来的数据 。持久型 XSS 攻击不需要诱骗点击,黑客只需要在提交表单的地方完成注入即可,但是这种 XSS 攻击的成本相对还是很高。
攻击成功需要同时满足以下几个条件:
POST 请求提交表单后端没做转义直接入库。后端从数据库中取出数据没做转义直接输出给前端。前端拿到后端数据没做转义直接渲染成 DOM。持久型 XSS 有以下几个特点:
持久性,植入在数据库中盗取用户敏感私密信息危害面广3.如何防御
对于 XSS 攻击来说,通常有两种方式可以用来防御。
1) CSP
CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。
通常可以通过两种方式来开启 CSP:
设置 HTTP Header 中的 Content-Security-Policy设置 meta 标签的方式这里以设置 HTTP Header 来举例:
只允许加载本站资源Content-Security-Policy: default-src 'self'
只允许加载 HTTPS 协议图片Content-Security-Policy: img-src https://*
允许加载任何来源框架Content-Security-Policy: child-src 'none'
如需了解更多属性,请查看Content-Security-Policy文档
对于这种方式来说,只要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,并且 CSP 的兼容性也不错。
2) 转义字符
用户的输入永远不可信任的,最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠进行转义
function escape(str) { str = str.replace(/&/g, '&') str = str.replace(/</g, '<') str = str.replace(/>/g, '>') str = str.replace(/"/g, '&quto;') str = str.replace(/'/g, ''') str = str.replace(/`/g, '`') str = str.replace(/\//g, '/') return str }
但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。
const xss = require('xss') let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>') // -> <h1>XSS Demo</h1><script>alert("xss");</script> console.log(html)
以上示例使用了 js-xss 来实现,可以看到在输出中保留了 h1 标签且过滤了 script 标签。
3) HttpOnly Cookie。
这是预防XSS攻击窃取用户cookie最有效的防御手段。Web应用程序在设置cookie时,将其属性设为HttpOnly,就可以避免该网页的cookie被客户端恶意JavaScript窃取,保护用户cookie信息。
二、CSRFCSRF(Cross Site Request Forgery),即跨站请求伪造,是一种常见的Web攻击,它利用用户已登录的身份,在用户毫不知情的情况下,以用户的名义完成非法操作。
1. CSRF攻击的原理
下面先介绍一下CSRF攻击的原理:
完成 CSRF 攻击必须要有三个条件:
用户已经登录了站点 A,并在本地记录了 cookie在用户没有登出站点 A 的情况下(也就是 cookie 生效的情况下),访问了恶意攻击者提供的引诱危险站点 B (B 站点要求访问站点A)。站点 A 没有做任何 CSRF 防御我们来看一个例子: 当我们登入转账页面后,突然眼前一亮惊现"XXX隐私照片,不看后悔一辈子"的链接,耐不住内心躁动,立马点击了该危险的网站(页面代码如下图所示),但当这页面一加载,便会执行submitForm这个方法来提交转账请求,从而将10块转给黑客。
2.如何防御
防范 CSRF 攻击可以遵循以下几种规则:
Get 请求不对数据进行修改不让第三方网站访问到用户 Cookie阻止第三方网站请求接口请求时附带验证信息,比如验证码或者 Token1) SameSite
可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送,可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。
2) Referer Check
HTTP Referer是header的一部分,当浏览器向web服务器发送请求时,一般会带上Referer信息告诉服务器是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。可以通过检查请求的来源来防御CSRF攻击。正常请求的referer具有一定规律,如在提交表单的referer必定是在该页面发起的请求。所以通过检查http包头referer的值是不是这个页面,来判断是不是CSRF攻击。
但在某些情况下如从https跳转到http,浏览器处于安全考虑,不会发送referer,服务器就无法进行check了。若与该网站同域的其他网站有XSS漏洞,那么攻击者可以在其他网站注入恶意脚本,受害者进入了此类同域的网址,也会遭受攻击。出于以上原因,无法完全依赖Referer Check作为防御CSRF的主要手段。但是可以通过Referer Check来监控CSRF攻击的发生。
3) Anti CSRF Token
目前比较完善的解决方案是加入Anti-CSRF-Token。即发送请求时在HTTP 请求中以参数的形式加入一个随机产生的token,并在服务器建立一个拦截器来验证这个token。服务器读取浏览器当前域cookie中这个token值,会进行校验该请求当中的token和cookie当中的token值是否都存在且相等,才认为这是合法的请求。否则认为这次请求是违法的,拒绝该次服务。
这种方法相比Referer检查要安全很多,token可以在用户登陆后产生并放于session或cookie中,然后在每次请求时服务器把token从session或cookie中拿出,与本次请求中的token 进行比对。由于token的存在,攻击者无法再构造出一个完整的URL实施CSRF攻击。但在处理多个页面共存问题时,当某个页面消耗掉token后,其他页面的表单保存的还是被消耗掉的那个token,其他页面的表单提交时会出现token错误。
4) 验证码
应用程序和用户进行交互过程中,特别是账户交易这种核心步骤,强制用户输入验证码,才能完成最终请求。在通常情况下,验证码够很好地遏制CSRF攻击。但增加验证码降低了用户的体验,网站不能给所有的操作都加上验证码。所以只能将验证码作为一种辅助手段,在关键业务点设置验证码。
三、点击劫持点击劫持是一种视觉欺骗的攻击手段。攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,在页面中透出一个按钮诱导用户点击。
1. 特点
隐蔽性较高,骗取用户操作"UI-覆盖攻击"利用iframe或者其它标签的属性2. 点击劫持的原理
用户在登陆 A 网站的系统后,被攻击者诱惑打开第三方网站,而第三方网站通过 iframe 引入了 A 网站的页面内容,用户在第三方网站中点击某个按钮(被装饰的按钮),实际上是点击了 A 网站的按钮。接下来我们举个例子:我在优酷发布了很多视频,想让更多的人关注它,就可以通过点击劫持来实现
iframe { width: 1440px; height: 900px; position: absolute; top: -0px; left: -0px; z-index: 2; -moz-opacity: 0; opacity: 0; filter: alpha(opacity=0); } button { position: absolute; top: 270px; left: 1150px; z-index: 1; width: 90px; height:40px; } </style> ...... <button>点击脱衣</button> <img src="http://pic1.win4000.com/wallpaper/2018-03-19/5aaf2bf0122d2.jpg"> <iframe src="http://i.youku.com/u/UMjA0NTg4Njcy" scrolling="no"></iframe>
从上图可知,攻击者通过图片作为页面背景,隐藏了用户操作的真实界面,当你按耐不住好奇点击按钮以后,真正的点击的其实是隐藏的那个页面的订阅按钮,然后就会在你不知情的情况下订阅了。
3. 如何防御
1)X-FRAME-OPTIONS
X-FRAME-OPTIONS是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防御用 iframe 嵌套的点击劫持攻击。
该响应头有三个值可选,分别是
DENY,表示页面不允许通过 iframe 的方式展示SAMEORIGIN,表示页面可以在相同域名下通过 iframe 的方式展示ALLOW-FROM,表示页面可以在指定来源的 iframe 中展示2)JavaScript 防御
对于某些远古浏览器来说,并不能支持上面的这种方式,那我们只有通过 JS 的方式来防御点击劫持了。
<head> <style id="click-jack"> html { display: none !important; } </style> </head> <body> <script> if (self == top) { var style = document.getElementById('click-jack') document.body.removeChild(style) } else { top.location = self.location } </script> </body>
以上代码的作用就是当通过 iframe 的方式加载页面时,攻击者的网页直接不显示所有内容了。
给大家推荐一个好用的BUG监控工具Fundebug,欢迎免费试用!
四、URL跳转漏洞定义:借助未验证的URL跳转,将应用程序引导到不安全的第三方区域,从而导致的安全问题。
1.URL跳转漏洞原理
黑客利用URL跳转漏洞来诱导安全意识低的用户点击,导致用户信息泄露或者资金的流失。其原理是黑客构建恶意链接(链接需要进行伪装,尽可能迷惑),发在QQ群或者是浏览量多的贴吧/论坛中。安全意识低的用户点击后,经过服务器或者浏览器解析后,跳到恶意的网站中。
恶意链接需要进行伪装,经常的做法是熟悉的链接后面加上一个恶意的网址,这样才迷惑用户。
诸如伪装成像如下的网址,你是否能够识别出来是恶意网址呢?
http://gate.baidu.com/index?act=go&url=http://t.cn/RVTatrd http://qt.qq.com/safecheck.html?flag=1&url=http://t.cn/RVTatrd http://tieba.baidu.com/f/user/passport?jumpUrl=http://t.cn/RVTatrd
2.实现方式:
Header头跳转Javascript跳转META标签跳转这里我们举个Header头跳转实现方式:
<?php $url=$_GET['jumpto']; header("Location: $url"); ?> http://www.wooyun.org/login.php?jumpto=http://www.evil.com
这里用户会认为www.wooyun.org都是可信的,但是点击上述链接将导致用户最终访问www.evil.com这个恶意网址。
3.如何防御
1)referer的限制
如果确定传递URL参数进入的来源,我们可以通过该方式实现安全限制,保证该URL的有效性,避免恶意用户自己生成跳转链接
2)加入有效性验证Token
我们保证所有生成的链接都是来自于我们可信域的,通过在生成的链接里加入用户不可控的Token对生成的链接进行校验,可以避免用户生成自己的恶意链接从而被利用,但是如果功能本身要求比较开放,可能导致有一定的限制。
五、SQL注入SQL注入是一种常见的Web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。
1.SQL注入的原理
我们先举一个万能钥匙的例子来说明其原理:
<form action="/login" method="POST"> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="password" name="password" /></p> <p><input type="submit" value="登陆" /></p> </form>
后端的 SQL 语句可能是如下这样的:
let querySQL = ` SELECT * FROM user WHERE username='${username}' AND psw='${password}' `; // 接下来就是执行 sql 语句...
这是我们经常见到的登录页面,但如果有一个恶意攻击者输入的用户名是 admin' --,密码随意输入,就可以直接登入系统了。why! ----这就是SQL注入
我们之前预想的SQL 语句是:
SELECT * FROM user WHERE username='admin' AND psw='password'
但是恶意攻击者用奇怪用户名将你的 SQL 语句变成了如下形式:
SELECT * FROM user WHERE username='admin' --' AND psw='xxxx'
在 SQL 中,' --是闭合和注释的意思,-是注释后面的内容的意思,所以查询语句就变成了:
SELECT * FROM user WHERE username='admin'
所谓的万能密码,本质上就是SQL注入的一种利用方式。
一次SQL注入的过程包括以下几个过程:
获取用户请求参数拼接到代码当中SQL语句按照我们构造参数的语义执行成功SQL注入的必备条件:
1.可以控制输入的数据2.服务器要执行的代码拼接了控制的数据。
我们会发现SQL注入流程中与正常请求服务器类似,只是黑客控制了数据,构造了SQL查询,而正常的请求不会SQL查询这一步,SQL注入的本质:数据和代码未分离,即数据当做了代码来执行。
2.危害
获取数据库信息管理员后台用户名和密码获取其他数据库敏感信息:用户名、密码、手机号码、身份证、银行卡信息……整个数据库:脱裤获取服务器权限植入Webshell,获取服务器后门读取服务器敏感文件3.如何防御
严格限制Web应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害后端代码检查输入的数据是否符合预期,严格限制变量的类型,例如使用正则表达式进行一些匹配处理。对进入数据库的特殊字符(',",,<,>,&,*,; 等)进行转义处理,或编码转换。基本上所有的后端语言都有对字符串进行转义处理的方法,比如 lodash 的 lodash._escapehtmlchar 库。所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中,即不要直接拼接 SQL 语句。例如 Node.js 中的 mysqljs 库的 query 方法中的 ? 占位参数。六、OS命令注入攻击OS命令注入和SQL注入差不多,只不过SQL注入是针对数据库的,而OS命令注入是针对操作系统的。OS命令注入攻击指通过Web应用,执行非法的操作系统命令达到攻击的目的。只要在能调用Shell函数的地方就有存在被攻击的风险。倘若调用Shell时存在疏漏,就可以执行插入的非法命令。
命令注入攻击可以向Shell发送命令,让Windows或Linux操作系统的命令行启动程序。也就是说,通过命令注入攻击可执行操作系统上安装着的各种程序。
1.原理
黑客构造命令提交给web应用程序,web应用程序提取黑客构造的命令,拼接到被执行的命令中,因黑客注入的命令打破了原有命令结构,导致web应用执行了额外的命令,最后web应用程序将执行的结果输出到响应页面中。
我们通过一个例子来说明其原理,假如需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去返回一个结果给用户
// 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repo const exec = require('mz/child_process').exec; let params = {/* 用户输入的参数 */}; exec(`git clone ${params.repo} /some/path`);
如果 params.repo 传入的是 https://github.com/admin/admin.github.io.git 确实能从指定的 git repo 上下载到想要的代码。但是如果 params.repo 传入的是 https://github.com/xx/xx.git && rm -rf /* && 恰好你的服务是用 root 权限起的就糟糕了。
2.如何防御
后端对前端提交内容进行规则限制(比如正则表达式)。在调用系统命令前对所有传入参数进行命令行参数转义过滤。不要直接拼接命令语句,借助一些工具做拼接、转义预处理,例如 Node.js 的 shell-escape npm包以上就是常见的web安全漏洞及防御方法!
有什么办法解决吗?
大规模DDos流量清洗
关于服务器被人攻击的处理,当然先要分两种情况,如果是大规模DDos抢注攻击的话,一般对付办法不多,根本办法是通过运营商做流量清洗,分布式部署系统分流。用一些基于公有云的防护手段(费钱,效果一般般),一些安全公司昂贵的设备(作用也不大,有钱就可以多买)。
一般性防护手段一般性防护手段,通过硬防或者软防火墙比如iptables,主要要限制服务器端口访问,除了必须的80,443以外其他端口一律不对外开放。
关于对外开放端口限制和检测的访问,我的原创文章都提过几篇介绍过:
「安全扫描」看好你的大门,企业安全端口扫描实践
基本上就是在外面扫描你服务器ip,看都开了那些端口,对不该开放端口开放的话就封禁掉。主要对外开放的危险端口有 所有udp端口(比如最近大规模针对github的攻击,就用对外开放的memcache udp 11211 udp端口进行的反射式攻击),tcp重点关注端口: 21(ftp),22(ssh) 23(telnet),2181(zookeeper),3306(mysql),6379(redis),8161和61616(mq),11211(memcache),27017/27018(mongodb),9200(elasticsearch)还有其他的根据企业部署情况来增加。
在服务上查看开放的监听端口情况使用命令:
netstat -ntualp
Local地址 类似于 0.0.0.0:3306和 :::22的监听的服务器就要重点关注,一般除了web都不应该对外开放。
对web服务:
1、注意升级所用程序的版本,有漏洞的要及时升级(比如dedecms,struts2的漏洞等),部署的时候注意权限设置,不给多余的权限。
2、部署必要的waf系统,安利下笔者有个开源免费的waf,有需要的可以联系我。
3、部署时候精良先通过CDN或者自己用nginx返乡代理来对用户,不直接把php 应用、tomcat应用服务器对外,这样即可以提高访问效率,增加访问并发,还可以低于短期大流量访问的冲击。
如果服务器被人攻击,挂马了,怎么排除和解决常见异常情况:异常的流量、异常tcp链接(来源端口,往外发的端口)、异常的访问日志(大量的ip频繁的访问个别文件)。
如果部署了监控系统的话(强烈建议部署zabbix,并增加对系统添加专门安全items),可以方便通过zabbix监控图和趋势对比了解这些信息:
利用last,lastb发现异常的用户登录情况,ip来源。
利用lastlog,/var/log/message,/var/log/secure,日志等,是否权限已经被攻陷。
用history 发现shell执行情况信息。
用top,ps,pstree等发现异常进程和服务器负载等情况。
用netstat -natlp发现异常进程情况。用w命令发现当前系统登录用户的情况。
如果发现异常用户,立即修改用户密码,pkill -kill -t tty 剔除异常用户。然后进行进一步处理。
发现异常进程,立即禁止,冻结禁止。
发现一个恶意进程后通过 ls -al /proc/Pid (Pid为具体的进程号),发现进程的启动路径,启动的文件所在目录等信息。
如果发现异常连接数,通过iptables封禁相关端口或者ip
iptables -I INPUT -s ip -j DROP
iptables -I OUTPUT -p tcp --dport 25 -j DROP
iptables -I INPUT -p tcp --dport 25 -j DROP
对清理移动木马,杀掉进程
首先清理掉木马创建的cron 计划项和启动项。
ls -al /etc/proc/Pid/ 找的恶意木马文件。
恶意进程的执行目录和文件
最后用一条命令 kill -9 所有的进程ID && rm -rf 所有涉及的文件和目录。
更多信息可以关注笔者的文章或者咨询笔者:
「系统安全」当网站发生异常,出现安全事故,如何进行排查处置?
「WEB安全」单行命令查杀Webshell(php为例)
Python操作MySQL数据库安全吗?
谢邀!先说一下我平时用Python处理数据的方法。1、设置白名单IP,在内网下操作Pymysql访问数据库;2、数据库连接参数进行封装加密;3、Python脚本进行封装加密;4、程序部署在特定的服务器上;5、定期做网关和系统安全防护与检测。Python操作MySQL数据库要注意防SQL注入攻击,回避注入风险一般是使用ORM和flask网关技术。SQL注入主要是通过拼接SQL语句参数传入系统后台,来进行恶意删除、查询、插入和更新等危险操作。
网站建设中如何降低网站被挂马的风险?
一般用户可能没有感觉,但站长朋友肯定知道,如果一个网站放置一段时间不管它,等某一天你再去看它时,发现它可能都被挂马了。其实网站被挂马是常见现象,特别是基于CMS开发的网站。
网站一旦被挂马,就会给访客和网站自身带来一些麻烦,比如说:
网页上会存在一些恶意脚本,可能会弹出很多垃圾广告弹窗、跳转到不相关甚至是非法的网站上、插入大量链接、网页死循环等,降低了访问体验;
原网站内容被非法篡改,网站面目全非;
影响网站SEO效果,降低百度等排名,网站极容易被降权等;
非法修改网站源码,甚至删除了网站程序文件等,造成数据损失。
上面讲的这些危害后果,其实网站一旦被挂马后,清理也是很麻烦的一件事,因为黑客已经破坏了你网站的源文件,而且不止一处插入了恶意代码。
那这些黑客是如何将恶意代码植入我们网站程序中的呢?无非是这几步:
1、黑客寻找网站漏洞并利用
这里的漏洞主要有这些:
文件上传漏洞:比如上传页面没有对上传文件格式做验证导致上传了动态脚本(如直接上传了php文件),再者是上传页面没有做权限验证导致非法用户也能上传文件等;
表单数据未过滤漏洞:比如用户在发表文章时,可以插入JS、CSS代码,这样就足以植入恶意脚本,页面渲染时就会运行这些JS、CSS代码;
SQL注入漏洞:存在SQL注入点,黑客可以入侵数据库进行操作,严重的还能删库;
管理后台弱口令漏洞:一些管理后台帐号密码过于简单(比如 admin),一猜就中,直接登录进入后台,想怎么操作就怎么操作 ...
2、恶意代码植入
找到漏洞后就可以利用,然后在网页程序中植入恶意代码,这样用户访问到页面后就会加载到这些恶意代码,攻击者的目的也就达到了。
既然我们知道黑客挂马的大致流程,那如何避免网站被挂马呢?结合我十几年的运维经验整理了一些建议供大家参考:
1、网站建设时请尽可能不要选择CMS
现在市面上的CMS源代码都是公开的,所以0day漏洞也很多。漏洞公开后,大家只要找到是这种CMS建的站,基本上都能攻击成功,所以波及范围较广。
但如果我们的程序是自主开发的,那攻击者不知道我们的源码逻辑,攻击难度会很大。如果是基于CMS建的网站,一定要留意官方发布的补丁及时修复。
2、用户提交的数据做好过滤
在WEB开发领域,我们一直强调用户的任何输入都是不能相信的,我们在拿到用户提供的数据后务必要做必要的核验(格式是否正确)和过滤(过滤一些敏感字符)。我的建议是:
数据类型强制转换;
过滤掉这些内容:JS标签及代码、CSS标签及代码、HTML标签中的各类事件、单引号、双引号、SQL关键字;
3、源码目录及文件权限严格控制
这个是很重要的,既使攻击者拿到了上传漏洞,但是我们只允许它上传到特定目录,其它目录没有写权限,那就感染不了,如果没有执行权限,那上传的动态脚本也是无法执行的。
4、后台使用复杂口令
后台地址改成无法猜到的地址,密码一定要设得复杂点。
5、定期对站点进行木马查杀
定期把站点备份好,然后做木马查杀,现在杀毒软件是可以查杀WEB木马的。
以上就是我的观点,对于这个问题大家是怎么看待的呢?欢迎在下方评论区交流 ~ 我是科技领域创作者,十年互联网从业经验,欢迎关注我了解更多科技知识!