Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    16
    Rep Power
    0

    Can HTML 5 + php/asp be used to fully hide resource files?


    So, one of the first scripts I used to frequently run in to in the 90s was the disable right click button script, although a poor solution I can't help but wonder if html 5 is capable of hiding sensitive information like certain files or logins and passwords.

    I haven't coded it yet, so I don't know of the pitfalls, but it would seem to me that in theory you should be able to:

    1. present content in the canvas tag
    2. load all the names of your resource files or login info with an xml page that you fetch with xmlHttp.open (only giving away the destination of the xml file and it's structure)
    3. use new auth tokens for every time you fetch new xml data
    4. use a php/htaccess script to redirect every http request that doesn't come from the target page (and has the right auth token).
    5. use whitelists to protect against javascript inclusion for login info.

    and for the super paranoid people maybe even load resources as strings containing encrypted binary data (does that get saved as a file in the temp folders?), disable the print screen button and turn the canvas black if the browser tab with the frame isn't active?

    Would that be an effective way of protecting your data?
  2. #2
  3. No Profile Picture
    Super Moderator
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jul 2003
    Posts
    4,009
    Rep Power
    2791
    Why are you loading data into a client's browser if it is not safe for public consumption?
    No, you cannot restrict any data from your users within documents that they are viewing. You can obfuscate as much as you like but a determined user can access all of the data.

    You could write a million line piece of Javascript to scramble and distort the data into an unreadable mess, however, there is nothing stopping a user from disabling Javascript in their browser settings.

    Why are you doing this?
    [PHP] | [Perl] | [Python] | [Java] != [JavaScript] | [XML] | [C] | [C++] | [LUA] | [MySQL] | [FirebirdSQL] | [PostgreSQL] | [HTML] | [XHTML] | [CSS]

    W3Fools - A W3Schools Intervention.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    16
    Rep Power
    0
    Originally Posted by Winters
    Why are you loading data into a client's browser if it is not safe for public consumption?
    No, you cannot restrict any data from your users within documents that they are viewing. You can obfuscate as much as you like but a determined user can access all of the data.

    You could write a million line piece of Javascript to scramble and distort the data into an unreadable mess, however, there is nothing stopping a user from disabling Javascript in their browser settings.

    Why are you doing this?
    but disabling the javascript will only show the "Your browser does not support the HTML5 canvas tag." text along with a script that only leads to a URL that they will be redirected away from will it not? If all the sensitive data is stored in variables then disabling javascript will only lead to those variables not containing the data in the first place, would it not?

    Sorry, that was rude of me. I should answer your questions first:

    It's much for the same reason as someone would do something silly in the guinness book of world records - just to prove that it can be done (if it can be done)

    I can see how things like this could have a real world benefit though, like for example say you create a website that hosts and charges for other peoples photos and images like shutterstock - maybe something like this could be an alternative to making big watermarks over the pictures and thereby provide a competitive edge?

    Maybe news sites who have paid top dollar for a papparazzis photo could maintain that IP on their site and thereby drive more traffic?

    Or let's say you create a facebook game app and want to secure other peoples logins, your code from other devs plagiarising it, or hackers hacking the game or expose content ahead of time hidden on for example css sprites.

    What if you stored encrypted binary data in php session objects and loaded that into the code? With an advanced enough encryption it would be as safe as any other encrypted file, would it not?

    Surely there can be useful applications for technology such as this?

    Don't get me wrong, I am all for open source - but at the same time we must acknowledge that the internet contains personal information and we need to have technologies that keeps that data safe.

    Also, thank you so much for your reply - I really do apreciate having the discussion.
  6. #4
  7. No Profile Picture
    Super Moderator
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jul 2003
    Posts
    4,009
    Rep Power
    2791
    I understand that you may have data that you want to keep protected, however the nature of the internet, specifically web documents, is that they are downloaded to the user's computer before being viewed.

    If you encrypt something it becomes unusable until it is decrypted, which will we have to be done before or while it is on the user's computer, to make it usable. So you can use all manner of techniques, both client- and server-side, to secure the data but at the end of the day, all of that needs to be undone in order for it to be viewed by the user.

    The only method of securing downloaded data is to have an application, which is running the on the user's computer, to handle secure files. Such as Java or Flash. Even then a savvy enough user can intercept the data.

    What type of content are you attempting to secure?

    Comments on this post

    • Jacques1 agrees
    [PHP] | [Perl] | [Python] | [Java] != [JavaScript] | [XML] | [C] | [C++] | [LUA] | [MySQL] | [FirebirdSQL] | [PostgreSQL] | [HTML] | [XHTML] | [CSS]

    W3Fools - A W3Schools Intervention.
  8. #5
  9. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Hi Grandum,

    I think there are several fundamental misunderstandings.

    First of all, it's always a bad idea to try and come up with your own security techniques. I mean, of course you can do that for fun, but don't even think about using it on a real website. Developing security protocols is an expert topic, and it requires extensive peer-reviewing, professional testing and time. Any home-made stuff you may come up as a layman (which we all are) is guaranteed to be broken. Many, many programmers have tried it, and they've all failed. Most homegrown protocols don't even make sense, some are almost correct, but none of them ever worked.

    Secondly, you cannot utilize the client to protect data from the client. That's a contridiction in terms. You may ask the client to not look at the data by obfuscating it -- just like some puzzles have the solution printed upside down. But it's impossible to somehow use the browser to restrict access. All your canvas elements, encryption and whatnot are eventually just a bloated version of your 90s click blockers. Wanna know how I "cracked" those as a kid? I took a screenshot.

    What you also need to understand is that websites are not bound to any kind of browser. Sure, that's how you use the www most of the time: You open your Firefox (or whatever it is you're using), you enter the URL into the address bar, and then you see some fancy graphics on the screen. But a browser is just a convenience tool. What actually happens is that your operating system opens or resumes a TCP connection, sends an HTTP request and gets an HTTP response back (which will include the HTML document, a picture, a piece of JavaScript code or whatever). You can do that yourself in the console of your operating system without any browser involved.

    So: No, you cannot use HTML, JavaScript, Flash or any other client technique to protect data from the client. This has do be done on the server, and it's actually pretty simple: If you don't want somebody to see certain data, don't send the data. That's the only way you can protect it. Anything else is just yet another fancy click blocker.

    In fact, I think you should forget about the whole notion of "hiding" something. A user either gets the data or doesn't get the data. There's no in-between.
    Last edited by Jacques1; June 14th, 2013 at 07:12 AM.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    16
    Rep Power
    0
    Originally Posted by Winters
    I understand that you may have data that you want to keep protected, however the nature of the internet, specifically web documents, is that they are downloaded to the user's computer before being viewed.

    If you encrypt something it becomes unusable until it is decrypted, which will we have to be done before or while it is on the user's computer, to make it usable. So you can use all manner of techniques, both client- and server-side, to secure the data but at the end of the day, all of that needs to be undone in order for it to be viewed by the user.

    The only method of securing downloaded data is to have an application, which is running the on the user's computer, to handle secure files. Such as Java or Flash. Even then a savvy enough user can intercept the data.

    What type of content are you attempting to secure?
    Sorry about the late reply, I was modifying some old code to test some of this it - Thanks again for your reply, I appreciate that!

    I think it makes a lot of sense, and I did rethink the whole protecting images bit - I think it might be able to do with sprites, but I must admit that I left screen capture software out of the equation - as long as tech like that is around I guess it really will be impossible to protect images.

    At first I thought you referred to the temporary internet files, and that is that which ruins everything, so I ran my little experiment and loaded the names of the images from an xml file with:

    Code:
    XMLHttpRequest()
    and then loaded some data - 1 array contained the filename, table001.png and the other width, height, x & y coords, an alt description, etc, etc a an array, and then used those arrays to create images like this:

    Code:
    imgArray[0] = new Image();
    imgArray[0].src = pngnames[0];
    pngnames being dynamicly created.

    To test it I displayed the image in a canvas along with data from the other array that holds width, height x & y coords etc like this:

    Code:
    context.drawImage(imgArray[0], listedalbumArray[activealbum][lactpage][5], listedalbumArray[activealbum][lactpage][6], listedalbumArray[activealbum][lactpage][3], listedalbumArray[activealbum][lactpage][4], listedalbumArray[activealbum][lactpage][0], listedalbumArray[activealbum][lactpage][1], listedalbumArray[activealbum][lactpage][3], listedalbumArray[activealbum][lactpage][4]);
    And surely enough that does produce an image from the larger png file that I loaded from the xml file.

    However, here's the kicker - I checked my temporary internet files to see if the image I used, table001.png was stored there, but it wasn't - nor was the xml file that I fetched the data from.

    Is this something that different browsers store differently or was I on the wrong track with how you meant that documents are saved on the computer?

    If it truly is the case that it isn't stored there, could you then maybe elaborate on where it is stored and how people would get access to it?
  12. #7
  13. No Profile Picture
    Super Moderator
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jul 2003
    Posts
    4,009
    Rep Power
    2791
    Jacques has provided a far more in-depth and eloquent response than I. The simple answer is: If you want to allow the user to view the data, then it cannot be secured.
    [PHP] | [Perl] | [Python] | [Java] != [JavaScript] | [XML] | [C] | [C++] | [LUA] | [MySQL] | [FirebirdSQL] | [PostgreSQL] | [HTML] | [XHTML] | [CSS]

    W3Fools - A W3Schools Intervention.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    16
    Rep Power
    0
    Originally Posted by Jacques1
    Hi Grandum,

    I think there are several fundamental misunderstandings.

    First of all, it's always a bad idea to try and come up with your own security techniques. I mean, of course you can do that for fun, but don't even think about using it on a real website. Developing security protocols is an expert topic, and it requires extensive peer-reviewing, professional testing and time. Any home-made stuff you may come up as a layman (which we all are) is guaranteed to be broken. Many, many programmers have tried it, and they've all failed. Most homegrown protocols don't even make sense, some are almost correct, but none of them ever worked.

    Secondly, you cannot utilize the client to protect data from the client. That's a contridiction in terms. You may ask the client to not look at the data by obfuscating it -- just like some puzzles have the solution printed upside down. But it's impossible to somehow use the browser to restrict access. All your canvas elements, encryption and whatnot are eventually just a bloated version of your 90s click blockers. Wanna know how I "cracked" those as a kid? I took a screenshot.

    What you also need to understand is that websites are not bound to any kind of browser. Sure, that's how you use the www most of the time: You open your Firefox (or whatever it is you're using), you enter the URL into the address bar, and then you see some fancy graphics on the screen. But a browser is just a convenience tool. What actually happens is that your operating system opens or resumes a TCP connection, sends an HTTP request and gets an HTTP response back (which will include the HTML document, a picture, a piece of JavaScript code or whatever). You can do that yourself in the console of your operating system without any browser involved.

    So: No, you cannot use HTML, JavaScript, Flash or any other client technique to protect data from the client. This has do be done on the server, and it's actually pretty simple: If you don't want somebody to see certain data, don't send the data. That's the only way you can protect it. Anything else is just yet another fancy click blocker.

    In fact, I think you should forget about the whole notion of "hiding" something. A user either gets the data or doesn't get the data. There's no in-between.
    Great post.

    I know it's not your fault and that it really is wrong to assume, but I am a bit more experienced a user than you have given me credit for, so by all means feel free to get a bit more technical.

    Having said that yes, I agree the images bit is something that is doomed to fail - at least for the parts of the image that we want to show to a user.

    I do think however that there is a way that we can:

    1 securely identify a user in order to serve up the right content
    2 hide the parts of an image that we don't want to show (see my previous post)

    so let's go back to basics:

    1. present content in the canvas tag
    2. load all the names of your resource files or login info with an xml page that you fetch with xmlHttp.open (only giving away the destination of the xml file and it's structure)
    3. use a php/htaccess script to redirect every http request that doesn't come from the target page (and has the right auth token).

    Following these 3 steps, and given that my test produced accurate data in not showing up in the temporary internet files...

    Would you be able to see the full image and not just what has been defined in context.drawImage?

    Using the same method to extract a url

    could that url be used in sending data securely over xml along with ?user=xxx&password=yyy

    in order to serve up an xml file which only contains data relevant to that user (or write to a database) - data that is then loaded into arrays with xmlHttp.open?
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    16
    Rep Power
    0
    Originally Posted by Winters
    Jacques has provided a far more in-depth and eloquent response than I. The simple answer is: If you want to allow the user to view the data, then it cannot be secured.
    I'm with you 100% on that.

    The questions now are "can we hide external sensitive data in variables and use that data to serve up things we want the user to view?" and "can we only show parts of an image file like say the upper right corner without providing access to the entire image?"
  18. #10
  19. No Profile Picture
    Super Moderator
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jul 2003
    Posts
    4,009
    Rep Power
    2791
    Can you give an example of "can we hide external sensitive data in variables and use that data to serve up things we want the user to view?"?

    A partial image is an easy to handle on the server-side.
    [PHP] | [Perl] | [Python] | [Java] != [JavaScript] | [XML] | [C] | [C++] | [LUA] | [MySQL] | [FirebirdSQL] | [PostgreSQL] | [HTML] | [XHTML] | [CSS]

    W3Fools - A W3Schools Intervention.
  20. #11
  21. No Profile Picture
    Lost in code
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 2004
    Posts
    8,316
    Rep Power
    7170
    "can we only show parts of an image file like say the upper right corner without providing access to the entire image?"
    Only if you crop the image on the server side and don't send the full image to the client. It doesn't matter how you send the image or how you mask its URL, if you send the whole file, the client can view the whole file. At the lowest level, all the user needs to do is intercept the HTTP request, which they can easily do using a program like Fiddler, and they will have access to every single bit you transmit to them.
    PHP FAQ

    Originally Posted by Spad
    Ah USB, the only rectangular connector where you have to make 3 attempts before you get it the right way around
  22. #12
  23. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    16
    Rep Power
    0
    Originally Posted by Winters
    Can you give an example of "can we hide external sensitive data in variables and use that data to serve up things we want the user to view?"?

    A partial image is an easy to handle on the server-side.
    sure

    let's say you have a very big image containing 300 smaller large thumbnails for your online family album. half of all those images are of your son and daughter happening to be nude whilst doing funny things.

    Being a protective parent you don't want to make any nude pictures available to anyone outside of the family, so it's important that nobody sees the full picture with all the thumbnails.

    Ie, we don't want to make the full url available, and we don't want it to end up on someones computer, but we do want to share the rest of the images with coworkers, etc.

    We want to serve this up on the familys website where different logins are given to different people.

    In order for this to work we don't want to use PHP's gd library to split it up to individual thumbnails as that would create a new http request for every image and our webserver - every image taking say 0.5 sec because the webserver only allows for 2 simultanious http connections just for the sake of argument.

    that would then be 2.5 minutes worth of waiting for the images to load.

    Instead we want to go the route of creating a loading screen like you would see on a flash application that loads up all the resources in 10-15 sec and then provides for a loading free browsing experience.

    So we create a whopper of an image out of all the thumbnails, hide it away in some far off subfolder and then (since we don't want people to see the full image) the image data is stored in the xml file (loads up different content based on login) and is extracted with:

    Code:
    function loaddata(){
    	var imenu = 0;
    	if (window.XMLHttpRequest){
    	xmlHttp=new XMLHttpRequest();
    	}
    	else{
    	xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    	}
    
    	xmlHttp.open("GET","botparts.xml",false);
    	xmlHttp.send(null);
    	var xmlDoc = xmlHttp.responseXML;
    	x=xmlDoc.getElementsByTagName("botass");
    
    	for (i=0; i<x.length; i++) {
    		Arrtype = (x[i].getElementsByTagName("nType")[0].childNodes[0].nodeValue);
    		Arrsize = window[Arrtype].length;
    
    		window[Arrtype][Arrsize] = new Array();
    		window[Arrtype][Arrsize][0] = parseInt((x[i].getElementsByTagName("nStartWidth")[0].childNodes[0].nodeValue));
    		window[Arrtype][Arrsize][1] = parseInt((x[i].getElementsByTagName("nStartHeight")[0].childNodes[0].nodeValue));
    		window[Arrtype][Arrsize][2] = (x[i].getElementsByTagName("nCaption")[0].childNodes[0].nodeValue);
    		window[Arrtype][Arrsize][3] = parseInt((x[i].getElementsByTagName("nWidth")[0].childNodes[0].nodeValue));
    		window[Arrtype][Arrsize][4] = parseInt((x[i].getElementsByTagName("nHeight")[0].childNodes[0].nodeValue));
    		window[Arrtype][Arrsize][5] = parseInt((x[i].getElementsByTagName("nClipWidth")[0].childNodes[0].nodeValue));
    		window[Arrtype][Arrsize][6] = parseInt((x[i].getElementsByTagName("nClipHeight")[0].childNodes[0].nodeValue));
    		window[Arrtype][Arrsize][7] = (x[i].getElementsByTagName("nRSZ")[0].childNodes[0].nodeValue);
    		window[Arrtype][Arrsize][8] = (x[i].getElementsByTagName("nRSC")[0].childNodes[0].nodeValue);
    	}
    }
    with an xml file whos contents look something like this:

    Code:
    <root>
    <botass>
    <nType>menuArray</nType>
    <nStartWidth>505</nStartWidth>
    <nStartHeight>416</nStartHeight>
    <nCaption>Cards</nCaption>
    <nWidth>58</nWidth>
    <nHeight>53</nHeight>
    <nClipWidth>123</nClipWidth>
    <nClipHeight>21</nClipHeight>
    <nRSZ>0.9</nRSZ>
    <nRSC>1</nRSC>
    </botass>
    </root>
    let's say that one of the posts leads to an array that says

    Code:
    imagepath[2] = "/bigpic/familyfun.png"
    ie the file destination that we want to keep from everyone.

    We then set

    Code:
    miscalbumpages = new Image();
    miscalbumpages.src = imagepath[2];
    and load up each image like this:

    context.drawImage(miscalbumpages, listedalbumArray[activealbum][lactpage][5], listedalbumArray[activealbum][lactpage][6], listedalbumArray[activealbum][lactpage][3], listedalbumArray[activealbum][lactpage][4], listedalbumArray[activealbum][lactpage][0], listedalbumArray[activealbum][lactpage][1], listedalbumArray[activealbum][lactpage][3], listedalbumArray[activealbum][lactpage][4]);

    ...which probably looks like a mess to you, but let's pretend the numbers say

    context.drawImage(miscalbumpages, 90,130,50,60,10,10,50,60);

    not caching any image in the proccess, but being able to retain full control of what parts of the image that is being shown, loading the page much faster and making everyone happy in the process.

    Would that be a safe way of handling that image without running the risk of unauthorized people seeing your son and daughter naked?
  24. #13
  25. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by Grandum
    Would that be a safe way of handling that image without running the risk of unauthorized people seeing your son and daughter naked?
    No.

    When you send the whole picture, the client has the whole picture. There's nothing you could do to change that. As soon as the picture arrives at the client, it's too late to protect it.

    Whether the browser stores this picture in the temp folder doesn't matter. The fact is, the user has received it, and this allows them to watch it. Most browsers have developer tools, which let you go through all received data. But you might as well record the network traffic (as already mentioned by E-Oreo).

    Once your server has sent the data, the user has full access to it. Period. You cannot restrict the access afterwards, hide certain parts or anything like that. If the response is out, it's out -- just like a letter. You cannot send somebody a letter and then somehow have them only read certain parts of it.

    Understanding this is very, very important, because it's pretty much the foundation of all web security.

    You either have to store different versions of the "big picture", each one containing only the things that are meant to be seen by a particular user group. Or you need to create the picture dynamically with a server-side graphics library. But you cannot have one picture for everybody and "filter" it with JavaScript.

    And of course you mustn't allow direct access to any private picture, because this would make nonsense of all the protection. You have to deliver them with PHP after successful authentication.
    Last edited by Jacques1; June 14th, 2013 at 10:57 AM.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  26. #14
  27. No Profile Picture
    Lost in code
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 2004
    Posts
    8,316
    Rep Power
    7170
    half of all those images are of your son and daughter happening to be nude whilst doing funny things.

    Being a protective parent you don't want to make any nude pictures available to anyone outside of the family, so it's important that nobody sees the full picture with all the thumbnails.
    lol - I suppose that's one way to illustrate the approach. There are two pretty significantly different ways of interpreting that example though.
    PHP FAQ

    Originally Posted by Spad
    Ah USB, the only rectangular connector where you have to make 3 attempts before you get it the right way around
  28. #15
  29. A Not To Shabby Code Smurf
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2008
    Posts
    1,183
    Rep Power
    184
    Here is one security flaw I see; just right off the bat:
    Code:
    xmlHttp.open("GET","botparts.xml",false);
    Ok, botparts.xml is not dynamic based on say (an individuals login; ie => botparts.xml?cousin=bob&key=293092URIJKDF). So, that being said: I view your source code; download your XML file and your page with the JS code in it; then I manipulate it to show full photo and upload files to internet for all to see. Which, by the way... would be super easy; because all I have to do is attach your base domain to this:
    Code:
    imagepath[2] = "/bigpic/familyfun.png"
    Like so:
    Code:
    imagepath[2] = "http://www.myfamilymemorys_or_whatever.com/bigpic/familyfun.png"
    And... I just exploited your content and if I want to be slick like rick; I just download all of your internal files; serve them up on a fraudulent website and pone them off as mine or... even worse... yours; for all the world to see. And trust me... ppl do it all the time. Websites like this are used predominantly for Phishing, but can be extremely malicious and try to destroy your online reputation (if you have one established); then in turn hurting your businesses name. They may even infect this new created fraudulent website with viruses and then they will keep on causing harm to others; long past your initial impact. No one will want to use your site again; for photos services or anything else for that matter, because of your now infamous security whole.

    Slippery Slope: Your customers leave your site or who knows, they may even legally seek damages for your lack of security of intellectual property. And... who know's; a judge might actually award them a settlement. Then you loose your business or may even do a little jail time. Haha, now; all of this is loosely formatted on a extremely unlikely end result, but you get the idea; behind what everyone is telling you (above) and that is: basically when you send non-protected data, in any type of HTTP stream; that can be interpreted by a browser, there are ways around your methods of client side interception/security barriers.

    Now, my advice: do a subscription based download service of the images; based on server side login interactions with a database. Yes, someone can try to back door hack into your database or try to make it crash with a bruit force attack; so they can get the login info and/or the image data, but that is a far less likely scenario; then me, viewing your source code and having complete access to all your content.
    Last edited by web_loone08; June 15th, 2013 at 12:48 AM.
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo