ByetHost server passing html values "Checking your browser" with JSON String

21,849

Solution 1

Solved!

I had the same issue using Byethost to retrieve JSON data from my PHP server. We just need to add a cookie to the HTTP request to pass the testcookie-nginx-module

As Richard's answer says:

The main problem is that Byet Host implement a simple security antibots module >named testcookie-nginx-module

https://kyprizel.github.io/testcookie-nginx-module/

On the link he provided we can see that the testcookie-nginx-module makes a 2-steps validation:

  1. The first time that a HTTP request is done, the module returns a javascript instead of the JSON we are expecting. This script is executed on the client (tipically a web browser) and generates a validation cookie containing an AES key.

Here's the script I've received form my server:

<html>
<body>
    <script type="text/javascript" src="/aes.js" ></script>
    <script>
        function toNumbers(d){
        var e=[];
            d.replace(/(..)/g,function(d){
                e.push(parseInt(d,16))});
            return e
        }
        function toHex(){
            for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)
                e+=(16>d[f]?"0":"")+d[f].toString(16);
                return e.toLowerCase()
        }
        var a=toNumbers("f655ba9d09a112ffff8c63579db590b4"),
            b=toNumbers("98344c2eee86c3ffff90592585b49f80"),
            c=toNumbers("1286963467aa92ffff8323bdca0d7be9");
        document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; 
        location.href="http://myserver.byethost8.com/myPhpPage.php?i=1";
    </script>
    <noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
</body>

  1. The script adds the validation cookie to the document and redirects it to the url we actually want to access. The testcookie-nginx-module validates the cookie AES key and and let the request hit the url that will response with the JSON data we want to access.

On the following HTTP requests the client will have stored the cookie and will add it to the request skipping the step 1.

Solution for our Android App

We are going to skip the cookie generation by getting it from a web browser and add it directly to our Android HTTP request (Unless of course you want to get involved in generating it).

Before you get the cookie from the web browser make sure you accessed the url at least once with the browser to generate it.

  • Getting the cookie key from the web browser. I used Google Chrome for it:

    1. From the Chrome menu in the top right corner of the browser, select Settings.
    2. At the bottom of the page, click Show advanced settings....
    3. Under Privacy, select Content settings....
    4. select All cookies and site data....
    5. Search for you website name. By searching "byethost" you'll find it.
    6. Open the cookie named __test and copy the values of content, path and expires
  • Setting the cookie on our Android app. On your code should be something like:

    try 
    {
     if(post == "POST")
     {
         HttpClient httpClient = new DefaultHttpClient();
         HttpPost httpPost = new HttpPost(loginUrl);
         httpPost.setEntity(new UrlEncodedFormEntity(para));
         httpPost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 ");
         httpPost.addHeader("Cookie", "__test=THE_CONTENT_OF_YOUR_COOKIE_HERE; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/");
         HttpResponse httpResponse = httpClient.execute(httpPost);
         HttpEntity httpEntity = httpResponse.getEntity();
         is = httpEntity.getContent();
    }
    else if(post == "GET")
    {
        HttpClient httpClient = new DefaultHttpClient();
        String paramString = URLEncodedUtils.format(para, "utf-8");
        loginUrl += "?" + paramString;
        HttpGet httpGet = new HttpGet(loginUrl);
        httpGet.addHeader("Cookie", "__test=THE_CONTENT_OF_YOUR_COOKIE_HERE; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/");
        HttpResponse httpResponse = httpClient.execute(httpGet);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();
    }
    }
    

And that's it. Now every time the app makes an HTTP request it will include the cookie to pass the testcookie-nginx-module and will be retrieving your JSON data.

I hope this helps and is not too late.

Regards

Solution 2

The main problem is that Byet Host implement a simple security antibots module named testcookie-nginx-module

https://kyprizel.github.io/testcookie-nginx-module/

This make your app crash

Share:
21,849
Malav Shah
Author by

Malav Shah

Associate Consultant, currently working in Capgemini. Loves coding and developing Android Applications.

Updated on September 06, 2020

