简体   繁体   English

防止 Javascript 中的 HTML 和脚本注入

[英]Preventing HTML and Script injections in Javascript

Assume I have a page with an input box.假设我有一个带有输入框的页面。 The user types something into the input box and hits a button.用户在输入框中输入内容并点击按钮。 The button triggers a function that picks up the value typed into the text box and outputs it onto the page beneath the text box for whatever reason.该按钮会触发一个函数,该函数选取输入到文本框中的值并将其输出到文本框下方的页面上,无论出于何种原因。

Now this has been disturbingly difficult to find a definitive answer on or I wouldn't be asking but how would you go about outputting this string:现在很难找到一个明确的答案,否则我不会问,但你会如何输出这个字符串:

<script>alert("hello")</script> <h1> Hello World </h1>

So that neither the script is executed nor the HTML element is displayed?这样既不执行脚本也不显示 HTML 元素?

What I'm really asking here is if there is a standard method of avoiding both HTML and Script injection in Javascript .我在这里真正要问的是,是否有一种标准方法可以避免在Javascript 中同时避免 HTML 和 Script 注入。 Everyone seems to have a different way of doing it (I'm using jQuery so I know I can simply output the string to the text element rather than the html element for instance, that's not the point though).每个人似乎都有不同的方法(我使用的是 jQuery,所以我知道我可以简单地将字符串输出到文本元素而不是html元素,例如,这不是重点)。

You can encode the < and > to their HTML equivelant.您可以将<>编码为它们的 HTML 等效项。

html = html.replace(/</g, "&lt;").replace(/>/g, "&gt;");

How to display HTML tags as plain text 如何将 HTML 标签显示为纯文本

myDiv.textContent = arbitraryHtmlString 

as @Dan pointed out, do not use innerHTML, even in nodes you don't append to the document because deffered callbacks and scripts are always executed.正如@Dan 指出的那样,不要使用innerHTML,即使在您不附加到文档的节点中也是如此,因为延迟回调和脚本总是被执行。 You can check this https://gomakethings.com/preventing-cross-site-scripting-attacks-when-using-innerhtml-in-vanilla-javascript/ for more info.您可以查看此https://gomakethings.com/preventing-cross-site-scripting-attacks-when-using-innerhtml-in-vanilla-javascript/了解更多信息。

A one-liner:单线:

var encodedMsg = $('<div />').text(message).html();

See it work:看看它的工作:

https://jsfiddle.net/TimothyKanski/wnt8o12j/ https://jsfiddle.net/TimothyKanski/wnt8o12j/

I use this function htmlentities($string):我使用这个函数 htmlentities($string):

 $msg = "<script>alert("hello")</script> <h1> Hello World </h1>" $msg = htmlentities($msg); echo $msg;

From here从这里

var string="<script>...</script>";
string=encodeURIComponent(string); // %3Cscript%3E...%3C/script%3

My solution using typescript + decorators + regex我使用打字稿 + 装饰器 + 正则表达式的解决方案

