Android Question Best way to protect your app?

ilan

Expert
Licensed User
Longtime User
hi

i developed many apps until today that makes get request to a mysql db on a shared hosting and i realized that many times the data on my sql db does not comes from my app.
for example i have a score system that gives the user points by step 5 like for each correct answer 5 points so the number on my db must be divided by 5 but i can find scoring like 99999999 or really weird numbers so the only explanation is that people hack the db. and the funny thing is that it is super easy to do.
all you need to do is download the apk open with 7zip and go to classes.dex and start search for url, table name,... you can find it very easily and then use any browser and put the correct url to upload data to the DB.

so my question how can i make my app more secure?

thanx
 

Alex_197

Well-Known Member
Licensed User
Longtime User
thanks for the reply @aeric



i never compile in Obfuscation mode :oops:



it was just an example but the question is how can i prevent the user read the url and endpoints of my sql db that can be found with minimal effort in my apk code.


as you already mention it is very simple to perform a post request using postman or any other free app.



token will not prevent the user to hack the db. he can sign and use his token and perform a post request from outside the app using fake values.


no i dont, i think it would take to much effort to start hunting those users it would make more sense to put that effort make my app more secure.

the real question is how can i hide or encrypt my api endpoints inside my app so they are not readable. if i would use my own server application i would have much more control but because it is a shared hosting and i have to use php to communicate with the mysql db i need to find a way to keep my endpoints adresses encrypted inside my app.
the real question is how can i hide or encrypt my api endpoints inside my app so they are not readable.

The answer is - Release obfuscation. You can do a simple test - compile it in Relese mode, open apk and try to find yout endpoint string. Then try obuscation.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Another idea - 2 steps verification.

Step 1 - you can send a POST request to the server. with the encrypted device id and user id Server receives this request, does initial validation. If it passes - 2nd step.
Step 2 - the server pushes a notification back to the app, app receives this notification, does validation (yes, I'm paranoid) and sends some key back to the server. You can read about Firebase Push Notification here in the forum https://www.b4x.com/android/forum/t...s-firebase-cloud-messaging-fcm.67716/#content
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Maybe split the url between code modules and just append them at run time. That way the text will be split between classes and (maybe) not contiguous bytes that are easy to find. (Not tried it btw - just a thought)
 
Upvote 0

noxius3

Member
I store part of the urls on the server. The rest, divided into 3-4 parts, are located in Process_Globals. During execution, the address is formed from several variables, which complicates its search in the code. I connect to the database using jRDC. And I compile, always in obfuscation mode.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
the real question is how can i hide or encrypt my api endpoints inside my app so they are not readable.

The answer is - Release obfuscation. You can do a simple test - compile it in Relese mode, open apk and try to find yout endpoint string. Then try obuscation.
The protection offered by obfuscation is next to none. It's better than nothing of course but don't rely upon it. Decoding an obfuscated string is very easy since the code to do it is provided with your app.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
The protection offered by obfuscation is next to none. It's better than nothing of course but don't rely upon it. Decoding an obfuscated string is very easy since the code to do it is provided with your app.
Thanks fred for your reply. So what would you do?

i need to mention that i cannot use a server app. I need to connect to hosted server via php.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
you can implement it into php
here is my code for push message that I'm using in asp.net

B4X:
Private Function PushMessage(Subject As String, Body As String, DeviceID As String) As String

        Dim MyUser As New clsUser

        Try

            Dim oUserInfo As UserInfo = UserController.GetUser(0, MyUser.GetUserID, False)
            Dim Key As String = ""
            Dim MyDV As DataView
            Dim Facility As String = ""
            Key = System.Configuration.ConfigurationManager.AppSettings("push").ToString

            Subject = "My Subject"

            Dim result = "-1"
            Dim webAddr = "https://fcm.googleapis.com/fcm/send"
            Dim httpWebRequest = CType(WebRequest.Create(webAddr), HttpWebRequest)
            httpWebRequest.ContentType = "application/json"
            httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "key=" & Key)
            httpWebRequest.Method = "POST"

            Using streamWriter = New StreamWriter(httpWebRequest.GetRequestStream())

                Dim strNJson As String = ""

                strNJson = "{""data"": {""title"":""MyTitle"",""body"":""MyBody""},""to"":""\/topics\/DeviceID""}"

                strNJson = strNJson.Replace("MyTitle", Subject)
                strNJson = strNJson.Replace("MyBody", Body)
                strNJson = strNJson.Replace("DeviceID", DeviceID)

                

                streamWriter.Write(strNJson)
                streamWriter.Flush()
            End Using

            Dim httpResponse = CType(httpWebRequest.GetResponse(), HttpWebResponse)

            Using streamReader = New StreamReader(httpResponse.GetResponseStream())
                result = streamReader.ReadToEnd()
            End Using

            Return result

        Catch ex As Exception
            Functions.SaveError(ex)
            Return "Error " & ex.Message
        Finally
            MyUser = Nothing
        End Try
    End Function
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
check my code in asp.net in #28
Hi alex,

