In order to add a new comment you really only need a couple of fields and a POST
method.
In a typical comment form, requests are submitted to http://www.example.com/
wp-comments-post.php
which parses the $_POST
data and sends it off to wp_handle_comment_submission
.
A POST
method varies from a GET
request in that params are usually sent in a non-visual way. With GET
you might see www.example.com?foo=bar
but in a POST
method the params are sent in addition to the url request so you visually only see www.example.com
.
Another thing to note is that the page
/post
ID can usually be seen as a class in the page’s body section. <body class="page page-id-1234"
so in order to submit a comment to a page you would really only need that ID coupled with the wp-comments-post.php
url.
Here is an example using POSTMAN
to construct the request for PHP:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://www.vistex.com/wp-comments-post.php",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"email-notes\"\r\n\r\nemail-notes-here\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_post_ID\"\r\n\r\n134\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"author\"\r\n\r\n4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"email\"\r\n\r\[email protected]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"url\"\r\n\r\nhttp://wordpress.stackexchange.com/questions/221084/bots-posting-comments-on-pages\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment\"\r\n\r\nspam_from_stackexchange_brandozzzzzzz - http://wordpress.stackexchange.com/users/64789/brandozz - http://wordpress.stackexchange.com/questions/221084/bots-posting-comments-on-pages\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_parent\"\r\n\r\n134\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"_wp_unfiltered_html_comment\"\r\n\r\n_wp_unfiltered_html_comment\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
"content-type: multipart/form-data; boundary=---011000010111000001101001",
"postman-token: c34ed3e0-fcc4-2b4b-75bf-d864135cddde"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
And the same request in jQuery:
var form = new FormData();
form.append("email-notes", "email-notes-here");
form.append("comment_post_ID", "134");
form.append("author", "4");
form.append("email", "[email protected]");
form.append("url", "http://wordpress.stackexchange.com/questions/221084/bots-posting-comments-on-pages");
form.append("comment", "spam_from_stackexchange_brandozzzzzzz - http://wordpress.stackexchange.com/users/64789/brandozz - http://wordpress.stackexchange.com/questions/221084/bots-posting-comments-on-pages");
form.append("comment_parent", "134");
form.append("_wp_unfiltered_html_comment", "_wp_unfiltered_html_comment");
var settings = {
"async": true,
"crossDomain": true,
"url": "https://www.vistex.com/wp-comments-post.php",
"method": "POST",
"headers": {
"cache-control": "no-cache",
"postman-token": "a66dc74a-685e-719c-75be-9c81ab69bf5e"
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
}
$.ajax(settings).done(function (response) {
console.log(response);
});
As you can see, all the data is removed from the URL and sent with the data fields. You can also see that a WP front-end isn’t required to send the comment request and that any language can submit a comment from anywhere. Awesome right? 🙁
That being said, when I tried this method on the page you described I got a response back:
<html>...
<p>Sorry, comments are closed for this item.</p>
...</html>
That’s because the simple check to see if the page accepts comments in the first place:
if ( ! comments_open( $comment_post_ID ) ) {
Then throws and error if they aren’t open:
return new WP_Error( 'comment_closed', __( 'Sorry, comments are closed for this item.' ), 403 );
So, in your case, there may be another way or there could be something else running that triggers a new comment:
$commentdata = compact(
'comment_post_ID',
'comment_author',
'comment_author_email',
'comment_author_url',
'comment_content',
'comment_type',
'comment_parent',
'user_ID'
);
$comment_id = wp_new_comment( wp_slash( $commentdata ) );