Comments

  • Malav Shah
    Malav Shah over 3 years

    While trying to parse json string to android, HTML values are passed. Before a day all was working good, and suddenly my app start crashing when trying to fetch database with the help of php files.

    When I checked noticed that html values.. see logcat

    08-10 01:09:55.814: E/result(6744): <html><body><h2>Checking your browser..<h2><script type="text/javascript" src="/aes.js" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("7965e114a1dccaf35af3756261f75ad8");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";location.href="http://realroom.byethost24.com/medical/stokist.php?ckattempt=1";</script></body></html>
    08-10 01:09:55.814: E/JSON Parser(6744): Error parsing data org.json.JSONException: Value <html><body><h2>Checking of type java.lang.String cannot be converted to JSONObject
    08-10 01:09:55.816: E/AndroidRuntime(6744): FATAL EXCEPTION: AsyncTask #1
    08-10 01:09:55.816: E/AndroidRuntime(6744): Process: com.example.medionline, PID: 6744
    08-10 01:09:55.816: E/AndroidRuntime(6744): java.lang.RuntimeException: An error occured while executing doInBackground()
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at android.os.AsyncTask$3.done(AsyncTask.java:304)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.lang.Thread.run(Thread.java:818)
    08-10 01:09:55.816: E/AndroidRuntime(6744): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.toString()' on a null object reference
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at com.example.medionline.All_supplier_list$FetchMFG.doInBackground(All_supplier_list.java:182)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at com.example.medionline.All_supplier_list$FetchMFG.doInBackground(All_supplier_list.java:1)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at android.os.AsyncTask$2.call(AsyncTask.java:292)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    08-10 01:09:55.816: E/AndroidRuntime(6744):     ... 4 more
    

    This is happening to all the pages that I have hosted on byethost server, while the pages that are hosted on other server are working well and fine. I tried moving one of my file to other server and on that it is returning proper json string.

    Also when I check the url in browser it is returning proper json string without any exception or error with byethost.. but in android giving html values..

    Here's my JSONfunction class

    package com.example.medionline;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.UnsupportedEncodingException;
    import java.util.List;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;    
    import org.apache.http.NameValuePair;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.utils.URLEncodedUtils;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import android.util.Log;
    
    public class JSONfunctions
    {
    
         static InputStream is = null;
     static String result = "";
     static JSONObject jArray = null;
    public static JSONObject getJSONfromURL(String url) 
    {
        // Download JSON data from URL
        try 
        {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 ");
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();
        } 
        catch (Exception e) 
        {
            Log.e("log_tag", "Error in http connection " + e.toString());
        }
    
        try 
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) 
            {
                Log.e("jsonnnnnnn", line);
                sb.append(line + "\n");
            }
            is.close();
            result = sb.toString();
            Log.e("result", result);
        } 
        catch (Exception e) 
        {
            Log.e("log_tag", "Error converting result " + e.toString());
        }
        try 
        {
            jArray = new JSONObject(result);
        } 
        catch (JSONException e)
        {
            Log.e("log_tag", "Error parsing data " + e.toString());
        }
        return jArray;
    }
    
    public static JSONObject makeHttpRequest(String loginUrl, String post, List<NameValuePair> para)
    {
        try 
        {
            if(post == "POST")
            {
                HttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(loginUrl);
                httpPost.setEntity(new UrlEncodedFormEntity(para));
                httpPost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 ");
                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
    
            }
            else if(post == "GET")
            {
                HttpClient httpClient = new DefaultHttpClient();
                String paramString = URLEncodedUtils.format(para, "utf-8");
                loginUrl += "?" + paramString;
                HttpGet httpGet = new HttpGet(loginUrl);
                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
        catch (ClientProtocolException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        try 
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            if (is != null) 
            {
                while ((line = reader.readLine()) != null) 
                {
                    //Log.e("jsonnnnnnn", line);
                    sb.append(line + "\n");
                }
                is.close();
                result = sb.toString();
                Log.e("result", result);
            }
        }
        catch (Exception e)
        {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }
        try
        {
            jArray = new JSONObject(result);
        }
        catch (JSONException e)
        {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }
        return jArray;
    }
    }
    

    And this is my PHP file

    <?php
    include('config.php');
    date_default_timezone_set("Asia/Calcutta");
    
    $result1 = mysqli_query($con,"SELECT  *
                                        FROM  `pj_medionline_mst_stockist` 
                                        ORDER BY  `pj_medionline_mst_stockist`.`ID` ASC ");
    
    
    $response = array();
    $posts = array();
    while($row=mysqli_fetch_array($result1))
    {
        $id =$row["ID"];
        $stkcode =$row["stkcode"];
        $comName =$row["ComName"];
        $operatorid =$row["operatorid"];
        $password =$row["Password"];
    
    
        $posts[] = array('id'=>$id, 'stkcode'=>$stkcode, 'stkname'=>$comName, 'operatorid'=>$operatorid, 'password'=>$password);
    }
    
    $response['stokist'] = $posts;
    print(json_encode($response));
    ?>
    
  • Aesthetic
    Aesthetic over 7 years
    Is there a way to use it for Volley library?
  • Kunjesh Virani
    Kunjesh Virani over 6 years
    Thanks a lot ! My work get stopped for 3 day because of this small Issue. You solved it. Many thanks to you.
  • Saeed Jassani
    Saeed Jassani over 6 years
    @707 yes there is. override getHeaders() method and it should work
  • Saeed Jassani
    Saeed Jassani over 6 years
    @Sebastian Mora I used this solution but the cookie changed after a day. Is it possible to keep it the same?
  • Saeed
    Saeed over 5 years
    I ask this question here,,,
  • Honza
    Honza over 4 years
    Note that the cookie is different on every client (specifically, every client gets different "c" and therefore computes different cookie).