const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");

 "use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; function filter(target) { return class extends target { constructor(...args) { super(...args); } setState(opts) { const state = { username: this.filter(opts.username), password: this.filter(opts.password), }; super.setState(state); } filter(value) { const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g"); return value.replace(removeTag, ""); } }; } let Form = class Form { constructor() { this.state = { username: "", password: "", }; } setState(opts) { this.state = { ...this.state, ...opts, }; } getState() { return this.state; } }; Form = __decorate([ filter, __metadata("design:paramtypes", []) ], Form); function getElement(key) { return document.getElementById(key); } const button = getElement("btn"); const username = getElement("username"); const password = getElement("password"); const usernameOutput = getElement("username-output"); const passwordOutput = getElement("password-output"); function handleClick() { const form = new Form(); form.setState({ username: username.value, password: password.value }); usernameOutput.innerHTML = `Username: ${form.getState().username}`; passwordOutput.innerHTML = `Password: ${form.getState().password}`; } button.onclick = handleClick;
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <style> :root { --bg: #1d1907; --foreground: #e3e0cd; --primary: #cfb53b; --black: #333; --white: #fafafa; } @keyframes borderColor { from { border-bottom: 1px solid var(--foreground); } to { border-bottom: 1px solid var(--primary); } } * { outline: none; border: none; } body { padding: 0.5rem; font-family: "Fira Code"; background-color: var(--bg); color: var(--foreground); } input { border-bottom: 1px solid var(--foreground); background-color: var(--black); color: var(--foreground); padding: 0.5rem; } input:focus { animation-name: borderColor; animation-duration: 3s; animation-fill-mode: forwards; } button { padding: 0.5rem; border-radius: 3px; border: 1px solid var(--primary); background-color: var(--primary); color: var(--white); } button:hover, button:active { background-color: var(--white); color: var(--primary); } .form { margin-bottom: 2rem; } </style> <title>Decorator</title> </head> <body> <h1>Prevent Injection</h1> <div class="form"> <div class="form-group"> <label for="username">Username</label> <input type="text" id="username" placeholder="Type your username" /> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" placeholder="Type your password" /> </div> <div class="form-group"> <button id="btn">Enviar</button> </div> </div> <div class="form-result"> <p id="username-output">Username:</p> <p id="password-output">Password:</p> </div> <script src="/dist/pratica1.js"></script> </body> </html>

Typescript Code bellow:打字稿代码如下:

    type State = {
  username: string;
  password: string;
};

function filter<T extends new (...args: any[]) => any>(target: T): T {
  return class extends target {
    constructor(...args: any[]) {
      super(...args);
    }

    setState(opts: State) {
      const state = {
        username: this.filter(opts.username),
        password: this.filter(opts.password),
      };
      super.setState(state);
    }

    filter(value: string) {
      const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
      return value.replace(removeTag, "");
    }
  };
}

@filter
class Form {
  private state: State;

  constructor() {
    this.state = {
      username: "",
      password: "",
    };
  }

  setState(opts: State) {
    this.state = {
      ...this.state,
      ...opts,
    };
  }

  getState() {
    return this.state;
  }
}

function getElement(key: string): HTMLElement | null {
  return document.getElementById(key);
}

const button = getElement("btn") as HTMLButtonElement;
const username = getElement("username") as HTMLInputElement;
const password = getElement("password") as HTMLInputElement;
const usernameOutput = getElement("username-output") as HTMLParagraphElement;
const passwordOutput = getElement("password-output") as HTMLParagraphElement;

function handleClick() {
  const form = new Form();
  form.setState({ username: username.value, password: password.value });
  usernameOutput.innerHTML = `Username: ${form.getState().username}`;
  passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}

button.onclick = handleClick;

Try this method to convert a 'string that could potentially contain html code' to 'text format':尝试使用此方法将“可能包含 html 代码的字符串”转换为“文本格式”:

$msg = "<div></div>";
$safe_msg = htmlspecialchars($msg, ENT_QUOTES);
echo $safe_msg;

Hope this helps!希望这有帮助!

Use this,用这个,

function restrict(elem){
  var tf = _(elem);
  var rx = new RegExp;
  if(elem == "email"){
       rx = /[ '"]/gi;
  }else if(elem == "search" || elem == "comment"){
    rx = /[^a-z 0-9.,?]/gi;
  }else{
      rx =  /[^a-z0-9]/gi;
  }
  tf.value = tf.value.replace(rx , "" );
}

On the backend, for java , Try using StringUtils class or a custom script.在后端,对于 java ,尝试使用 StringUtils 类或自定义脚本。

public static String HTMLEncode(String aTagFragment) {
        final StringBuffer result = new StringBuffer();
        final StringCharacterIterator iterator = new
                StringCharacterIterator(aTagFragment);
        char character = iterator.current();
        while (character != StringCharacterIterator.DONE )
        {
            if (character == '<')
                result.append("&lt;");
            else if (character == '>')
                result.append("&gt;");
            else if (character == '\"')
                result.append("&quot;");
            else if (character == '\'')
                result.append("&#039;");
            else if (character == '\\')
                result.append("&#092;");
            else if (character == '&')
                result.append("&amp;");
            else {
            //the char is not a special one
            //add it to the result as is
                result.append(character);
            }
            character = iterator.next();
        }
        return result.toString();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM