How to solve flutter wordpress json api error?

1,230

Your API is returning an html response as part of its bot protection. The response is actually some code that needs to run on your client before the server will allow it to access the API.

This is the html it's returning (not formatted on purpose):

<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("..................."),b=toNumbers(".................."),c=toNumbers("...........");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; location.href="http://crunchbox.epizy.com/wp-json/wp/v2/posts?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></html>

The important part is the javascript in the middle:

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("..............."),
    b = toNumbers("..............."),
    c = toNumbers("...............");
document.cookie = "__test=" + toHex(slowAES.decrypt(c, 2, a, b)) + "; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";
location.href = "http://crunchbox.epizy.com/wp-json/wp/v2/posts?i=1"; < /script>

Note that I've replaced the three binary sequences in toNumber("abcd1234") with....`.

If you have access to the NGINX server (I assume) that is serving the wordpress site, you could disable this. Or you could use wordpress's authentication and add an additional authentication method with a plugin - see the bottom of the wordpress documentation for api authentication.

A third option is that you could 'run' the js code and set the cookie into your request using a header. Obviously flutter can't run the js natively. But you could theoretically do it with webviews on android & ios, or you could parse the code to find the 'a', 'b', and 'c' and perform the AES-128 cbc decryption using some sort of library (this may work but no promises).

Share:
1,230
Admin
Author by

Admin

Updated on December 06, 2022

Comments

  • Admin
    Admin over 1 year

    I am trying to parse json from my wordpress site http://crunchbox.epizy.com/wp-json/wp/v2/ on a flutter app which fetch title and featured image from all existing post here is the code:

    final String apiUrl = "http://crunchbox.epizy.com/wp-json/wp/v2/";
      List posts;
    
      Future<String> getPosts() async {
        var res = await http.get(apiUrl,
            headers: {"Accept": "application/json"});
    
        setState(() {
          var resBody = jsonDecode(res.body);
          print(resBody);
          posts = resBody;
        });
        return "Success!";
    

    After running this code i am getting this error:

    E/flutter ( 2931): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
    E/flutter ( 2931): FormatException: Unexpected character (at character 1)
    E/flutter ( 2931): <html><body><script type="text/javascript" src="/aes.js" ></script><script>...
    E/flutter ( 2931): ^
    E/flutter ( 2931): 
    E/flutter ( 2931): #0      _ChunkedJsonParser.fail (dart:convert/runtime/libconvert_patch.dart:1362:5)
    E/flutter ( 2931): #1      _ChunkedJsonParser.parseNumber (dart:convert/runtime/libconvert_patch.dart:1258:9)
    E/flutter ( 2931): #2      _ChunkedJsonParser.parse (dart:convert/runtime/libconvert_patch.dart:926:22)
    E/flutter ( 2931): #3      _parseJson (dart:convert/runtime/libconvert_patch.dart:29:10)
    E/flutter ( 2931): #4      JsonDecoder.convert (dart:convert/json.dart:542:36)
    E/flutter ( 2931): #5      JsonCodec.decode (dart:convert/json.dart:169:41)
    E/flutter ( 2931): #6      jsonDecode (dart:convert/json.dart:101:10)
    E/flutter ( 2931): #7      _WordpressHomeState.getPosts.<anonymous closure> (file:///C:/Users/Arbaaz_AJ/IdeaProjects/wordpress_flutter/lib/main.dart:31:21)
    E/flutter ( 2931): #8      State.setState (package:flutter/src/widgets/framework.dart:1125:30)
    E/flutter ( 2931): #9      _WordpressHomeState.getPosts (file:///C:/Users/Arbaaz_AJ/IdeaProjects/wordpress_flutter/lib/main.dart:30:5)
    E/flutter ( 2931): <asynchronous suspension>
    E/flutter ( 2931): #10     _WordpressHomeState.initState (file:///C:/Users/Arbaaz_AJ/IdeaProjects/wordpress_flutter/lib/main.dart:41:10)
    E/flutter ( 2931): #11     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3751:58)
    E/flutter ( 2931): #12     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3617:5)
    E/flutter ( 2931): #13     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #14     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #15     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4654:14)
    E/flutter ( 2931): #16     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #17     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3653:16)
    E/flutter ( 2931): #19     Element.rebuild (package:flutter/src/widgets/framework.dart:3495:5)
    E/flutter ( 2931): #20     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3622:5)
    E/flutter ( 2931): #21     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3617:5)
    E/flutter ( 2931): #22     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #23     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #24     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4654:14)
    E/flutter ( 2931): #25     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #26     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #27     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4654:14)
    E/flutter ( 2931): #28     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #29     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #30     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4654:14)
    E/flutter ( 2931): #31     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #32     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #33     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4654:14)
    E/flutter ( 2931): #34     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #35     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #36     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3653:16)
    E/flutter ( 2931): #37     Element.rebuild (package:flutter/src/widgets/framework.dart:3495:5)
    E/flutter ( 2931): #38     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3622:5)
    E/flutter ( 2931): #39     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3769:11)
    E/flutter ( 2931): #40     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3617:5)
    E/flutter ( 2931): #41     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2907:14)
    E/flutter ( 2931): #42     Element.updateChild (package:flutter/src/widgets/framework.dart:2710:12)
    E/flutter ( 2931): #43     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3653:16)
    E/flutter ( 2931): #44     Element.rebuild (package:flutter/src/widg
    

    What i am trying to achieve is fetch the title and excerpt in a listview here is the code for that:

    FadeInImage.memoryNetwork(
                            placeholder: kTransparentImage,
                            image: posts[index]["featured_media"] == 0
                                ? 'images/placeholder.png'
                                : posts[index]["_embedded"]["wp:featuredmedia"][0]
                                    ["source_url"],
                          ),
                          Padding(
                            padding: EdgeInsets.all(10.0),
                            child: ListTile(
                              title: Padding(
                                padding: EdgeInsets.symmetric(vertical: 10.0),
                                child: Text(posts[index]["title"]["rendered"]),
                              ),
                              subtitle: Text(posts[index]["excerpt"]["rendered"]
                                  .replaceAll(new RegExp(r'<[^>]*>'), '')),
                            ),
    

    Please help me, thank you.

    • Günter Zöchbauer
      Günter Zöchbauer almost 6 years
      The request returns HTML that contains JSON. <html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">{"namespace":"wp\/v2","routes":{"\/wp\/v .... I don't know if there is an API to get pure JSON. You can use pub.dartlang.org/packages/html to extract the JSON content
  • Admin
    Admin almost 6 years
    how do i disable this bot protection can you please tell me and what are the drawbacks of disabling this.
  • rmtmckenzie
    rmtmckenzie almost 6 years
    The drawback is that you're opening your server's API up to bots. That may or may not be a concern, but it will definitely mean traffic served by your server at the very least. And since it appears your website is hosted on a free service, they probably have fairly strict limits. However, it shouldn't be all that difficult to disable it if you have permissions to access those files. In the nginx configuration file (/usr/local/nginx/conf, /etc/nginx , or /usr/local/etc/nginx) there should be a line something like testcookie on;.. removing that and restart with /etc/init.d/nginx restart
  • rmtmckenzie
    rmtmckenzie almost 6 years
    The other option as I said would be to add a wordpress plugin for authentication (or use Basic Authentication i.e. the username & password). The trick then would be to make sure that you don't use the password for an account that has any important permissions. You could make a new user with read only access to everything you need to serve, and use that as the user you use to access the API. The downsides to that would be that you have to embed that user & password into your app and that all the traffic for the app would show up as that user... although that might actually be a good thing.
  • rmtmckenzie
    rmtmckenzie almost 6 years
    The Application Password plugin seems like it would probably be a good bet. With that you make a user with read only permissions (make sure to disable draft page access too), then generate an application password for it, then in your app you add the Authentication header to your http request. The benifit of using an application password is that even if someone extracted the password from your app, I don't believe they'd be able to log into the wordpress site but rather just use it to access the api.
  • rmtmckenzie
    rmtmckenzie almost 6 years
    This is getting way off topic though so I'd better not continue any longer. If you're having problems, I'd advise asking a question for wordpress/nginx rather than flutter, as this really has very little to do with flutter (you'd have the same problem no matter which client you tried to use to access the wordpress API)
  • Admin
    Admin almost 6 years
    well thanks a lot man i will try to implement that and hope it works thanks again.