i looked at your code but i dont understand how it can help me?

i will explain again my issue. i cannot use web apps on my hosted builder so i cannot perform all action on the server side. all i can do is using php to update my sql db that is on my hosted server.

performing all action in php like auth and other action needs knowledge in php that i dont have. what i wanted to do is somehow hide the endpoints urls that are available on the b4a app so they cannot be taken out and manipulate from other apps. as soon as the endpoints are know they can be used to upload fake data to my sql db.
if i could use b4j web app i could perform checks on the server side. i am sure it is also possible using php but i need to learn it to know how to do it.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Maybe look at it from another angle, don't worry about a user connecting to DB after finding the URL.

Have your app supply a scorecount to the DB which increments whenever the score is updated by the app. Keep this value in your app.

example
scorecount (in app storage) = 12 (app has updated the score 12 times previously)
when sending the new score increment the scorecount in your app and save it there.
read scorecount from db.
if dbscorecount (newly read) + 1 <> sentscorecount then ignore the update as it hasn't come from your app
if correct value then process the update as normal sending score and the new scorecount

(sorry if the explanation is hard to follow/understand)
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Maybe look at it from another angle, don't worry about a user connecting to DB after finding the URL.

Have your app supply a scorecount to the DB which increments whenever the score is updated by the app. Keep this value in your app.

example
scorecount (in app storage) = 12 (app has updated the score 12 times previously)
when sending the new score increment the scorecount in your app and save it there.
read scorecount from db.
if dbscorecount (newly read) + 1 <> sentscorecount then ignore the update as it hasn't come from your app
if correct value then process the update as normal sending score and the new scorecount

(sorry if the explanation is hard to follow/understand)
there is no specific problem because there can be many ways that fake data can manipulate the game/app somehow.

i will give an example but again it is not the issue that i need to solve, i look at it from a more higher perspective. i want to avoid the situation and not a solution for a specific issue.

example:

i have a game that once you run it you are creating a user that will upload the scoring to the db (automatically and not using any sign in mechanism).
so you play -> finish game -> score is uploaded.

now there is a ranking system where i tell the player which ranking he is according to the high score he has. now if you know the urls to send the data to the php file like.


then all you need to do is calling this url in any web browser and thats it you are in rank nr1 if you put 99999999 as scoring.

again i could solve this with some check and so on but i want to solve the issue in another level. i want to some how hide the urls because today the issue is scoring tomorrow something else.

i hope i delivered my point clear. :)
 
Last edited:
Upvote 0

Num3

Active Member
Licensed User
Longtime User
I have been running for some years an app, that comunicates to a backend over SSL and encrypted data.

On the PHP side, i use these URL:

B4X:
(Site/Type/Function)
https://api.mysite.com/PUT/highscore
https://api.mysite.com/PUT/register
https://api.mysite.com/GET/allhighscores

The PUT functions only accept a valid number of arguments on the JSON file and reject all other

The messages are POSTed to the endpoint with this format:

B4X:
Dim Request as String = $"[validation=${setPayload(token,Validator)}&token=${su.EncodeUrl(token,"UTF8")}&data=${setPayload(token,JSON.ToString)}]"$
j.PostString($"${app.url }/PUT/${function.ToLowerCase.Trim}"$ , Request)
where:
setPayload is a Sub that uses AES_Encrypt to encode the data
validation is a calculated and encripted value that uses current date+time and gets checked on server date+time. This is to ensure that if a message is captured and resent, it will only be accepted within a certain time period, after that it is discarted
token the a public key for this message (it changes every message)
data is an encripted JSON file with the data itself
The private AES key is hidden inside an image file, and is retrived by a series of calculations that are executed on a random basis and stored on several variables that are only combined when something needs to be sent.

Yes i am paranoid.
 
Last edited:
Upvote 0
Top