其他分享
首页 > 其他分享> > Android逆向之https(1),2021年Android常见面试题

Android逆向之https(1),2021年Android常见面试题

作者:互联网

方法说明1.0、1.1中支持的协议版本
GET获取资源1.0、1.1
POST传输实体主体1.0、1.1
PUT传输文件1.0、1.1
HEAD获得报文首部1.0、1.1
DELETE删除资源1.0、1.1
OPTIONS删除资源1.0、1.1
TRACE追踪路径1.1
CONNECT将服务器作为代理,让服务器代替用户去访问1.1
LINK建立和资源之间的联系1.0
UNLINK断开连接关系1.0

首部

http首部主要分为五大部分:

  1. 通用首部:各种类型的报文(请求、响应报文)都可以使用,提供有关报文最基本的信息。
  2. 请求首部:专用于请求报文的首部,用于给服务器提供相关信息,告诉服务器客户端的期望和能力。
  3. 响应首部:专用于响应报文的首部,用于告诉客户端是谁在响应以及响应者的能力。
  4. 实体首部:用于描述http报文的负荷(主体),提供了有关实体及其内容的相关信息。
  5. 扩展首部:非标准首部,由应用开发者定义的首部。

(以下整理的首部并非完全按照这五类划分,部分扩展首部也按照功能划入了请求首部、响应首部等部分)

通用首部

字段名说明示例
Cache-Control控制缓存的行为Cache-Control: no-cache
Connection逐跳首部、连接的管理(HTTP/1.1默认持久连接)Connection: close
Date创建报文的日期时间Date: Tue, 15 Nov 2010 08:12:31 GMT
PragmaHTTP/1.1之前版本的历史遗留字段,用来包含实现特定的指令Pragma: no-cache
Trailer说明传输中分块编码的编码信息Trailer: Max-Forwards
Transfer-Encoding逐跳首部,指定传输报文主体时使用的编码方式Transfer-Encoding: chunked
Upgrade升级为其他协议Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
Via代理服务器的相关信息Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning错误通知Warning: 199 Miscellaneous warning

请求首部

字段说明示例
Accept客户端能够接收的内容类型Accept: text/plain, text/html
Accept-Charset客户端可以接受的字符编码集Accept-Charset: iso-8859-5
Accept-Encoding端到端首部,告知服务器客户端能够处理的编码方式和相对优先级Accept-Encoding: compress, gzip
Accept-Language客户端可接受的自然语言Accept-Language: en,zh
AuthorizationWeb认证信息Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
DNT指示该用户的跟踪的偏好:0用户更喜欢在目标站点上进行跟踪;1用户不希望在目标站点上跟踪DNT: 1
Expect客户端要求的特殊服务器行为。若服务器不能理解或者满足,则须返回417状态,或者如果请求有其他问题,返回4xx状态Expect: 100-continue
Forwarded代理服务器的客户端的信息,此标头标准版本是X-Forwarded-For,X-Forwarded-Host与X-Forwarded-ProtoForwarded: for=192.0.2.60; proto=http; by=203.0.113.43
From用户的电子邮箱地址From: user@email.com
Host指定请求的服务器的域名和端口号Host: www.zcmhi.com
If-Match当客户端If-Match的值若与服务端的ETag一致,才会执行请求,否则会拒绝412If-Match: W/“67ab43”, “54ed21”, “7892dd”
If-Modified-Since若If-Modifed-Since字段值早于资源的更新时间,则希望服务端能处理该请求f-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range告知服务器若指定的If-Range字段值和请求资源的ETag值一致时,则作为范围请求处理,否则返回全部资源If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since比较资源的更新时间,与If-Modified-Since相反If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards该字段以十进制整数形式指定可经过的服务器最大数目。服务器在往下一个服务器转发请求之前,会将Max-Forwards的值减1后重新赋值,当服务器接收到Max-Forwards值为0的请求时,则不再进行转发,而是直接返回响应Max-Forwards: 10
Proxy-Authorization代理服务器要求客户端的认证信息Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Public-Key-Pins将特定的加密公钥与特定的Web务器相关联,以降低伪造证书对MITM攻击的风险Public-Key-Pins: pin-sha256=""; pin-sha256=""; max-age=5184000; includeSubDomains; report-uri=""
Public-Key-Pins-Report-Only将针对违规的报告发送到头中report-uri指定的报告,但是,Public-Key-Pins如果违反了钉住规则,仍然允许浏览器连接到服务器Public-Key-Pins-Report-Only: pin-sha256="; pin-sha256=""; includeSubDomains; report-uri=""
Range实体的节点范围请求Range: bytes=5001-10000
Referer指定该请求是从哪个页面跳转页来的,常被用于分析用户来源等信息Referer: www.example.com/index.html
Referrer-Policy用于过滤Referrer报头的策略Referrer-Policy: origin-when-cross-origin
CookieHTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器Cookie: $Version=1; Skin=new;
TE逐跳首部,告知服务器客户端能够处理的编码方式和相对优先级TE: gzip, deflate; q=0.5
Upgrade-Insecure-Requests向服务器发送一个信号,表示客户对加密和认证响应的偏好,Upgrade-Insecure-Requests: 1
User-AgentHTTP 客户端程序的信息User-Agent: Mozilla/5.0 (Linux; X11)
X-Forwarded-For来表示 HTTP 请求端真实 IPX-Forwarded-For: IP0, IP1, IP2
X-Forwarded-Host可用于确定最初使用哪个主机X-Forwarded-Host: id42.example-cdn.com
X-Forwarded-Proto确定客户端和负载平衡器之间使用的协议确定客户端和负载平衡器之间使用的协议

响应首部

字段说明示例
Accept-Ranges是否接受字节范围请求Accept-Ranges: bytes
Age从原始服务器到代理缓存形成的估算时间(以秒计,非负)Age: 12
ETag资源的匹配信息ETag: “737060cd8c284d8af7ad3082f209582d”
Expires响应过期的日期和时间Expires: Thu, 01 Dec 2010 16:00:00 GMT
Location配合 3xx : Redirection 的响应,提供重定向的 URILocation: www.example.com
Proxy-Authenticate代理服务器对客户端的认证方式Proxy-Authenticate: Basic
Retry-After如果实体暂时不可取,通知客户端在指定时间之后再次尝试Retry-After: 120
Set-CookieHttp CookieSet-Cookie: status-enable; expires=Tue, 05 Jul 2018 02:01:22 GMT; path=/; domain=.example.com;
Serverweb服务器信息Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
SourceMap响应报头链接生成的代码到一个源映射,使浏览器来重构原始源并在调试器呈现重构原始SourceMap: /path/to/file.js.map
Strict-Transport-Security通常缩写为HSTS,告诉客户端它应该只使用HTTPS,而不是使用HTTP进行通信Strict-Transport-Security: max-age=31536000; includeSubDomains
Tk显示了对相应请求的跟踪情况Tk: ! (under construction) Tk: ? (dynamic) Tk: G (gateway or multiple parties)
Vary告知下游的代理服务器,应当如何对以后的请求协议头进行匹配,以决定是否可使用已缓存的响应内容而不是重新从原服务器请求新的内容Vary: Accept-Encoding,User-Agent
WWW-Authenticate表明客户端请求实体应该使用的授权方案WWW-Authenticate: Basic
X-Content-Type-Options如果服务器发送响应头 “X-Content-Type-Options: nosniff”,则script和styleSheet元素会拒绝包含错误的 MIME 类型的响应。这是一种安全功能,有助于防止基于 MIME 类型混淆的攻击X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control控制浏览器的DNS预读取功能X-DNS-Prefetch-Control: on
X-Frame-Options给浏览器指示允许一个页面可否在 , 或者 中展现的标记,网站可以使用此功能,来确保自己网站的内容没有被嵌套到别人的网站中去,也从而避免了点击劫持的攻击X-Frame-Options: ALLOW-FROM example.com/
X-XSS-Protection是 IE,Chrome 和 Safari 的一个特性,当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面X-XSS-Protection: 1; mode=block

实体首部

字段说明示例
Allow服务器支持的HTTP请求方法Allow: GET, HEAD
Content-Disposition指示回复的内容是以内联的形式还是以附件的形式下载并保存到本地;也可在multipart/form-data 类型的应答消息体中,用来给出其对应字段的相关信息Content-Disposition: attachment; filename=“filename.jpg”
Content-Encoding告知客户端服务器对实体的主体选用的内容编码方式Content-Encoding: gzip
Content-Language实体主体使用的自然语言Content-Language: zh-CN
Content-Length实体部分大小Content-Length: 15000
Content-Location返回报文主体返回资源对应的URIContent-Location: httpo://www.example.com/index.html
Content-MD5检查报文主体在传输过程中是否保持完整,对报文主体执行 MD5 算法获得218位二进制数,再通过 Base64 编码后将结果写入Content-MD5: ZTEwYWRjMzk0OWJhNTlhYmJlNTZlMDU3ZjIwZjg4M2U=
Content-Range针对范围请求,表示当前发送部分及整个实体大小Content-Range: bytes 5001-10000/10000
Content-type实体主体内对象的媒体类型Content-Type: text/html; charset=utf-8
Expires将资源失效日期告知客户端Expires: Wed, 04 Jul 2012 08:26:05 GMT
Last-Modified资源最终修改时间Last-Modified: wed, 25 May 2018 09:11:40 GMT

跨域资源共享首部

