清理请求体并执行POST请求到API。

huangapple go评论66阅读模式
英文:

Sanitizing request body doing a POST request to API

问题

我想使用 htmlspecialchars 来在进行 POST 请求之前对数据进行清理,但一直出现以下错误:

url=*** - Uncaught TypeError: http_build_query(): Argument #1 ($data) must be of type array, string given

这是与此错误相关的函数以及触发它的方式:

function makePostRequest($baseURL) {
    $ch = curl_init();
    $clean_post =  htmlspecialchars($POST);
    $data = http_build_query($clean_post);
    curl_setopt($ch, CURLOPT_URL, $baseURL);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);

    if($e = curl_error($ch)) {
        echo $e;
    } else {
        $json = json_decode($response, true);
        return print_r($json);
    }
}
...
$response = "";
switch (getRequestMethod()) {
  case 'GET':
    $response = makeGetRequest($baseURL);
    break;
  case 'POST':
    $response = makePostRequest($baseURL);
    break;
  default:
    echo "There has been an error";
    return;
}

这是我在 POST 请求的一部分发送的数据示例:

data = {
    name:'***',
    password: '***',
    userID: emailAddress,
    userSecret: password
}
console.log('data', data)
jQuery.ajax({
    type: "POST",
    url: "proxy.php?url=***",
    dataType: "json",
    contentType: 'application/x-www-form-urlencoded',
    data: data,
    success: function (data){
        console.log('success', data)
    }
});

这段代码中的关键问题是在使用 htmlspecialchars 函数来清理数据时,应该将数据传递给它,而不是 $POST。此外,http_build_query 需要一个数组作为参数,但现在传递的是字符串。您需要确保在传递给 http_build_query 的数据是一个数组,并且在使用 htmlspecialchars 之前正确处理它。

英文:

I would like to use htmlspecialchars to sanitize data before doing a POST request but keep getting the error:

url=*** - Uncaught TypeError: http_build_query(): Argument #1 ($data) must be of type array, string given

This is the function related to this error and how it is getting triggered:

function makePostRequest($baseURL) {
    $ch = curl_init();
    $clean_post =  htmlspecialchars($POST);
    $data = http_build_query($clean_post);
    curl_setopt($ch, CURLOPT_URL, $baseURL);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);

    if($e = curl_error($ch)) {
        echo $e;
    } else {
        $json = json_decode($response, true);
        return print_r($json);
    }
}
...
$response = "";
switch (getRequestMethod()) {
  case 'GET':
    $response = makeGetRequest($baseURL);
    break;
  case 'POST':
    $response = makePostRequest($baseURL);
    break;
  default:
    echo "There has been an error";
    return;
}

This is a sample of the data I am sending as part of the POST request:

    data = {
        name:'***',
        password: '***',
        userID: emailAddress,
        userSecret: password
    }
    console.log('data', data)
    jQuery.ajax({
        type: "POST",
        url: "proxy.php?url=***",
        dataType: "json",
        contentType: 'application/x-www-form-urlencoded',
        data: data,
        success: function (data){
            console.log('success', data)
        }
    });
});

答案1

得分: 2

实际错误在于htmlspecialchars返回一个字符串(而不是一个数组),但http_build_query期望你提供一个数组,正如错误消息所指出的。然而,没有必要直接尝试修复它,因为你一开始就不应该这样做。

你对htmlspecialchars()的使用是不合适的,可能会引发问题。htmlspecialchars()是一个输出过滤器,只能在将数据输出到HTML文档时_特别_使用。它的设计仅用于防止XSS攻击 - 这只会发生在加载到启用JavaScript的Web浏览器中的HTML文档中。

它不应在接收输入数据等任何其他时间使用 - 最坏的情况下,它可能会在那种情况下更改或损坏你的数据。它与发送HTTP请求也无关。另请参阅何时使用htmlspecialchars()函数?

你没有将这些数据写入将在浏览器中显示的HTML文档,因此无需对数据进行HTML编码,或尝试"净化"数据以防范其他问题(例如你在评论中提到的SQL注入),这些问题与你的直接使用无关。

