有人可以离线编辑javascript文件来运行恶意代码吗?

时间:2021-07-21 16:10:27

I am worried about something related to javascript files of my website, I am not sure if this is doable.

我担心我的网站的javascript文件,我不确定这是否可行。

Js files will be downloaded when someone visits a website, what if someone edited the downloaded js script and inserted his own code, then refreshed the website. In the new refresh the website will read the edited Js file and will run the malicious code. The malicious code might be used to run some code at the server in normal ways.

当有人访问一个网站时,会下载Js文件,如果有人编辑了下载的Js脚本并插入了自己的代码,然后刷新了网站。在新的刷新中,网站将读取编辑好的Js文件并运行恶意代码。恶意代码通常用于在服务器上运行一些代码。

Example:

例子:

A user is only allowed to post an article in his page:

用户只能在其页面上发布文章:

HTML

HTML

Article form will only show for the user in his page.

文章形式将只显示给用户在他的页面。

<?php
if( $user->id == $page->userID )
{
?>    
<form>
<h1>Add new article:</h1><br />
<textarea name="articleText" cols="65" rows="3"></textarea>
<input class="SubmitArticle" id="<?php echo $userPage->id; ?>" name="SubmitArticle" type="button" value="Submit article" />
</form>
<?php
}
?>

Javascript

Javascript

$(".SubmitArticle").click( function(e){
    var targetPage = $(this).attr('id');
    var thisForm = $(this).parent();
    var postData = thisForm.serialize() + "&targetPage=" + targetPage;

    $.post(document.location, postData, function(data) {
        $('#mainDiv').html(data);
    });
});

PHP

PHP

if( isset($_POST["SubmitArticle"]) )
{
    $pageID = $_POST["targetPage"];
    $text = $_POST["articleText"];

    PublishArticle( $pageID , $text );
}

Malicious Code:

恶意代码:

Code inserted in JS file to write article on other users pages (which is not allowed), the attacker reads page id from html element using view page source (lets say page_id=12):

在JS文件中插入的代码用于在其他用户页面上写文章(不允许),攻击者使用视图页面源从html元素中读取页面id(假设page_id=12):

postData = "SubmitArticle=1&targetPage=12&articleText='Muwhahahah'";
$.post(document.location, postData, function(data) {
});

What is the solution if this is possible?

如果可能的话,解决方案是什么?

8 个解决方案

#1


3  

You are right to be worried, don't trust the client. Ever.

你担心是对的,不要相信客户。永远。

In your example you should validate the user prior to publishing the article, something like:

在您的示例中,应该在发布文章之前验证用户,比如:

if( isset($_POST["SubmitArticle"]) ){
    $pageID = $_POST["targetPage"];
    $text = $_POST["articleText"];

    if( $user->id == $page->userID ){
      PublishArticle( $pageID , $text );
    }
}

Don't stop there

不要停在这里

In addition, you should not trust that the client will send you valid article text and page id. It could be a SQL Injection, malicious javascript, page breaking html, etc. You need to sanitize your inputs as well.

此外,您不应该相信客户端会发送有效的文章文本和页面id,它可能是SQL注入、恶意javascript、页面破坏html等。

#2


3  

I think you have some misunderstanding on how a web-server works.

我认为您对web服务器的工作方式有一些误解。

From the client point of view everything the server sends to the client is readonly.

从客户机的角度来看,服务器发送给客户机的所有内容都是只读的。

Imagine you have downloaded a zip file from the internet. You then modify it and save it. The save process will happen on your hard-drive and not on the server. When you edit your local file (in your example the javascript file) it won't be edited on the server, just on your local PC.

假设您从internet上下载了一个zip文件。然后修改并保存它。保存过程将发生在您的硬盘上,而不是服务器上。当您编辑本地文件(在您的示例中是javascript文件)时,它不会在服务器上进行编辑,而是在您的本地PC上。

Therefor you are free to do / edit your local files like you want. Unless you somehow upload it to the server (FTP for example) it will only be on your local PC.

因此你可以*地做/编辑你想要的本地文件。除非您以某种方式将其上载到服务器(例如FTP),否则它将只在您的本地PC上。

With this in mind you should always validate the data also on your serverside as a skilled user could edit your javascript to remove data validation and send it to the server.

记住这一点,您应该始终验证服务器端上的数据,因为熟练的用户可以编辑javascript以删除数据验证并将其发送到服务器。

#3


2  

A smart user can easily break client side validation.
client is doing this in its end so we need not to worry, un till he is sending a wrong data to server.
so apply the server side validation.

聪明的用户可以很容易地破坏客户端验证。客户端最终会这样做,所以我们不必担心,un直到他向服务器发送错误的数据。所以应用服务器端验证。

->like the length of data comming from user  
->he is a geniune person to send data or not etc.  
->he is on session or not 
->check the data type, as expecting(type castings)  
->check userId equals to sessionId in server side also not only in client side  

it is also known as Cross-Site Scripting

它也被称为跨站脚本。

Cross-site scripting is one of the most common vulnerabilities in web applications. It consists of injecting malicious JavaScript into web pages using forms that your application provides.

跨站点脚本是web应用程序中最常见的漏洞之一。它包括使用应用程序提供的表单向web页面注入恶意JavaScript。

Let’s say you’re writing a blog, and anyone can add a comment. If you blindly include what commenters have written into your HTML page, you’re opening your site to attacks. It can be:

假设你正在写博客,任何人都可以添加评论。如果你盲目地将评论写进你的HTML页面,你的网站就会受到攻击。它可以是:

Show a popup to your visitors
Redirect your visitors to a site controlled by the attacker
Steal information supposed to be visible only to the current user, and send it back to the attacker’s site

Consequently it is very important to be protected from those attacks.

因此,保护自己不受这些攻击是非常重要的。

check this for example for server side validation example

检查服务器端验证示例

#4


1  

You always need some server validation in your form processing php code, like:

在处理php代码的表单中,您总是需要一些服务器验证,比如:

if( isset($_POST["SubmitArticle"]) )
{
  $pageID = $_POST["targetPage"];
  $text = $_POST["articleText"];

  // here write some code to create a page from pageID

  if ($user->id == $page->userID)
  {
     PublishArticle( $pageID , $text );
  }
}

#5


1  

Whenever dealing with user input make sure the input is never executed as code during the whole chain of processing (receive, store, read, send, output). Therefore never render user input as HTML like .innerHTML in Javascript or .html() like you do in jQuery

无论何时处理用户输入,都要确保在整个处理链(接收、存储、读取、发送、输出)中不会将输入作为代码执行。因此,永远不要像在jQuery中那样将用户输入呈现为HTML(如.innerHTML)或.html()

//jQuery
$('#mainDiv').html(data);

//JavaScript
mainDiv.innerHTML = data;

always use text instead:

总是用文字代替:

//jQuery
$('#mainDiv').text(data);

//JavaScript
mainDiv.appendChild(document.createTextNode(data));

If you need markup in your data then things get much more complicated and you should provide your own (reduced) markup language like SO or Wikipedia are doing it.

如果您需要在数据中添加标记,那么事情会变得更加复杂,您应该提供您自己的(简化的)标记语言,比如SO或Wikipedia正在这样做。

#6


0  

Whenever a user uploads anything (which is supposed to be visible by other users) to the server side you have to secure it. One way would be to escape all special characters (which may be interpretted as JavaScript), for example convert all . to its HTML equivalent &#46;. You may want to escape HTML as well simply by converting all < to &#60;. The characters I would go for are at least these: <>.=()[].

当用户将任何内容(其他用户应该可以看到)上传到服务器端时,必须对其进行保护。一种方法是转义所有特殊字符(可以解释为JavaScript),例如转换所有字符。到它的HTML等价物.。您也可以通过将所有< <转换为<来转义html。我想要的字符至少是这些:<> .=()[]。

You can check special codes here. There should be some PHP library for that though. I'm not sure, I'm not PHP developer.

你可以在这里查看特殊代码。应该有一些PHP库。我不确定,我不是PHP开发人员。

#7


0  

Actually there are much easier ways to run code in the browser than editing the downloaded js files. The user can run js code in the console of the browser or write an browser extension that will run user javascript. And I believe this is a feature, not a bug.

实际上,在浏览器中运行代码比编辑下载的js文件要容易得多。用户可以在浏览器的控制台中运行js代码,或者编写一个浏览器扩展来运行用户javascript。我相信这是一个特性,而不是缺陷。

What you need to do is to make sure on the server side that the user does not do anything that he/she has no right to do, you can not trust in anything coming from the client.

您需要做的是在服务器端确保用户没有做任何他/她没有权利做的事情,您不能信任来自客户端的任何事情。

Also, if you follow this rule user code running in the browser is usually only a problem when he/she can make that code run on other user's browser (you have no way to limit the user from running any js code in his/her browser he/she wants).

此外,如果您遵循这一规则,那么在浏览器中运行的用户代码通常只在他/她可以让该代码在其他用户的浏览器上运行时才会出现问题(您无法限制用户在他/她想要的浏览器中运行任何js代码)。

#8


0  

