任务1:介绍
JavaScript (JS) 是一种流行的脚本语言,它允许 Web 开发人员向包含 HTML 和 CSS(样式)的网站添加交互式功能。创建 HTML 元素后,您可以通过 JS 添加交互性,例如验证、onClick 操作、动画等。学习该语言与 HTML 和 CSS 一样重要。JS 脚本主要用于 HTML。
这个房间被设计为 JS 的介绍性概述,专为 JS 经验有限的初学者量身定制。主要重点是从网络角度教授 JS 的基础知识以及黑客如何利用合法功能来实现恶意结果。
会议室先决条件
- Linux的基础模块
- Web 应用程序基础知识
- 网站如何运作
学习目标
- 了解 JS 的基础知识
- 在 HTML 中集成 JS
- 滥用对话功能
- 绕过 Control Flow 语句
- 浏览缩小的文件
连接到本机
您可以通过单击 来启动虚拟机。本机将以分屏视图启动。如果 VM 不可见,请使用页面左上角的蓝色按钮。请在系统完全启动后等待 1-2 分钟,以让自动脚本成功运行。Start Machine
Show Split View
注意:我们在这个房间中创建的所有脚本也可以在连接的 VM 的桌面上的 exercise 文件夹中找到,如下所示。如果您发现自己创建脚本很困难,也可以使用提供的脚本。
任务2:基本概念
变量
变量是允许您在其中存储数据值的容器。与任何其他语言一样,JS 中的变量类似于存储数据的容器。当您在存储桶中存储某些内容时,您还需要对其进行标记,以便以后可以轻松引用它。同样,在 JS 中,每个变量都有一个名称;当我们在变量中存储某个值时,我们会为其分配一个名称,以便稍后引用它。在 JS 中声明变量有三种方法:var、let 和const 。其中var 是函数范围的,而 let和const 都是块范围的,可以更好地控制特定代码块中的变量可见性。
数据类型
在 JS 中,数据类型定义了变量可以保存的值的类型。示例包括 (text)、、(true/false)、null、undefined 和 object(用于数组或对象等更复杂的数据)。
string
number
boolean
功能
函数表示旨在执行特定任务的代码块。在函数中,对需要执行类似任务的代码进行分组。例如,您正在开发一个 Web 应用程序,您需要在其中将学生的成绩打印到网页上。理想的情况是创建一个函数,该函数将接受用户的卷号作为参数。PrintResult(rollNum)
<script>function PrintResult(rollNum) {alert("Username with roll number " + rollNum + " has passed the exam");// any other logic to display the result}for (let i = 0; i < 100; i++) {PrintResult(rollNumbers[i]);}</script>
因此,我们将使用一个简单的函数来打印结果,而不是为所有学生编写相同的打印代码。
循环loops
循环允许您多次运行代码块,只要条件为 。JS 中的常见循环是 , 和 ,它们用于重复任务,例如浏览项目列表。例如,如果我们想打印 100 名学生的成绩,我们可以通过写入 100 次来调用 PrintResult(rollNum) 函数 100 次,或者我们可以创建一个循环,该循环将从 1 到 100 迭代,并调用 PrintResult(rollNum) 函数,如下所示。
true
for
while,
do...while
// Function to print student resultfunction PrintResult(rollNum) {alert("Username with roll number " + rollNum + " has passed the exam");// any other logic to the display result}for (let i = 0; i < 100; i++) {PrintResult(rollNumbers[i]); // this will be called 100 times }
请求-响应周期
在 Web 开发中,请求-响应周期是指用户的浏览器(客户端)向 Web 服务器发送请求,服务器使用请求的信息进行响应。这可以是网页、数据或其他资源。您可以在此处了解更多信息。
任务3:JavaScript 概述
在此任务中,我们将使用 JS 创建我们的第一个程序。JS 是一种解释型语言,这意味着代码直接在浏览器中执行,无需事先编译。下面是一个示例 JS 代码,演示了关键概念,例如定义变量、理解数据类型、使用控制流语句和编写简单函数。这些基本构建块有助于创建更具动态性和交互性的 Web 应用程序。如果它现在看起来有点新,请不要担心 - 我们稍后将详细讨论这些概念中的每一个。
// Hello, World! program
console.log("Hello, World!");// Variable and Data Type
let age = 25; // Number type// Control Flow Statement
if (age >= 18) {console.log("You are an adult.");
} else {console.log("You are a minor.");
}// Function
function greet(name) {console.log("Hello, " + name + "!");
}// Calling the function
greet("Bob");
S 主要在客户端执行,这使得直接在浏览器中检查 HTML 并与之交互变得容易。我们将使用该功能来运行我们的第一个 JS 程序,让我们无需额外的工具即可轻松编写和执行 JS 代码。请按照以下步骤开始:Google Chrome Console
- 通过单击 VM 桌面上的 图标打开。
Google Chrome
Google Chrome
- 打开 Chrome 后,按 打开 或右键单击页面上的任意位置并选择 。
Ctrl + Shift + I
Console
Inspect
然后,单击选项卡。此控制台允许您直接在浏览器中运行 JS 代码,而无需安装其他软件。C
- 让我们创建一个简单的 JS 程序,将两个数字相加并显示结果。下面是代码:
let x = 5;
let y = 10;
let result = x + y;
console.log("The result is: " + result);
- 在上面的代码中, 和 是保存数字的变量。 是将两个数字相加的表达式,而 是用于将结果打印到控制台的函数。
x
y
x + y
console.log
- 复制上述代码并按 键将其粘贴到控制台中。粘贴后,按 。您应该会看到结果显示为:
Ctrl + V
Enter
任务4:将 JavaScript 集成到 HTML 中
此任务假定您对 HTML 及其结构有基本的了解。本节将探讨如何将 JS 集成到 HTML 中。通常,JS 不用于呈现内容;它与 HTML 和 CSS 一起创建动态和交互式网页。如果您不熟悉 HTML,建议您通过提供的链接进行查看。将 JS 集成到 HTML 中有两种主要方法:内部和外部。
内部 JavaScript
内部 JS 是指将 JS 代码直接嵌入到 HTML 文档中。这种方法更适合初学者,因为它允许他们查看脚本如何与 HTML 交互。脚本将插入到标记之间。这些标签可以放置在部分内,通常用于需要在呈现页面内容之前加载的脚本,也可以放置在部分内,当元素加载到网页上时,可以使用脚本与元素进行交互。<script>
<head>
<body>
例
要使用内部 JS 创建 HTML 文档,请右键单击 并选择 > 。将文件命名为 。接下来,右键单击该文件并在文本编辑器中打开它。Desktop
Create Document
Empty File
internal.html
internal.html
choose Open with Pluma
编辑器打开后,粘贴以下代码:
<!DOCTYPE html>
<html lang="en">
<head><title>Internal JS</title>
</head>
<body><h1>Addition of Two Numbers</h1><p id="result"></p><script>let x = 5;let y = 10;let result = x + y;document.getElementById("result").innerHTML = "The result is: " + result;</script>
</body>
</html>
粘贴代码后,单击并选择 ,这会将文件保存到 。双击该文件以在 Chrome 浏览器中打开它,您将在其中看到以下输出:File
Save
internal.html
在此 HTML 文档中,我们使用内部 JS,这意味着代码直接放置在 HTML 文件中的 <script> 标记内。该脚本执行一项简单的任务:它添加两个数字(x 和 y),然后在网页上显示结果。JS 通过选择一个元素(<p> 和 id=“result”) 并使用 .此内部 JS 在浏览器加载 HTML 文件时执行。document.getElementById("result").innerHTML
外部 JavaScript
外部 JS 涉及在以文件扩展名结尾的单独文件中创建和存储 JS 代码。此方法可帮助开发人员保持 HTML 文档的整洁和组织。外部 JS 文件可以存储或托管在与 HTML 文档相同的 Web 服务器上,也可以存储在外部 Web 服务器(如云)上。.js
我们将对外部 JS 使用相同的示例,但将 JS 代码分离到不同的文件中。
首先,创建一个名为 的新文件,并使用以下代码将其保存在 上:script.js
Desktop
let x = 5;
let y = 10;
let result = x + y;
document.getElementById("result").innerHTML = "The result is: " + result;
接下来,创建一个名为 的新文件并粘贴以下代码(请注意,HTML 代码与上一个示例的代码相同):external.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>External JS</title>
</head>
<body><h1>Addition of Two Numbers</h1><p id="result"></p><!-- Link to the external JS file --><script src="script.js"></script>
</body>
</html>
现在,双击 external.html 文件并检查结果。您认为有什么不同吗?否,输出与上一个示例中的相同。
我们所做的不同是使用 <script> 标记中的属性从外部文件加载 JS。当浏览器加载页面时,它会查找文件并将其内容加载到 HTML 文档中。这种方法允许我们将 JS 代码与 HTML 分开,使代码更有条理且易于维护,尤其是在处理大型项目时。src
script.js
验证内部或外部 JS
在对 Web 应用程序进行渗透测试时,检查网站是使用内部 JS 还是外部 JS 非常重要。这可以通过查看页面的源代码来轻松验证。为此,请打开位于 的文件夹中的页面,右键单击页面上的任意位置,然后选择 。external_test.html
exercise
Chrome
View Page Source
这将显示呈现的页面的 HTML 代码。在源代码中,直接在页面上编写的任何 JS 都将出现在 <script> 标签之间,而不带该属性。如果您看到带有 src 属性的 <script> 标记,则表示该页面正在从单独的文件加载外部 JS。src
有关实际示例,请访问浏览器中的 https://tryhackme.com 并检查源代码以确定网站如何在内部和外部源加载 JS。
任务5:滥用对白功能
JS 的主要目标之一是提供用于与用户交互的对话框,并动态更新网页上的内容。JS 提供了 、 和 等内置函数来促进这种交互。这些函数允许开发人员显示消息、收集输入并获得用户确认。但是,如果未安全实施,攻击者可能会利用这些功能来执行跨站点脚本 (XSS) 等攻击,您将在本模块后面介绍。alert
prompt
confirm
我们将在即将到来的练习中使用 。Google Chrome console
警报Alert
alert 函数在对话框中显示带有 “” 按钮的消息,通常用于向用户传达信息或警告。例如,如果我们想向用户显示 “”,我们将使用 .要试用,请打开 Chrome 控制台,键入 ,然后按 Enter。屏幕上将出现一个包含该消息的对话框。OK
Hello THM
alert("HelloTHM");
alert("Hello THM")
提示Prompt
提示函数显示一个对话框,要求用户输入。当用户单击 “OK
” 时,它将返回输入的值,如果用户单击 “Cancel
”,则返回 null。例如prompt("What is your name?");
,要询问用户的姓名,我们将使用 .
要对此进行测试,请打开 Chrome 控制台并粘贴以下内容,该内容要求提供用户名,然后向他打招呼。
name = prompt("What is your name?");alert("Hello " + name);
粘贴代码并按 Enter 键后,将出现一个对话框,用户输入的值将返回到控制台。
将出现一个对话框,根据用户是单击 “” 还是 “”,值 true 或 false 将返回到控制台。OK
Cancel
黑客如何利用该功能
想象一下,您收到一封来自陌生人的电子邮件,其中附有一个 HTML 文件。该文件看起来无害,但当您打开它时,它包含会破坏您的浏览体验的 JS。例如,以下代码将显示一个警报框,其中包含消息 “Hacked” 三次:
<!DOCTYPE html>
<html lang="en">
<head><title>Hacked</title>
</head>
<body><script>for (let i = 0; i < 3; i++) {alert("Hacked");}</script>
</body>
</html>
在附加的 VM 的 Desktop (桌面) 上,创建一个名为 并粘贴上述代码的文件。双击该文件将其打开,警报消息将弹出 3 次,从而导致意外体验。invoice.html
想象一下,如果不良行为者向您发送了一个类似的文件,但该数字不是显示警报 3 次,而是设置为 500。您将被迫一个接一个地关闭警报框。这是一个简单的例子,说明如何使用恶意 JS 来制造不便或更糟。因此,确保您只从受信任的来源执行 JS 文件对于避免这种不希望的体验至关重要。
任务6:绕过 Control Flow 语句
JS 中的控制流是指根据特定条件执行语句和代码块的顺序。JS 提供了多种控制流结构,例如if-else
用于做出决策的 ,switch
语句,以及用于重复操作的循环for
, while
以及do...while
。正确使用控制流可确保程序能够有效地处理各种情况。
操作中的条件语句
最常用的条件语句之一是if-else
语句,它允许您根据条件的计算结果是否为true
或 false
来执行不同的代码块。
为了实际测试这一点,让我们在附加的 VM 的桌面上创建一个age.html
文件并粘贴以下代码:
<!DOCTYPE html>
<html lang="en">
<head><title>Age Verification</title>
</head>
<body><h1>Age Verification</h1><p id="message"></p><script>age = prompt("What is your age")if (age >= 18) {document.getElementById("message").innerHTML = "You are an adult.";} else {document.getElementById("message").innerHTML = "You are a minor.";}</script>
</body>
</html>
双击该文件以在 Google Chrome 中打开它。您将看到下图:
在上面的代码中,系统会提示您的年龄。如果您的年龄大于或等于 18 岁,则会显示一条消息You are an adult.
,指出 “”否则,将显示不同的消息。此行为由 if-else 语句控制,该语句检查 age 变量的值并根据条件显示相应的消息。
绕过登录表单
假设开发人员在 JS 中实现了身份验证功能,其中仅允许用户名为 “admin
” 且密码与特定值匹配的用户登录。要查看实际效果,请打开 exercises 文件夹中的login.html
文件。
当您双击该文件并在浏览器中打开它时,它会提示您输入用户名和密码。如果输入了正确的凭据,则会显示一条消息,确认您已登录,如下所示:
直接查看源码
任务7:浏览缩小的文件
到目前为止,我们已经了解了 JS 的工作原理以及如何读取它,但如果文件不是人类可读的并且已被缩小怎么办?
JS 中的缩小是通过删除所有不必要的字符(例如空格、换行符、注释,甚至缩短变量名称)来压缩 JS 文件的过程。这有助于减小文件大小并缩短网页的加载时间,尤其是在生产环境中。缩小的文件使代码更紧凑,更难为人类阅读,但它们的功能仍然完全相同。
同样,混淆通常用于通过添加不需要的代码、将变量和函数重命名为无意义的名称,甚至插入虚拟代码来使 JS 更难理解。
实例
在连接的 VM 的桌面上创建一个名称为hello.html
该文件的文件,并粘贴以下 HTML 代码:
<!DOCTYPE html>
<html lang="en">
<head><title>Obfuscated JS Code</title>
</head>
<body><h1>Obfuscated JS Code</h1><script src="hello.js"></script>
</body>
</html>
然后,创建另一个具有该名称的文件并添加以下代码:hello.js
function hi() {alert("Welcome to THM");
}
hi();
现在,双击该文件以在 Google Chrome 中打开它。打开hello.html
文件后,您将看到一条警报,以 “Welcome to THM
” 向您致意。
单击OK
以关闭警报对话框。右键单击页面上的任意位置,然后单击Inspect
以打开开发人员工具。在开发人员工具中,导航到Sources
选项卡并单击hello.js
文件以查看源代码。您将看到 JS 代码易于访问和查看,如下所示:
混淆操作
现在,我们将尝试使用在线工具缩小和混淆 JS 代码。访问 Web 站点(https://codebeautify.org/javascript-obfuscator)并复制 hello.js
的内容,然后将其粘贴到 Web 站点上的对话框中。该工具将缩小和混淆代码,将其转换为一串乱码字符,如下所示:
但是,如果我们告诉你这些乱码字符仍然是功能齐全的代码呢?唯一的区别是它们不是人类可读的,但浏览器仍然可以正确执行它们。该网站将我们的 JS 代码转换为以下代码:
(function(_0x114713,_0x2246f2){var _0x51a830=_0x33bf,_0x4ce60b=_0x114713();while(!![]){try
{var _0x51ecd3=-parseInt(_0x51a830(0x88))/(-0x1bd3+-0x9a+0x2*0xe37)*(parseInt(_0x51a830(0x94))/
(-0x15c1+-0x2*-0x3b3+0xe5d))+parseInt(_0x51a830(0x8d))/(0x961*0x1+0x2*0x4cb+0x4bd*-0x4)*
(-parseInt(_0x51a830(0x97))/(-0x22b3+0x16e9+0x1*0xbce))+parseInt(_0x51a830(0x89))/
(-0x631+0x20cd+0x8dd*-0x3)*(-parseInt(_0x51a830(0x95))/(-0x8fc+0x161+0x7a1))+-
parseInt(_0x51a830(0x93))/(-0x1c38+0x193+0x1aac)*(parseInt(_0x51a830(0x8e))/
(-0x1*-0x17a6+-0x167e+-0x3*0x60))+-parseInt(_0x51a830(0x91))/(-0x2*-0x1362+-0x4a8*0x5+-0xf73)*
(parseInt(_0x51a830(0x8b))/(-0xb31*0x2+0x493*0x5+0x1*-0x73))+parseInt(_0x51a830(0x8f))/
(-0x257a+-0x1752+0x3cd7)+parseInt(_0x51a830(0x90))/(-0x2244+-0x15f9+0x3849);if(_0x51ecd3
===_0x2246f2)break;else _0x4ce60b['push'](_0x4ce60b['shift']());}catch(_0x38d15c)
{_0x4ce60b['push'](_0x4ce60b['shift']());}}}(_0x11ed,-0x17d11*-0x1+0x2*0x2e27+0x100f*0x17));
function hi(){var _0x48257e=_0x33bf,_0xab1127={'xMVHQ':function(_0x4eefa0,_0x4e5f74)
{return _0x4eefa0(_0x4e5f74);},'FvtWc':_0x48257e(0x96)+_0x48257e(0x92)};_0xab1127[_0x48257e(0x8c)
](alert,_0xab1127[_0x48257e(0x8a)]);}function _0x33bf(_0xb07259,_0x5949fe){var _0x3a386b
=_0x11ed();return _0x33bf=function(_0x4348ee,_0x1bbf73){_0x4348ee=_0x4348ee-(0x11f7+-
0x1*0x680+-0x3a5*0x3);var _0x423ccd=_0x3a386b[_0x4348ee];return _0x423ccd;},_0x33bf
(_0xb07259,_0x5949fe);}function _0x11ed(){var _0x4c8fa8=['7407EbJESQ','\x20THM',
'2700698TTmqXC','10ILFtfZ','190500QONgph','Welcome\x20to',
'4492QOmepo','21623eEAyaP','65XMlsxw','FvtWc','2410qfnGAy','xMVHQ','321PfYXZg',
'8XBaIAe','1946483GviJfa','15167592PYYhTN'];_0x11ed=function(){return _0x4c8fa8;};return _0x11ed();}hi();
单击Copy to Clipboard
网站上显示的(在上图中突出显示为 2)按钮。然后,删除附加的 VM 上的当前内容hello.js
,并将模糊处理的内容粘贴到文件中。
在 Google Chrome 中重新加载hello.html
文件,并在选项卡下再次检查源Sources
代码。您会注意到,代码现在已经过混淆处理,但功能仍与以前完全相同。
对代码进行反混淆处理
我们还可以使用在线工具对加密代码进行反混淆。访问该网站,然后将模糊处理的代码粘贴到提供的对话框中。该网站将为您生成等效的、人类可读的 JS 代码,从而更容易理解和分析原始脚本。
Obfuscator.io Deobfuscator
您已经看到我们多么轻松地对原始代码进行混淆处理和检索。
任务8:最佳实践
此任务概述了评估网站或为网站编写代码的最佳实践。如果您正在开发 Web 应用程序,您最终可能会在您的网站上使用 JS。以下做法将帮助您减少攻击面并最大限度地减少攻击机会。
避免仅依赖客户端验证
JS 的主要功能之一是执行客户端验证。开发人员有时使用它来验证表单并完全依赖它,这不是一个好的做法。由于用户可以在客户端禁用/操作 JS,因此在服务器端执行验证也是必不可少的。
避免添加不受信任的库
如前面的任务中所述,JS 允许您在标签中包含使用该属性的任何其他 JS 脚本。但是您是否考虑过我们包含的库是否来自可信来源?不良行为者在 Internet 上上传了一堆名称类似于合法库的库。因此,如果您盲目地包含恶意库,您的 Web 应用程序将面临威胁。src
script
避免硬编码密钥
切勿将 API 密钥、访问令牌或凭据等敏感数据硬编码到您的 JS 代码中,因为用户可以轻松检查源代码并获取密码。
// Bad Practice
const privateAPIKey = 'pk_TryHackMe-1337';
缩小和混淆 JavaScript 代码
缩小和模糊处理 JS 代码可以减小其大小,缩短加载时间,并使攻击者更难理解代码的逻辑。因此,在生产环境中使用代码时,请始终缩小和模糊处理代码。攻击者最终可以对其进行逆向工程,但获取原始代码至少需要一些努力。