[PYTHON] How to intercept or tamper with the SSL communication of the actual iOS device by a proxy

Introduction

When interacting with the Web / API server via API in smartphone application development, there is no such thing as "If you use https, communication will not be noticed by the user", and the user can do it in the same way as using a tool in a Web application. You can check and tamper with the communication contents.

Therefore, if the app or server API is not designed and implemented on the premise of that, the app user may falsify the game score result transmission, damage the raid boss in the social game, or purchase the EC site app. Will also be possible.

Also, I recently released an app called "All-you-can-listen to music for free !! --Net radio"](https://itunes.apple.com/jp/app/nettorajio-j-popmo-wu- liaode / id769979888? mt = 8), check if the static link library installed in this app is not communicating with an unknown external server, or if you intend to use SSL but are not communicating otherwise To do this, I use a proxy server tool called mitmproxy.

The following contents are like this

--About mitmproxy and its introduction --Confirmation of communication contents --Falsification of communication contents (request rewriting, response rewriting)

What you need is:

About mitmproxy and its introduction

mitmproxy is a command line proxy tool. The name mitm is an abbreviation for man-in-the-middle and seems to come from terms used in communication terms such as man-in-the-middle attack.

Man-in-the-middle attacks are radical, but they are a useful tool for verifying your own apps.

The image looks like this:

mitm_2.jpg

The rough mechanism is to use the Internet sharing (the function that OSX itself becomes a WiFi router) in the standard setting of Mac OS X, relay the communication with a proxy, and use the WiFi on the actual iOS device.

Python installation

To run mitmproxy, you need Python first, so install Python with homebrew.

 $ brew update
 $ brew upgrade
 $ brew install python

Then install pip. easy_insall should be installed at the same time as python is installed by brew.

$ easy_install pip

Install mitmproxy

Install mitmproxy from pip

$ pip install mitmproxy

If you have already installed it and want to update it, add option -U as follows and update it.

$ pip install mitmproxy -U

The related libraries are also installed by installing with pip.

Start mitmproxy

To execute, specify the port with the option -p as follows.

$ mitmproxy -p 8080

I have specified port 8080, but this also requires 8080 to be specified in the WiFi settings from the iPhone side.

You can specify the server address and port number by selecting Manual with HTTP Proxy from the WiFi settings of iOS.

IMG_0669.jpg

(Sunny in the figure is the machine name of Mac OS X, which is the WiFi name, so don't worry)

Installation of root certificate on actual iPhone

Also, when mitmproxy is executed, a certificate called mitmroxy-ca.pem is created in ~ / .mitmproxy /. It is possible to install by sending this certificate by email from OS X to the iPhone and opening the certificate from the email client on the iPhone side. You can check this certificate from [Settings] [General] [Provisioning], which is familiar to iOS app developers.

Use mitmproxy

A simple use of mitmproxy is to view requests and responses, tamper with them, or stop communication.

Regarding falsification of the request, for example, you can change the parameters from the already sent request, and you can send the changed request again.

名称未設定.jpg

Interactively rewrite request / response data

From the request list on the screen shown in the figure where mitmproxy is started, press the [Enter key] to move to the GET request / response details screen. Edit request (query, path, URL, header, form, body, method) with [e key], You can return to the list and get the edited request again with the [r key].

You can also undo the edits with the [V key], which is hard to notice. You can check these shortcuts by pressing the [? Key].

This ability to edit requests interactively makes it easy to try API calls on the server side, making it ideal for validation and testing when the specifications on the server API side are unknown. You will also be able to test anomalous systems when parameters are messed up, such as when requesting billing items, and sending receipts to the server during In-App Purchase.

On the contrary, in this interactive rewriting, even if you edit the request and GET / POST again, the communication on the application side has been completed, so if you can test by receiving the tampered request / response on the application side, etc. I think there are few.

Real-time data tampering with scripts

With mitmproxy, you can apply a script for each communication by specifying a Python script file that describes the contents to be tampered with in advance, instead of falsifying the request / response by interactive operation.

For example, suppose you have a system called Raid Boss in a social game where a large number of users are fighting a common boss.

In most cases, the flow will be:

--User A inflicted 100 damage on the boss --Send a request to the server that User A has done 100 damage --The server side recognizes that user A has done 100 damage --Completion response to user A

Considering changing the damage with mitmproxy and changing the number of reward items that caused damage, it becomes as follows.

--User A inflicted 100 damage on the boss --Changed to hook the request and deal 9999 damage --Send a request to the server that User A has done 9999 damage --The server side recognizes that user A has done 9999 damage --Completion response to user A --Hook the response and increase the number of reward items

By falsifying the request response with a script, it becomes possible to do things that could not be timed out by interactive rewriting.

Specifying a script

$ mitmproxy -s examples/add_header.py

The add_header.py in the sample has the following simple contents, so it should be brought to the introduction.

add_header.py


def response(context, flow):
    flow.response.headers["newheader"] = ["foo"]

The response method is a method that rewrites the communication response before delivering it to the HTTP (S) client. Override this method, add "newheader" to the response header, and set the value to the string "foo" from the list.

The Flow class and Response class are defined in flow.py, so you will have to refer to them to understand the specifications.

https://github.com/mitmproxy/mitmproxy/blob/master/libmproxy/flow.py

There is also sample code that uses a script to determine whether the request is for a specific host, which is the most helpful.

https://github.com/mitmproxy/mitmproxy/blob/master/examples/redirect_requests.py

redirect_requests.py will create an original response for all requests to the host on "example.com" and return it, redirecting to "mitmproxy.org" if it is "example.org".

Based on this sample code, it will be quick to tamper with and verify the request to the host you prepare.

About mitmdump

Installing mitmproxy also installs a tool called mitmdump. Unlike the mitmproxy explained so far, mitmdump outputs the result to the standard output instead of the interactive list display like the console screen mentioned above, so it seems that you can narrow down the result by using it together with grep. By using this, you intend to use https for a specific host, but you will be able to efficiently check whether it is http.

Operation and application summary

--Try to make an illegal request by in-app purchase with the basic operation of mitmproxy --With the basic operation of mitmproxy, you can easily try what happens by sending a fake (used or other app) receipt from the app to the server in the in-app purchase part. --Try falsifying the request / response to a specific host with the mitmproxy script --You can check if http communication has been made to a specific host with mitmdump.

What I didn't write here

The method described here modifies the wifi settings to access port 8080. However, if you use a transparent proxy, you can make the actual machine communicate as usual using the default port 80 of wifi.

For information on how to use a transparent proxy, refer to the following site.

Transparent mitmproxy with Wifi sharing on Mac http://bagpack.hatenablog.jp/entry/2014/02/04/225553

in conclusion

If the world's Web API designers / operators and application developers do not know the above correctly, it will take a different time from the original content management such as recovery in the event of a failure and tracking of violators, and damage will occur. It even causes a feeling of stagnation in the plan. I think that the beginning is that the design is passive due to optimistic thinking such as peace of mind if you communicate with https with a smartphone application, so I thought that it was the first thing to know how to intercept / tamper with the communication.

In fact, Apple's Game Center seems to send scores via plist, and it seems that you can change the score of the app user just by tampering with the interactive request by mitmproxy (although it may be fixed now). ..

Setting highscores on Apple's GameCenter http://mitmproxy.org/doc/tutorials/gamecenter.html

Specific security measures will vary depending on the requirements and priorities of each content, so think for yourself. Or If you consult with us, we will think together.

Reference URL

mitmproxy http://mitmproxy.org/

mitmproxy script sample https://github.com/mitmproxy/mitmproxy/tree/master/examples

Check the contents of SSL communication using mitmproxy http://ido.nu/kuma/2012/01/29/how-to-use-mitmproxy/

Did you start using pip because of the pyasn1 and PyOpenSSL dependencies? https://github.com/mitmproxy/mitmproxy/issues/37

Recommended Posts

How to intercept or tamper with the SSL communication of the actual iOS device by a proxy
How to plot a lot of legends by changing the color of the graph continuously with matplotlib
[Python] How to use the for statement. A method of extracting by specifying a range or conditions.
[Introduction to Python] How to sort the contents of a list efficiently with list sort
How to calculate the volatility of a brand
[python] How to sort by the Nth Mth element of a multidimensional array
How to get a list of files in the same directory with python
[Introduction to Python] How to get the index of data with a for statement
[Python] How to deal with the is instance error "is instance () arg 2 must be a type or tuple of types"
How to create a submenu with the [Blender] plugin
How to identify the element with the smallest number of characters in a Python list?
[Ruby] How to replace only a part of the string matched by the regular expression?
A memo on how to overcome the difficult problem of capturing FX with AI
Create a 2D array by adding a row to the end of an empty array with numpy
How to insert a specific process at the start and end of spider with scrapy
[Ubuntu] How to delete the entire contents of a directory
[Python] How to make a list of character strings character by character
How to test the attributes added by add_request_method of pyramid
How to display a list of installable versions with pyenv
A story about how to deal with the CORS problem
How to connect the contents of a list into a string
How to send a file in one shot by connecting to a host on the other side of the platform with SCP in multiple stages
Find the white Christmas rate by prefecture with Python and map it to a map of Japan
How to display the CPU usage, pod name, and IP address of a pod created with Kubernetes
How to determine the existence of a selenium element in Python
[Introduction to Python] How to split a character string with the split function
How to check the memory size of a variable in Python
[Introduction to StyleGAN] I played with "The Life of a Man" ♬
How to make a command to read the configuration file with pyramid
Here's a brief summary of how to get started with Django
How to check the memory size of a dictionary in Python
How to find the memory address of a Pandas dataframe value
How to output the output result of the Linux man command to a file
How to monitor the execution status of sqlldr with the pv command
How to get the vertex coordinates of a feature in ArcPy
How to send a request to the DMM (FANZA) API with python
[NNabla] How to remove the middle tier of a pre-built network
How to run the practice code of the book "Creating a profitable AI with Python" on Google Colaboratory
[EC2] How to take a screen capture of your smartphone with selenium
I tried to communicate with a remote server by Socket communication with Python.
Think about how to write a filter with the Shotgun API-Contact Versions
How to crop the lower right part of the image with Python OpenCV
[Python] Explains how to use the range function with a concrete example
[Image recognition] How to read the result of automatic annotation with VoTT
How to deal with SSL error when connecting to S3 with boto of Python
[NNabla] How to add a quantization layer to the middle layer of a trained model
How to put a line number at the beginning of a CSV file
Setting to debug test by entering the contents of the library with pytest
How to fix the initial population with a genetic algorithm using DEAP
How to create a wrapper that preserves the signature of the function to wrap
[Introduction to Python] How to write a character string with the format function
How to format a list of dictionaries (or instances) well in Python
How to play a video while watching the number of frames (Mac)
I tried to verify the result of A / B test by chi-square test
Summary of how to build a LAMP + Wordpress environment with Sakura VPS
How to sort by specifying a column in the Python Numpy array.
How to get the "name" of a field whose value is limited by the choice attribute in Django's model
How to add a package with PyCharm
How to check the version of Django
How to pass the execution result of a shell command in a list in Python
Feel free to write a test with nose (in the case of + gevent)