Well, it is not so much a "changing the contents of a cached JS file"-issue, as any code that runs on a client machine can be altered for malicious use. That, and most browsers nowadays have a convenient console allowing you to create and run JavaScript functions on the fly making this nicely easy!

好吧,这与其说是“修改缓存的JS文件的内容”,不如说是问题,因为在客户端机器上运行的任何代码都可以被修改为恶意使用。现在大多数浏览器都有一个方便的控制台,允许您动态地创建和运行JavaScript函数,这非常简单!

The solution is in securing your code on the servier-side, i.e. in the example you mention in the method that takes the POST data and publishes it as a new article.

解决方案是在服务端保护您的代码,例如您在方法中提到的,该方法获取POST数据并将其作为一篇新文章发布。

You can overcome this in numerous manners, one would be validating the users session by passing a token along with the article data. Server side, you create and pair a unique token for a unique user session and store it there. The token thus isn't the session identifier, but an identifier that should be interpreted as "the pass allowing user x to submit an article under conditions y". So for instance the HTML page could be creating a hidden form field containing this unique string which is only valid for a single request, and for a specific user session. So when the user submits the form, the server not only validates the contents of the form (as this too could be tampered with on the client side), but also reads the token value and tries to find a stored match for it for the users session AND validates whether it is valid for the action the user is trying to execute. After passing these validations, the stored token can be removed as it is now invalid. You could add additional checks to see whether to token was used in a given time slot should you want to, whether the IP still matches, or preferably whether the user hasn't logged out of that session in the meantime, etc (IF you use registered users in your application, this has the benefit that you can only allow registered users to submit data, but this has the down side that it requires all visitors to register before they can interact with the site.).

您可以通过多种方式克服这个问题,其中之一是通过在文章数据中传递一个令牌来验证用户会话。服务器端,您将为一个独特的用户会话创建和配对一个唯一的令牌并将其存储在那里。因此,令牌不是会话标识符,而是一个标识符,应该被解释为“允许用户x在条件y下提交文章的通行证”。例如,HTML页面可以创建一个隐藏的表单字段,其中包含这个唯一的字符串,这个字符串只对单个请求有效,对特定的用户会话有效。所以,当用户提交表单时,服务器不仅验证表单的内容(这也可以在客户端篡改),但也读取存储的令牌值,并试图找到一个匹配的用户会话并验证是否有效的用户正在执行的操作。通过这些验证之后,存储的令牌可以被删除,因为它现在是无效的。你可以添加额外的检查是否在给定的时间段使用令牌应该你想,IP是否仍然匹配,或者最好是用户没有登录的会话是否同时,等等(如果你在应用程序中使用的注册用户,这有好处,你可以只允许注册用户提交的数据,但这下侧,它要求所有访客注册之前与网站交互)。

So if a funny guy tries to re-submit the same form but with nonsensical (or malicious!) data, the server side code would deny the request as the token was used / or the users session doesn't match the stored token and thus is invalid (additionally, you could also use server side validation to look for naughty words in the body text, non-valid e-mail addresses, etc, but that has more to do with sanitizing the content of your website, rather than strict security).

如果一个有趣的家伙试图重新提交相同的形式,但荒谬的(或恶意!)数据,服务器端代码会否认请求令牌/或使用令牌存储的用户会话不匹配,因此是无效的(此外,你也可以使用服务器端验证寻找粗俗的词语在正文,无效的电子邮件地址,等等,但这更多的与消毒你的网站的内容,而不是严格的安全)。

#1


3  

You are right to be worried, don't trust the client. Ever.

你担心是对的,不要相信客户。永远。

In your example you should validate the user prior to publishing the article, something like:

在您的示例中,应该在发布文章之前验证用户,比如:

if( isset($_POST["SubmitArticle"]) ){
    $pageID = $_POST["targetPage"];
    $text = $_POST["articleText"];

    if( $user->id == $page->userID ){
      PublishArticle( $pageID , $text );
    }
}

Don't stop there

不要停在这里

In addition, you should not trust that the client will send you valid article text and page id. It could be a SQL Injection, malicious javascript, page breaking html, etc. You need to sanitize your inputs as well.

此外,您不应该相信客户端会发送有效的文章文本和页面id,它可能是SQL注入、恶意javascript、页面破坏html等。

#2


3  

I think you have some misunderstanding on how a web-server works.

我认为您对web服务器的工作方式有一些误解。

From the client point of view everything the server sends to the client is readonly.

从客户机的角度来看,服务器发送给客户机的所有内容都是只读的。

