The website for a client of mine continues to be "hacked" (I didn't do the website).The hacked pages contain a js script that loads an image and audio from youtube (Lol). Every page was modified and every page has a "news banner" .I'm pretty sure the problem is this part
<?php
$ul = new NewsList;
$ul->Load(3);
if($ul->Current() == null){ ?>
<?php }
else{
for(; $ul->Current() != null; $ul->Next()){
$new = $ul->Current();
the complete implementation of this NewsList : http://pastebin.com/WuWjcJ4p
I'm not a php programmer so I don't get where the problem is....I'm not asking that someone going to explain every line, maybe only an advice , thank you
Sounds like an SQL injection.
I believe the loadById() method is injectable (depending on how you call it).
Here is a way to strengthen it :
function LoadById($id){
$this->news = array();
$this->current = 0;
$this->total = 0;
$ndb = new NewsDB('news');
$result = $ndb->_query("SELECT * FROM ".$ndb->table." WHERE id = " . intval($id));
$new = mysql_fetch_assoc($result);
$n = new News($new['id'], $new['titolo'], $new['data'], $new['contenuto'], $new['img']);
array_push($this->news, $n);
unset($n);
$this->total = 1;
}
Someone might have stolen the passwords from administration using this security flaw and edited the articles from the back-office.
So I suggest you change this code, then change the passwords, delete all php sessions, and finally edit your articles to remove this "news banner".
Note that it might as well be a stored XSS.
Do you have a system which allows to comment the news?
Related
Sorry for my bad grammar, English is not my main language :)
I'm developing a fully ajax frontend based wordpress theme based on user comments and I wanted to add a rich text editor (Froala). And as we all know that; that brings a lot of security problems.
I don't want to use HTML Purifier library, it's too heavy.
I guess I found a good way to sanitize all of my data sent from the users but I'm stuck.
My sanitize opinion->
On submit form -> get all HTML data and convert it to bbcode like style with javascript.
var htmlToBBCode = function(html) {
...
html = html.replace(/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/gi, "[url url=$2 kelime=$4]");
html = html.replace(/<textarea(.*?)>(.*?)<\/textarea>/gmi, "\[code]$2\[\/code]");
html = html.replace(/<b>/gi, "[b]");
html = html.replace(/<\/b>/gi, "[/b]");
html = html.replace(/<img(.*?)width="(.*?)"(.*?)height="(.*?)"(.*?)src="(.*?)"(.*?)>/gi, "[img weight=$2 height=$4 src=$6]");
...
}
let editor = new FroalaEditor('#entry_html_input', {}, function () {
});
var bbcode = htmlToBBCode(editor.html.get());
On the server side -> sanitize_text_field() all $_POST["comment"] (So I can protect against ppl who sent a dirty xss code via console - ajax)
$clean_comment = sanitize_textarea_field(nl2br(wp_unslash($_POST["comment"])));
On the server side -> Use add_shortcode() function of wordpress.
function img_shortcode($atts, $content)
{
$weight = intval($atts["weight"]);
$height = intval($atts["height"]);
$src = esc_url($atts["src"])
$return = '<center><img src="' . $src . '" width="'.$weight.'" height="'.$height.'" rel="nofollow"/></center>';
return $return;
}
add_shortcode('img', 'img_shortcode');
function b_shortcode($atts, $content)
{
$bold_text = sanitize_text_field($content);
return '<b>'.$bold_text.'</b>';
}
add_shortcode('b', 'b_shortcode');
And it works perfect! Correct if I'm wrong, this is a fully secure way against XSS. I know all paramaters passed to shortcode and I know how to deal with them. If they bypasses bbcode converter there is a sanitize_text_field(); when $_POST arrived.
But this is where I'm stuck...
When editor sends a HTML like this:
<p>
<strong>
sdfsfsdfsfd
<img src="https://i.ibb.co/9bxPvhM/86a9d5b8bc498dc5eb3689f0b983a5a7a3f1c1bb.jpg" style="width: 300px;" class="fr-fic fr-dib">
qwrrwqqrwqwrrqw
</strong>
</p>
Yeah bbconverter trying to this:
[b]
sdfsfsdfsfd
[img]
https:/i.ibb.co/9bxPvhM/86a9d5b8bc498dc5eb3689f0b983a5a7a3f1c1bb.jpg
[/img]
qwrrwqqrwqwrrqw
[/b]
And sanitize_text_field(); inside b_shortcode function compelety killing-removing the image...
This is only a simple example. As you can imagine this is happening with "i","sub","sup" tags either.
I tried solutions like this:
html = html.replace(/<strong>(.*?)<img(.*?)src="(.*?)"(.*?)style="(.*?)"(.*?)>(.*?)<\/strong>/gi, "[bold_image_mixed text_before=$1 text_after=$7 img_url=$3 img_width=$5]");
And yeah this is works. But there are so many tags and combinations that can broke my image or my youtube video (iframe) with those tags.
How can I prevent that?
Whats your thought about my way to sanitize html input?
I hope somebody can help me...
God! I just figured it out!
function b_shortcode($atts, $content)
{
$bold_text = sanitize_text_field($content);
return '<b>'.$bold_text.'</b>';
}
add_shortcode('b', 'b_shortcode');
If I change this, to this ->
function b_shortcode($atts, $content)
{
$bold_text = sanitize_text_field($content);
return '<b>'.do_shortcode($bold_text).'</b>';
}
add_shortcode('b', 'b_shortcode');
So if I adds do_shortcode() to $bold_text; it applies other shortcode functions to this string. If there is no other shortcode values matches; it returns plain text!
But my other question is still up...
Is this a secure way to stop XSS?
I want to put a clicks counter on banners on my page so advertisers get an idea of how many visitors arrive via my website.
I've seen that could be done by directing the link to an intermediate page that access MySQL (to save the data in a record BD) using PHP, and then redirected to the advertiser's website, but I wonder if there otherwise somewhat more "elegant" to do so.
Could anyone tell me if it is possible?
I've found an similar example, but this one donwload a file and count the visit (I only want to go to another web)
EXAMPLE HTML
<span style="font-family: Verdana, Arial, Helvetica, sans-serif;"><a href='files/my_file.zip' id='25' onClick='dc(this.id)' target='_blank'>Download this file</a> </span>
EXAMPLE Javascript
function dc(id){$.post("process.php",{file_id:id})}
EXAMPLE Process.php
$file_id = $_POST['file_id'];
mysql_query("UPDATE file SET downloads = downloads + 1 WHERE id = " .$file_id);
I tried to adapt this example to my code, like this:
HTML
echo '<br><a onClick="sumar(this.id);" href="http://'.$result['WEB'].'" id="'.$result['ID_PAG'].'" target="_blank">'.$result['WEB'].'</a><br />';
Javascript (In head section)
function sumar(id){($.post("suma.php",{pag:id})}
Suma.php
$pag=$_POST['pag'];
$mysqli->query("UPDATE lapag SET visitas=visitas+1 WHERE id_pag=".$pag);
Thank You!
Are you sure you have the apostrophs right? I c/p html part into eclipse and it did not particularly like it.
echo "<br><a onClick='sumar(this.id)'";
echo "href='http://".$result['WEB'] . "'";
echo "id=". $result['ID_PAG'] . 'target="_blank">';
echo $result['WEB']. "</a><br />";
I have broken it up into several echoes in order to make it clearer and easier to handle.
HTML
<?php echo $result['WEB']; ?>
Sumar.php
$pag=$_GET['ID_PAG'];
$mysqli->query("UPDATE lapag SET visitas=visitas+1 WHERE id_pag=".$pag);
header("Location: http://".$_GET['WEB']); // redirect
exit();
Think best practice should look like this:
<a href="http://random.org" onclick='called(event, this, "clicked")'>Visit site</a>
function called(event, link, id){
event.preventDefault();
event.stopImmediatePropagation();
var theUrl = "counter.php";
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange=function(){
if (this.readyState != 4) //4 means call is finished - we just want to switch side after the counter-call finished
return;
window.location.href = link.href.value;
};
xmlHttp.open("GET", theUrl, true);
xmlHttp.send("id="+id);
return false;
}
Example: http://jsbin.com/porotobuna/1/edit?html,js,output
In the counter.php just get the get variable "id" (which represents the clicked link) and handle the counter (I recommend some kind of database)
I'd like to scrape the actual the dynamically created URLs in this web page's menu using PHP:
http://groceries.iceland.co.uk/
I have previously used something like this:
<?php
$baseurls = array("http://groceries.iceland.co.uk/");
foreach ($baseurls as $source)
{
$html = file_get_contents($source);
$start = strpos($html,'<nav id="mainNavigation"');
$end = strpos($html,'</nav>',$start);
$mainarea = substr($html,$start,$end-$start);
$dom = new DOMDocument();
#$dom->loadHTML($mainarea);
// grab all the urls on the page
$xpath = new DOMXPath($dom);
$hrefs = $xpath->evaluate("/html/body//a");
for ($i = 0; $i < $hrefs->length; $i++)
{
$href = $hrefs->item($i);
$url = $href->getAttribute('href');
}
}
?>
but it's not doing the job for this particular page. For example, my code returns a url such as:
groceries.iceland.co.uk//frozen-chips-and-potato-products
but I want it to give me:
groceries.iceland.co.uk//frozen/chips-and-potato-products/c/FRZCAP?q=:relevance&view=list
The browser adds "/c/FRZCAP?q=:relevance&view=list" to the end and this is what I want.
Hope you can help
Thanks
Edit: Just to confirm, I had at look at the website you're trying to scrape with JavaScript turned off and it appears that the Mainnav urls are generated using JavaScript, so you will be unable to scrape the page without using a headless browser.
Per #Sam and #halfer's comments, if you need to scrape a site that has dynamic URLs generated by JavaScript then you will need to use a scraper that supports JavaScript.
If you want to do the bulk of your development in PHP, then I recommend not trying to use a headless browser via PHP and instead relying on a service that can scrape a JavaScript rendered page and return the contents for you.
The best one that I've found, and one that we use in our projects, is https://phantomjscloud.com/
This question already has answers here:
How to show google.com in an iframe?
(9 answers)
Closed 9 years ago.
I want to create a universal website crawler using PHP.
By using my web application, a user will input any URL, will provide input on what he needs to get from given site and will click on Start button.
Then my web application will begin to get data from source website.
I am loading the page in iframe and using jQuery I get class and tags name of specific area from user.
But when I load external website like ebay or amazon etc it does not work, as these site are restricted. Is there any way to resolve this issue, so I can load any site in iFrame? Or is there any alternative to what I want to achieve?
I am actually inspired by mozenda, a software developed in .NET, http://www.mozenda.com/video01-overview/.
They load a site in a browser control and it's almost the same thing.
You can't crawl a site on the client-side if the target website is returning the "X-Frame-Options: SAMEORIGIN" response header (see #mc10's duplicate link in the question comments). You must crawl the target site using server-side functionality.
The following solution might be suitable if wget has all of the options that you need. wget -r will recursively crawl a site and download the documents. It has many useful options, like translating absolute embedded urls to relative, local ones.
Note: wget must be installed in your system for this to work. I don't know which operating system you're running this on, but on Ubuntu, it's sudo apt-get install wget to install wget.
See: wget --help for additional options.
<?php
$website_url = $_GET['user_input_url'];
//doesn't work for ipv6 addresses
//http://php.net/manual/en/function.filter-var.php
if( filter_var($website_url, FILTER_VALIDATE_URL) !== false ){
$command = "wget -r " + escapeshellarg( $website_url );
system( $command );
//iterate through downloaded files and folders
}else{
//handle invalid url
}
You can sub in what element you're looking for in the second foreach loop within the following script. As is the script will gather up the first 100 links on cnn's homepage and put them in a text file named "cnnLinks.txt" in the same folder in which this file is located.
Just change the $pre, $base, and $post variables to whatever url you want to crawl! I separated them like that to change through common websites faster.
<?php
set_time_limit(0);
$pre = "http://www.";
$base = "cnn";
$post = ".com";
$domain = $pre.$base.$post;
$content = "google-analytics.com/ga.js";
$content_tag = "script";
$output_file = "cnnLinks.txt";
$max_urls_to_check = 100;
$rounds = 0;
$domain_stack = array();
$max_size_domain_stack = 1000;
$checked_domains = array();
while ($domain != "" && $rounds < $max_urls_to_check) {
$doc = new DOMDocument();
#$doc->loadHTMLFile($domain);
$found = false;
foreach($doc->getElementsByTagName($content_tag) as $tag) {
if (strpos($tag->nodeValue, $content)) {
$found = true;
break;
}
}
$checked_domains[$domain] = $found;
foreach($doc->getElementsByTagName('a') as $link) {
$href = $link->getAttribute('href');
if (strpos($href, 'http://') !== false && strpos($href, $domain) === false) {
$href_array = explode("/", $href);
if (count($domain_stack) < $max_size_domain_stack &&
$checked_domains["http://".$href_array[2]] === null) {
array_push($domain_stack, "http://".$href_array[2]);
}
};
}
$domain_stack = array_unique($domain_stack);
$domain = $domain_stack[0];
unset($domain_stack[0]);
$domain_stack = array_values($domain_stack);
$rounds++;
}
$found_domains = "";
foreach ($checked_domains as $key => $value) {
if ($value) {
$found_domains .= $key."\n";
}
}
file_put_contents($output_file, $found_domains);
?>
Take a look at using the file_get_contents function in PHP.
You may have better success in retrieving the HTML for a given site like this:
$html = file_get_contents('http://www.ebay.com');
Hi i have a quick question, say that you would like to connect to a website and search it for what links it contains, how do you do this with javascript?
I would like to do something like this
Var everythingAdiffrentPageContains = //Go to some link ex www.msn.se and store it in this variable
var pageLinks = []; var anchors = everythingAdiffrentPageContains.getElementsByTagName('a');
var numAnchors = anchors.length;
for(var i = 0; i < numAnchors; i++) {
pageLinks.push(anchors[i].href);
}
We can assume here that we have acces rights to the site so this is not of a concern.
In other words I would like to go to some site and store all that sites Hyperlinks in an array, how would you do this in javascript?
Thanks
EDIT since pointed out Im not trying to connect to another domain. Im trying to connect to another apache webserver inside my lan that hosts a website that I would like to scan for links.
Unfornuatley I do not have PHP on my webserver :/ But a simple javascript would do it
for example go to X:/folder/example.html
Read it, and store the links
Unfortunately - You can't do this. "We can assume here that we have acces rights to the site"...that's a false assumption from a JavaScript point of view, if the page is on another domain. You simply can't access content on another domain (not HTML content anyway) via JavaScript. It's prevented by the same-origin policy, in place for several security reasons.
I suggest you to use a JS framework that helps you to retrieve elements and do stuff with DOM easily.
For example using mootools you could achieve this writing some code like this:
var req = new Request.HTML({
url:'./retrieve.php?url=YOURURL', //create a server script to "retrieve" the html of another domain page
onSuccess: function(tree,DOMelements) {
var links = [];
DOMelements.getElements('a').each(function(element){
links.push(element.get('href'));
});
}
});
req.send();
The retrieve.php page should be written for example in this way:
<?php
$url = $_GET['url'];
header('Content-type: application/xml');
echo file_get_contents($url);
?>