跨域资源共享标准新增了一组HTTP头部字段,属于扩展首部,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,对那些可能对服务器产生副作用的HTTP请求方法,浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求。服务器允许后才发起实际的HTTP请求。预检请求的返回中,服务器也可以通知客户端是否需要携带身份凭证。

字段说明示例
Access-Control-Allow-Credentials指示的请求的响应是否可以暴露于该页面,当true值返回时它可以被暴露,凭证是 Cookie ,授权标头或 TLS 客户端证书Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers用于预检请求中,列出了将会在正式请求的Access-Control-Request-Headers字段中出现的首部信息Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Methods在对预检请求的应答中明确了客户端所要访问的资源允许使用的方法或方法列表Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Origin指定了该响应的资源是否被允许与给定的origin共享Access-Control-Allow-Origin: developer.mozilla.org
Access-Control-Expose-Headers出了哪些首部可以作为响应的一部分暴露给外部Access-Control-Expose-Headers: Content-Length, X-Kuma-Revision
Access-Control-Max-Age表示预检请求的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息)可以被缓存多久Access-Control-Max-Age: 600
Access-Control-Request-Headers出现于预检请求中,用于通知服务器在真正的请求中会采用哪些请求头Access-Control-Request-Headers: X-PINGOTHER, Content-Type
Access-Control-Request-Method出现于预检请求中,用于通知服务器在真正的请求中会采用哪种HTTP方法Access-Control-Request-Method: POST

安全性的不足

  1. 通信使用明文,内容可能会被窃听(可窃听)。
  2. 无法证明报文的完整性,内容有可能已遭篡改(可篡改)。
  3. 不验证通信方的身份,因此有可能遭遇伪装(可冒充)。

HTTPS协议

可以理解为HTTP+SSL/TLS, 即 HTTP 下加入 SSL/TLS 层,用于安全的 HTTP 数据传输,简单来说HTTP + 加密 + 认证 + 完整性保护 = HTTPS,用来解决HTTP协议安全性的不足。

HTTPS

SSL/TLS历史

HTTPS相比HTTP多出了SSL/TLS 层,SSL 协议原本由网景公司开发,后来被 IETF 标准化,正式名称叫做 TLS,TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3,TLS1.1和TLS1.0不支持HTTP2,目前应用最广泛的应该还是 TLS 1.2,SSL协议发展历史如下:

协议发布时间状态
SSL 1.0未公布未公布
SSL 2.01995年已于2011年弃用 RFC6176
SSL 3.01996年已于2015年弃用 RFC7568
TLS 1.01999年RFC2246
TLS 1.12006年RFC4346
TLS 1.22008年RFC5246,目前最广泛应用
TLS 1.32018年RFC8446

TLS1.2单向认证流程

以目前使用最广泛的TLS1.2说明下认证流程即握手流程,认证分为单向和双向两种模式,单向认证客户端验证服务端证书合法即可访问,一般Web应用都是采用SSL单向认证的;双向认证需要客户端和服务器都需要持有证书,两者证书验证均合法才可以继续访问。

使用wireshark抓包TLS1.2,单向认证流程如下: wireshark抓包TLS1.2

  1. 客户端发送Client Hello。将一个Unix时间戳、TLS版本、支持的所有加密套件、支持的签名算法、生成的随机数Random_C等发送给服务器。

  2. 服务器发送Server Hello。将服务器Unix时间戳、生成的随机数Random_S、协商的加密算法套件等发送给客户端。

  3. 服务器发送**Certificate、Server Key Exchange、Server

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

Hello Done**。Certificate是数字证书,Server Key Exchange为公钥参数(有时也可不需要),Server Hello Done表明服务器已经将所有预计的握手消息发送完毕。

  1. 客户端发送Client Key Exchange、Change Cipher Spec、Encrypted Handshake Message。客户端首先需要校验证书,证书向上按照证书链逐级校验,每一级证书校验过程是通过拿到证书签发者(Issuer)的证书中的公钥(证书 = 使用者公钥 + 主体信息如公司名称等 + CA对信息的确认签名 + 指纹)对本级证书(Subject)的签名进行数学验证,并校验证书是否被吊销,是否在有效期,是否与域名匹配等,验证成功即证书有效,整个一级一级验证上去,形成信任链,如果校验不通过则中断连接,浏览器弹出警告,校验正确后解析得到服务器公钥,并发送Client Key Exchange、Change Cipher Spec、Encrypted Handshake Message。Client Key Exchange:生成一个随机数 Pre-master,并用证书公钥加密,通过Fuc(random_C, random_S, Pre-Master)生成一个协商密钥;Change Cipher Spec:通知服务器协商完成,以后就使用上面生成的协商密钥进行对称加密;Encrypted Handshake Message:结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商密钥与算法进行加密。

  2. 服务器发送Change Cipher Spec、Encrypted Handshake Message。服务器使用私钥解密得到 Pre-master数值,基于之前交换的两个明文随机数 random_C 和 random_S,同样通过Fuc(random_C, random_S, Pre-Master)得到协商密钥,计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性,验证通过之后,服务器同样发送 change_cipher_spec 以告知客户端后续的通信都采用协商的密钥与算法进行加密通信;encrypted_handshake_message:服务器也结合所有当前的通信参数信息生成一段数据并采用协商密钥与算法加密并发送到客户端。

  3. 客户端计算所有接收信息的hash值,并采用协商密钥解密encrypted_handshake_message,验证服务器发送的数据和密钥,验证通过则握手完成。

  4. 开始使用协商密钥与算法进行加密通信。(Encrypted Alert是由客户端或服务器发送,意味着加密通信因为某些原因需要中断,警告对方不要再发送敏感的数据)。