Imagine you have downloaded a zip file from the internet. You then modify it and save it. The save process will happen on your hard-drive and not on the server. When you edit your local file (in your example the javascript file) it won't be edited on the server, just on your local PC.

假设您从internet上下载了一个zip文件。然后修改并保存它。保存过程将发生在您的硬盘上,而不是服务器上。当您编辑本地文件(在您的示例中是javascript文件)时,它不会在服务器上进行编辑,而是在您的本地PC上。

Therefor you are free to do / edit your local files like you want. Unless you somehow upload it to the server (FTP for example) it will only be on your local PC.

因此你可以*地做/编辑你想要的本地文件。除非您以某种方式将其上载到服务器(例如FTP),否则它将只在您的本地PC上。

With this in mind you should always validate the data also on your serverside as a skilled user could edit your javascript to remove data validation and send it to the server.

记住这一点,您应该始终验证服务器端上的数据,因为熟练的用户可以编辑javascript以删除数据验证并将其发送到服务器。

#3


2  

A smart user can easily break client side validation.
client is doing this in its end so we need not to worry, un till he is sending a wrong data to server.
so apply the server side validation.

聪明的用户可以很容易地破坏客户端验证。客户端最终会这样做,所以我们不必担心,un直到他向服务器发送错误的数据。所以应用服务器端验证。

->like the length of data comming from user  
->he is a geniune person to send data or not etc.  
->he is on session or not 
->check the data type, as expecting(type castings)  
->check userId equals to sessionId in server side also not only in client side  

it is also known as Cross-Site Scripting

它也被称为跨站脚本。

Cross-site scripting is one of the most common vulnerabilities in web applications. It consists of injecting malicious JavaScript into web pages using forms that your application provides.

跨站点脚本是web应用程序中最常见的漏洞之一。它包括使用应用程序提供的表单向web页面注入恶意JavaScript。

Let’s say you’re writing a blog, and anyone can add a comment. If you blindly include what commenters have written into your HTML page, you’re opening your site to attacks. It can be:

假设你正在写博客,任何人都可以添加评论。如果你盲目地将评论写进你的HTML页面,你的网站就会受到攻击。它可以是:

Show a popup to your visitors
Redirect your visitors to a site controlled by the attacker
Steal information supposed to be visible only to the current user, and send it back to the attacker’s site

Consequently it is very important to be protected from those attacks.

因此,保护自己不受这些攻击是非常重要的。

check this for example for server side validation example

检查服务器端验证示例

#4


1  

You always need some server validation in your form processing php code, like:

在处理php代码的表单中,您总是需要一些服务器验证,比如:

if( isset($_POST["SubmitArticle"]) )
{
  $pageID = $_POST["targetPage"];
  $text = $_POST["articleText"];

  // here write some code to create a page from pageID

  if ($user->id == $page->userID)
  {
     PublishArticle( $pageID , $text );
  }
}

#5


1  

Whenever dealing with user input make sure the input is never executed as code during the whole chain of processing (receive, store, read, send, output). Therefore never render user input as HTML like .innerHTML in Javascript or .html() like you do in jQuery

无论何时处理用户输入,都要确保在整个处理链(接收、存储、读取、发送、输出)中不会将输入作为代码执行。因此,永远不要像在jQuery中那样将用户输入呈现为HTML(如.innerHTML)或.html()

//jQuery
$('#mainDiv').html(data);

//JavaScript
mainDiv.innerHTML = data;

always use text instead:

总是用文字代替:

//jQuery
$('#mainDiv').text(data);

//JavaScript
mainDiv.appendChild(document.createTextNode(data));

If you need markup in your data then things get much more complicated and you should provide your own (reduced) markup language like SO or Wikipedia are doing it.

如果您需要在数据中添加标记,那么事情会变得更加复杂,您应该提供您自己的(简化的)标记语言,比如SO或Wikipedia正在这样做。

#6


0  

Whenever a user uploads anything (which is supposed to be visible by other users) to the server side you have to secure it. One way would be to escape all special characters (which may be interpretted as JavaScript), for example convert all . to its HTML equivalent &#46;. You may want to escape HTML as well simply by converting all < to &#60;. The characters I would go for are at least these: <>.=()[].

当用户将任何内容(其他用户应该可以看到)上传到服务器端时,必须对其进行保护。一种方法是转义所有特殊字符(可以解释为JavaScript),例如转换所有字符。到它的HTML等价物.。您也可以通过将所有< <转换为<来转义html。我想要的字符至少是这些:<> .=()[]。

You can check special codes here. There should be some PHP library for that though. I'm not sure, I'm not PHP developer.

你可以在这里查看特殊代码。应该有一些PHP库。我不确定,我不是PHP开发人员。

#7


0  

Actually there are much easier ways to run code in the browser than editing the downloaded js files. The user can run js code in the console of the browser or write an browser extension that will run user javascript. And I believe this is a feature, not a bug.

实际上,在浏览器中运行代码比编辑下载的js文件要容易得多。用户可以在浏览器的控制台中运行js代码,或者编写一个浏览器扩展来运行用户javascript。我相信这是一个特性,而不是缺陷。

What you need to do is to make sure on the server side that the user does not do anything that he/she has no right to do, you can not trust in anything coming from the client.

您需要做的是在服务器端确保用户没有做任何他/她没有权利做的事情,您不能信任来自客户端的任何事情。

Also, if you follow this rule user code running in the browser is usually only a problem when he/she can make that code run on other user's browser (you have no way to limit the user from running any js code in his/her browser he/she wants).

此外,如果您遵循这一规则,那么在浏览器中运行的用户代码通常只在他/她可以让该代码在其他用户的浏览器上运行时才会出现问题(您无法限制用户在他/她想要的浏览器中运行任何js代码)。

#8


0  

Well, it is not so much a "changing the contents of a cached JS file"-issue, as any code that runs on a client machine can be altered for malicious use. That, and most browsers nowadays have a convenient console allowing you to create and run JavaScript functions on the fly making this nicely easy!

好吧,这与其说是“修改缓存的JS文件的内容”,不如说是问题,因为在客户端机器上运行的任何代码都可以被修改为恶意使用。现在大多数浏览器都有一个方便的控制台,允许您动态地创建和运行JavaScript函数,这非常简单!

The solution is in securing your code on the servier-side, i.e. in the example you mention in the method that takes the POST data and publishes it as a new article.

解决方案是在服务端保护您的代码,例如您在方法中提到的,该方法获取POST数据并将其作为一篇新文章发布。

You can overcome this in numerous manners, one would be validating the users session by passing a token along with the article data. Server side, you create and pair a unique token for a unique user session and store it there. The token thus isn't the session identifier, but an identifier that should be interpreted as "the pass allowing user x to submit an article under conditions y". So for instance the HTML page could be creating a hidden form field containing this unique string which is only valid for a single request, and for a specific user session. So when the user submits the form, the server not only validates the contents of the form (as this too could be tampered with on the client side), but also reads the token value and tries to find a stored match for it for the users session AND validates whether it is valid for the action the user is trying to execute. After passing these validations, the stored token can be removed as it is now invalid. You could add additional checks to see whether to token was used in a given time slot should you want to, whether the IP still matches, or preferably whether the user hasn't logged out of that session in the meantime, etc (IF you use registered users in your application, this has the benefit that you can only allow registered users to submit data, but this has the down side that it requires all visitors to register before they can interact with the site.).

您可以通过多种方式克服这个问题,其中之一是通过在文章数据中传递一个令牌来验证用户会话。服务器端,您将为一个独特的用户会话创建和配对一个唯一的令牌并将其存储在那里。因此,令牌不是会话标识符,而是一个标识符,应该被解释为“允许用户x在条件y下提交文章的通行证”。例如,HTML页面可以创建一个隐藏的表单字段,其中包含这个唯一的字符串,这个字符串只对单个请求有效,对特定的用户会话有效。所以,当用户提交表单时,服务器不仅验证表单的内容(这也可以在客户端篡改),但也读取存储的令牌值,并试图找到一个匹配的用户会话并验证是否有效的用户正在执行的操作。通过这些验证之后,存储的令牌可以被删除,因为它现在是无效的。你可以添加额外的检查是否在给定的时间段使用令牌应该你想,IP是否仍然匹配,或者最好是用户没有登录的会话是否同时,等等(如果你在应用程序中使用的注册用户,这有好处,你可以只允许注册用户提交的数据,但这下侧,它要求所有访客注册之前与网站交互)。

So if a funny guy tries to re-submit the same form but with nonsensical (or malicious!) data, the server side code would deny the request as the token was used / or the users session doesn't match the stored token and thus is invalid (additionally, you could also use server side validation to look for naughty words in the body text, non-valid e-mail addresses, etc, but that has more to do with sanitizing the content of your website, rather than strict security).

如果一个有趣的家伙试图重新提交相同的形式,但荒谬的(或恶意!)数据,服务器端代码会否认请求令牌/或使用令牌存储的用户会话不匹配,因此是无效的(此外,你也可以使用服务器端验证寻找粗俗的词语在正文,无效的电子邮件地址,等等,但这更多的与消毒你的网站的内容,而不是严格的安全)。