你也不知道你将发送数据给的第三方API是否会尝试将你提供的数据放入HTML或SQL上下文,或其他任何地方。如果他们不这样做,那么没有人需要担心。如果他们这样做,那么他们有责任在适当的时候处理数据。他们应该将你的应用视为潜在威胁 - 你提供的输入数据是他们无法控制的,他们不知道它是如何到达的,来自哪里,或者你如何处理它。

如果你过早地对不会进入HTML文档的数据进行HTML编码,你只会冒着损坏它的风险(比如,假设我在我的密码中使用了字符<,这应该是完全合法的...对它使用htmlspecialchars会在我不知情的情况下更改它,这意味着我不再知道我的真实密码,而这种更改将不会产生有用的结果)。在这里你无法对SQL注入进行净化,因为那涉及到编写参数化查询,而在这种情况下,你不是在编写查询代码。


P.S.

事实上,我曾经为一个向普通公众提供服务的大型商业组织创建了一个帐户,他们在我注册时默默地从我提供的密码中删除了一个#字符,这意味着我无法正确登录。根据我的了解,我最终猜到发生了什么事情,并尝试不包含该字符的相同密码,这样我就可以成功登录。因此,人们在现实生活中确实会这样做,这会引发实际问题 - 没有相关经验的人将不知道为什么无法正常工作。

我向他们的帮助台报告了这个问题,他们的开发人员最初不知道我在提到什么,这本身就令人担忧,对于一个如此规模的组织来说,他们不了解他们对数据做了什么。最终,我认为他们修复了这个问题,但我留下这个轶事,只是为了证明这些都是真正存在的问题,而不仅仅是技术上的琐事。

英文:

The actual error here is because htmlspecialchars returns a string (rather than an array), but http_build_query expects you to give it an array, as the error message points out. However, there's no point trying to fix it directly, because you shouldn't be doing this to begin with.

Your usage of htmlspecialchars() is inappropriate and potentially problematic. htmlspecialchars() is an output filter, only to be used specifically when outputting data into a HTML document. It is designed only to help protect against XSS attacks - which are something that can only occur in a HTML document loaded into a web browser with JavaScript enabled.

It should not be used at any other time, such as when receiving input data -at worst it can change or corrupt your data unnecessarily in that situation. It also has nothing to do with sending in a HTTP request either. See also when to use htmlspecialchars() function?.

You're not writing this data to a HTML document which is going to be displayed in a browser so there is no need to HTML-encode the data, or try to "sanitise" it against anything else (e.g. SQL injection as you mentioned in the comments) that you aren't directly using it for.

You also have no idea whether the 3rd party whose API you are sending it to will try to put any of the data you provide into either a HTML or SQL context, or anything else. If they don't, there's nothing for anyone to worry about. And if they do, then it's their responsibility to deal with the data accordingly at the right moment. They should be treating your application as a potential threat - you're providing input data they don't control, and they don't know how it got there or where it came from, or how you've processed it.

If you prematurely HTML-encode data which isn't going anywhere near a HTML document then you simply risk corrupting it (e.g. imagine I used the character < in my password, which ought to be a perfectly legitimate thing to do...using htmlspecialchars on that would alter it without my knowledge, meaning I don't know my real password anymore, and the alteration wouldn't achieve anything useful). And you physically cannot sanitise for SQL injection here, because that involves writing parameterised queries, and in this case you're not the one writing the query code.


P.S.

I actually once created an account with a large commercial organisation which provides services to the general public, and they silently stripped a # character from the password I provided at registration, meaning I couldn't log in properly. Knowing what I know about these processes, I eventually guessed what had happened and tried the same password without that character and it logged me in. So people actually do this stuff in real life and it causes real problems - anyone without relevant experience would have no idea why it wasn't working.

I reported it to their helpdesk and their developers initially had no idea what I was referring too, which was worrying in itself, for an organisation of that size not to have the understanding of what they were doing to the data. Eventually I think they fixed it, but I leave this anecdote here just to demonstrate that these are real issues, and not just technical pedantry.

huangapple
  • 本文由 发表于 2023年2月23日 20:36:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75544933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定