Android抓包HTTPS

HTTP/HTTPS抓包工具有不少,常见的电脑端抓包工具有fiddlerCharlesBurp SuitewhistleAnyProxy,Android端抓包APP也有HttpCanary,wireshark也可以抓包但是不可以解密HTTPS内容。

使用Charles抓包安卓HTTP很简单,将手机WIFI设置代理为Charles,步骤如下:

  1. 为方便设置代理,使手机与电脑处于同一局域网(连接同一个WIFI,或者电脑连到同一个路由器的LAN端口)。
  2. 电脑使用ipconfig查看局域网ip,并打开Charles。
  3. 手机连接的WIFI–高级设置–代理服务器,代理服务器填写电脑的局域网ip,Charles的代理端口默认8888。
  4. 电脑端Charles允许连接即可。
  5. Charles–Proxy–SSL Proxying Setting,Enable SSL Proxying打勾,add添加抓包的Host和Port,一般Port都是443,Host和Port都填*则抓包所有。

打开APP就能在Charles上看到抓包的HTTP,但是HTTPS都会显示为Unknown,因为还没有安装Charles的证书。手机设置代理以后,浏览器访问chls.pro/ssl下载Charles证书并安装。Android 7.0以下直接安装即可,但是Android 7.0及以上默认不信任用户自己安装的证书,而只信任系统预设的证书,解决方法有:

AndroidManifest.xml修改:

<manifest … >



network_security_config.xml内容:

<?xml version="1.0" encoding="utf-8"?>

在JSSE中证书信任管理器类实现了X509TrustManager接口,我们可以自己实现一个X509TrustManager,通过hook修改掉网络请求库的X509TrustManager配置。

比如自定义X509TrustManager实现信任所有服务端的证书(无论是否过期、是否经过认证):

public class TrustAllManager implements X509TrustManager {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}

okhttp的X509TrustManager设置为:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(createAllSSLSocketFactory(), new TrustAllManager());

我们可以通过hook OkHttpClient.Builder类的sslSocketFactory方法,实现修改X509TrustManager配置,从而实现用户证书的信任。

HTTPS抓包原理

代理原理

Charles、fiddler、HttpCanary抓包都是基于代理实现的,对HTTPS的抓包原理其实也都差不多,类似于中间人攻击,原理如下(图片来源于谈移动端抓包方式和原理及如何防犯中间人攻击):

Charles抓包原理

Android防抓包策略及绕过思路

Android上HTTPS抓包成本并不算高,使系统信任第三方证书就能够实现抓包,Android 7.0 (API 24)及以上虽默认不再信任用户CA,提高了安全性但抓包成本也不算高,还可添加其他防抓包策略进一步提高安全性。

设置无代理模式

由于Charles、fiddler这些抓包工具是基于代理实现的(wireshark不是基于代理,而是网卡抓包),所以可以将APP所用的HTTP客户端设置为无代理,设置之后HTTP客户端不会连接到代理服务器,这样的话Charles就无法直接抓包了,比如OkHttp配置无代理:

OkHttpClient.Builder()
.proxy(Proxy.NO_PROXY)
.build()

绕过方案:
PI 24)及以上虽默认不再信任用户CA,提高了安全性但抓包成本也不算高,还可添加其他防抓包策略进一步提高安全性。

设置无代理模式

由于Charles、fiddler这些抓包工具是基于代理实现的(wireshark不是基于代理,而是网卡抓包),所以可以将APP所用的HTTP客户端设置为无代理,设置之后HTTP客户端不会连接到代理服务器,这样的话Charles就无法直接抓包了,比如OkHttp配置无代理:

OkHttpClient.Builder()
.proxy(Proxy.NO_PROXY)
.build()

绕过方案:

标签:面试题,请求,证书,首部,Charles,2021,服务器,Android,客户端
来源: https://blog.csdn.net/m0_65511948/article/details/122191851