Can't validate reCAPTCHA in PHP form - php

I can't figure out why the server's response doesn't allow me to validate the recaptcha. My PHP code is:
$captcha = $_POST['g-recaptcha-response'];
$secret = "my key";
$postdata = "secret=".$secret."&response=".$captcha;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
$out = json_decode($server_output);
curl_close($ch);
if($out->success == true){/*make stuff*/} /* when the user clicks, $out->success is not true! */
My HTML form is quite ordinary.
<form method="POST" id="form">
<!-- inputs -->
<div class="g-recaptcha" data-sitekey="my key" style="margin:10px"></div>
<input type="submit" name="submit" value="Valider">
</form>
I know the problem must be really silly. I've found a workaround which is, instead of checking if $out->success==true, checking if strlen($captcha) > 1. But I'm pretty sure it's not very likely to block robots... Any idea? Thanks...
EDIT: I just ran a ZAP attack on my website (ZED attack proxy, a security tool from OWASP foundation). It fails completing the sign-up form (before that, it was able to create 100 users in less than a minute!). So this means that some robots will blocked. I still want to get it done properly though...

Can you try to send your data as an array like that :
$postdata = array(
'secret' => $secret,
'response' => $captcha
);

Related

How to log out of a website that sends back a page to verify if I want to log out using php and curl

I am trying to logout of a website using curl. When clicked on the logout button this websites sends back a page that asks if we want to log out with two buttons "ok" and "cancel". I used curl to get this data
$headers = array(
"GET $geturl HTTP/1.1",
"Host: " . "$ip",
"User-Agent:Mozilla/5.0(X11;Linuxx86_64;rv:45.0)Gecko/20100101Firefox/45.0",
"Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*,q=0.8",
"Referer: " . $referer,
"Cookie: JSESSIONID=" . $session_id,
"Connection: keep-alive",
"Content-Length: 64",
'"etag": W/"102-1257495352000"',
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_TIMEOUT, 15); //timeout after 15 seconds
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLINFO_REDIRECT_URL, true);
curl_setopt($ch, CURLOPT_POSTREDIR, 3);
curl_setopt($ch, CURLOPT_COOKIESESSION, $session_id);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "logout=logout");
$result1 = curl_exec($ch1);
The output contains two forms:
<form name="myLogout" action="logout.jsp" target="main" method="post">
<input name="logout" type="hidden" value="logout">
<input class="yesno" class="button" type="Submit" value=" OK ">
</form>
</td>
<td width="20"></td>
<td>
<form action="start.jsp" target="main">
<input class="yesno" type="Submit" value=" Cancel ">
</form>
Then the session waits around 15 seconds to get a response for a post-event to the "OK" button.
Thus I am sending another post request with the same curl options as above except I changed CURLOPT_CUSTOMREQUEST from "GET" to "POST", But I am getting either null or "Bad Request".
Can someone please help with this.
Here I will do what i can to explain this.
All you have to do to submit that form or any form is to emulate what it is doing.
Ok, what do forms do?
Simply, they send a request to the server using one of 2 methods, GET or POST. GET is the same as using a URL in the browser (which is why when you submit it the query parameters change in the url and you get a new page).
So in theory you just make a POST request to logout.jsp the forms action with the data in the form logout=logout.
Think in terms of if you built that form
<form name="myLogout" action="logout.jsp" target="main" method="post">
<input name="logout" type="hidden" value="logout">
<input class="yesno" class="button" type="Submit" value=" OK ">
</form>
If I built this form, I would build a page at action="logout.jsp" I would be using the $_POST array, etc.(lets assume its PHP)
<?php
if(isset($_POST['logout'])){
session_destroy();
header('Location: www.example.com');
exti();
}else{
//some error message or redirect to 404, this should never happen.
//maybe send message to the Internet police with your IP, just kidding
}
So I would just look for the logout in the post array, then destroy the session, then redirect to my homepage.
So in curl you just need to
curl_setopt($ch, CURLOPT_COOKIESESSION, $session_id);
curl_setopt($ch, CURLOPT_URL, '{www.example.com}/logout.jsp');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'logout=logout');
And then the other standard CURL stuff.
Some things to consider:
Now this may or may not work, there are a lot of variable that I just don't know about to be able to say it will 100%. They can do things with cookies and JavaScript that is beyond what you can do with just CURL (eg. PhantomJS or headless browser scrappers). However, this HTML is pretty simple (eg. no random generated IDs) so I think it's not that advanced.
One thing to do, is in a browser, go to that page when logged in. Press f12 open the browser debug window. Find the network panel, find the record button (or persist). Logout, then inspect the request that was made to the server for that form. This is what you need to replicate.
In conclusion I done to much scrapping over the years. Now we have a .Net guy to handle it. It's a bit better suited to what we needed then PHP.

PHP curl login with captcha failed on specific site

I am trying to login to licindia with curl. But get failed the same code is working at other site.
I have used one of library for dom manipulation "simple_html_dom.php".
Website: http://sourceforge.net/projects/simplehtmldom/
I am able to get captcha but after submitting it gives me "Error : Pl Check your Answer.."
Cookies is set properly.
<?php
require_once './simple_html_dom.php';
$host = 'customer.onlinelic.in';
$home_url = 'https://' . $host . '/';
$login_url = $home_url . 'LICEPS/Login/begin.do';
$user_agent = 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0';
$headers[] = "Host: $host";
$headers[] = "Connection: Keep-Alive";
$headers[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$headers[] = "Host:customer.onlinelic.in";
$headers[] = "Accept-Language:en-US,en;q=0.5";
$headers[] = "Content-Type:application/x-www-form-urlencoded";
$cookie = 'cookie.txt';
function getAnswer() {
global $login_url, $headers, $cookie;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);
$html = str_get_html($response);
$token = $html->find('form[name="chkLoginForm"] span', 3);
return $token;
}
function login() {
global $login_url, $headers, $cookie;
$postFiels = [
'{actionForm.userName}' => '12349743554',
'{actionForm.password}' => 'dfdfg56',
'{actionForm.qreply}' => ($_POST['ans'])
];
$ch = curl_init();
$url = "https://customer.onlinelic.in/LICEPS/Login/secureLogin.do";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_REFERER, $login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postFiels));
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
}
?>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<form action="" method="post">
<p><?php echo getAnswer(); ?></p>
<input type="text" name="ans" value="<?php echo isset($_POST['ans']) ? $_POST['ans'] : ''; ?>" /><br />
<button type="submit" name="submit">Submit</button>
</form>
<?php
if (isset($_POST['submit'])) {
login();
}
?>
</body>
</html>
first off, there's no need to use simple_html_dom, php's built-in DOMDocument & DOMXpath is fully capable of doing this, with minimal knowledge of XPaths, i suggest you study XPaths a little (eg, $token = $html->find('form[name="chkLoginForm"] span', 3); probably translates to $token=$xp->query('//form[#name="chkLoginForm"]')->item(3)->textContent; )
second, don't do this $headers[] = "Host: $host";
- curl will provide the Host header automatically. (the only instances where you'd want to provide the host header manually, as far as i can think of atm, is when you're communicating with a server that has improperly configured their DNS, a very rare event)
third, you don't actually tell curl to use your user-agent string, add that $user_agent variable to CURLOPT_USERAGENT.
fourth, you're giving the host header 2 times, that doesn't make much sense, and is probably an error (and as stated above, you should actually provide it zero times, as curl will also do it for you automatically if you don't.)
fifth, don't provide this header manually Content-Type:application/x-www-form-urlencoded - curl will automatically detect when you're using this encoding type, and send the appropriate headers for you - and unlike you, curl won't make any typos in doing so. (this is also true for multipart/form-data-encoding btw)
with that out of the way, your real problem is that your post fields make no sense, their login request looks NOTHING like that. you try to send the username/password in application/x-www-form-urlencoded encoding, but what they really use is application/json encoding. you try to send the login username in a variable called {actionForm.userName}, but the variable for the username is actually called userId. you try to send the password in a variable called {actionForm.password}, and you try to send it raw, but the password actually goes in a variable called password, and its not sent raw, its first hashed & salted (i'm not sure what hash they use, but the candidates are sha2-512 , sha3-512, and whirlpool, and they are using this library for the hashing: https://github.com/travist/jsencrypt ), hex encoded, and then base64-encoded after the hex encoding again. (obviously the web devs here has no idea what they're doing, as that double encoding is just a waste of cpu, ram, and bandwidth, both for their server, and for the client logging in. they could save 50% bandwidth by taking away the hex encoding), also the login form as a variable called userRole which seems to be hardcoded to Customer, and a variable called dob which is an ISO8601 timestamp of the day you were born, as a question the login form asks you, hardcoded with the time of day being T00:00:00...
if your current code used to work, they must have recently redesigned their login system.
the first thing you need to do is figure out what hash they're using, and figure out where the salt is given, then re-implement that salt & hash mechanism in php, and you must get a session cookie & salt before sending the login request, and... send the correct variables, with the correct encoding (aka, use json_encode()), to https://ebiz.licindia.in/intellect-platform-services/v1.0/login/authenticate
it won't be easy, and i can't be arsed digging further for you (unless you're willing to pay for it)

Not getting a response from web service - not sure what I'm doing wrong

This is my first shot at getting something back from a web service. What I'm expecting is something to the effect of 'Authorization Failed'. The URL is one in our test environment and the XML being sent is correct, but I'm not getting a response and don't know what I'm doing wrong.
The service is REST, the headers have to pass an encoded authorization (this example is correct) and the content type is set as xml.
When I use the same parameters to test it in the Advanced Rest Client in Chrome it connects and gives me a response.
Also, if there's a better way to create the XML, I'm all for that - this is just an example I found and started with. Code is below
<?php
if (!isset($_POST['firstname'])) {
?>
<form name="ppost" method="post" action="<?=$_SERVER['PHP_SELF']?>">
<input type="text" name="firstname" />
<input type="submit" name="SUbmit" value="Submit" />
</form>
<?php
} // end if, form not posted
else {
extract($_POST);
$inputdata = '
<ReqGetWebUserInfo>
<OrgId>598</OrgId>
<OrgUnitId>598</OrgUnitId>
<MasterCustomerId>'.$firstname.'</MasterCustomerId>
<SubCustomerId>0</SubCustomerId>
</ReqGetWebUserInfo>';
echo '<pre>'.$inputdata.'</pre>';
$url = "https://gsusacustom.ebiz.uapps.net/GSUSARestWebService/PersonifyWcfSvc.svc/GetWebUserInfo";
$headers = array(
'Authorization: Basic dG1hc2d1bmRhbTpwYXNzd29yZDE=',
'Content-Type: application/xml;charset=utf-8',
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url ); // THE URL TO FETCH - CAN ALSO BE SET IN THE CURL_INIT
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADER, 0); // DON'T INLCUDE HEADER IN THE OUTPUT
curl_setopt($ch, CURLOPT_POST, 1); // TRUE FOR A REGULAR HTTP POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $inputdata); // THE DATA POST FROM THE FORM
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close ($ch);
print $response;
} // end else, form submitted and processed
?>
Thanks in advance.
My guess is you didn't handle the https connection as your has it. Try this option:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
If the error still persists then do the following to dig more.
Run the code with enabling all error reporting:
error_reporting(E_ALL);
Run the curl with enabling debugging option:
curl_setopt($ch, CURLOPT_VERBOSE, 1);

PHP string from HTTP post to another server

I will be using PHP further on this site, otherwise interested in learning more python to achieve these results.
I start with a search form that allows the user to enter in the 'findme' value which needs to be translated to a url. (for example purposes I will use findme = 12345678)
<form name="search" method="post" action="search.php" target="_blank" novalidate>
<input type="text" name="findme" />
<input type="submit" name="submit" value="submit" />
</form>
And then, I would like to retrieve a string within a HTTP post response page from a second server and store a url as a PHP string.
First I need to submit the form to another server, here is my attempt at search.php
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://another.server.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
$data = array(
'surname' => 'surname',
'name' => 'name',
'findme' => 'findme'
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
?>
The other server responds by serving a new page (ie. https://another.server.com/response.html), I want to then find the line containing the findme string, below is the format which the findme value of 12345678 would appear in a line of the response page. I want to save ABCDE as a string.
<tr class="special"><td>12345678......
Hopefully I can acheive with
<?php
file_put_contents("response.html", file_get_contents("https://another.server.com/response.html"));
$content = file_get_contents('response.html');
preg_match('~^(.*'.$findme.'.'</a>'.*)$~',$content,$line);
echo $line[1];
$findme_url = substr("abcdef", -37, 5);
echo $findme_url
?>
Updated with cURL and preg_match possible solutions, however the file put contents needs to be reading the response page from cURL
Yes, this is a perfect time to use curl.
$request = curl_init( 'https://another.server.com' );
curl_setopt( $request, CURLOPT_POST, true ); // use POST
$response = curl_exec( $request );
// catch errors
if( $response === false ) {
throw new Exception( curl_error($response) );
}
curl_close( $request );
// parse response...

How to make Curl post Using Php involving cookies

I am developing a script involving Php Curl to send sms using http://www.gysms.com/freesms.php
The page stores a cookie PHPSESSID and also a hidden field named token is passed during the posting.
I have written a script involving two curl requests. 1st curl request parse the page and obtain the token value .
Here is the code for that:
<?php
$phone = '9197xxxxxxx';
$msg = 'Hi this is curlpost';
$get_cookie_page = 'http://www.gysms.com/freesms.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $get_cookie_page);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sabin = curl_exec($ch);
$html=explode('<input type="hidden" name="trigger" value="',$sabin);
$html=explode('"/>',$html[1]);
//store the token value to $html[0]
?>
Curl post is done using the following code:
<?php
$fields = array(
'trigger'=>urlencode($html[0]), //token value
'number'=>urlencode($phone), //phone no
'message'=>urlencode($msg) //message
);
//posting curl request
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
$url = 'http://www.gysms.com/freesms.php';
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
//execute post
$result = curl_exec($ch);
echo $result;
curl_close($ch);
?>
The sms is not sending Using the above code.
If the sms is sent It should show sms is send to-No.
I don't Know where I went wrong. Please help, I am new to PHP.
Finally this attempt is only for my educational purpouse.
Here is some code I came up with that worked. Hope it helps. Some explanations and feedback about your code follow.
<?php
$number = '14155556666';
$message = 'This is my text in all its glory.';
$url = 'http://www.gysms.com/freesms.php';
$cookieFile = tempnam(null, 'SMS');
$userAgent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0';
if (strlen($message) > 100) {
die('Message length cannot exceed 100 characters.');
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent); // empty user agents probably not accepted
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // enable this - they check referer on POST
$html = curl_exec($ch);
// <input type="hidden" name="trigger" value="CXXrtmqVC7KbUnJ22UBodFy1kBj4ign5PsQ3qNR91nH2055307b4xP4"/>
if (!preg_match('/name=.trigger.\s+value=.([^\'"]+)/i', $html, $trigger)) {
die('Failed to locate hidden input value');
}
sleep(5); // without a slight delay, i often would not receive sms
$trigger = $trigger[1];
// build array of post values - all are important
$post = array('number' => $number,
'trigger' => $trigger,
'message' => $message,
'remLen' => 100 - strlen($message),
$trigger => 'Send Message');
// switch request to POST, use http_build_query to encode post data for us
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$html = curl_exec($ch);
if (strpos($html, '<b>Message sent to</b>') !== false) {
echo "Message sent!";
} else {
echo "<b>Message not sent :(</b><br /><br />";
echo $html;
}
I think you may have had trouble for several reasons:
A User-Agent should be specified in the request, they seem to reject if you leave it empty
I used http_build_query to build the POST string (preference)
You were missing 2 fields in the request, remLen, and the trigger value as the submit button
I often would not receive the messages if I didn't sleep a few seconds before sending the message after getting the trigger value.
In most of the cases where I didn't get the message, it still showed the "Message sent to phone #" on the screen even though it never came. Once I combined all the right things (sleep time, user agent, valid post fields) I would see the success message but also get the response.
I think the most critical thing left out from your code was that on the first request where you grab the trigger value, they also set a cookie (PHPSESSID) that you are required to capture. Without sending that on the POST request it was probably an automatic reject.
To get around this, make sure you capture cookies on the first request as well as subsequent requests. I chose to re-use the same curl handle for both requests. You don't have to do it that way, but you would have to use the same cookie file and cookie jar between requests.
Hope that helps.

Categories