1. 程式人生 > 實用技巧 >C/S架構的滲透測試-請求加解密及測試

C/S架構的滲透測試-請求加解密及測試

概述

目標站點是http://www.example.com,官網提供了api使用文件,但是對其測試後沒有發現漏洞,目錄、埠掃描等都未發現可利用的點。後發現官網提供了客戶端下載,遂對其進行一番測試。

資訊收集

先抓了下客戶端的包,使用Fiddler和BurpSuite都抓不到,懷疑走的不是HTTP協議,用WireShark檢視其確實用的是HTTP協議,但是資料包不好重放,這裡最後使用了WSExplorer抓指定程序的包,成功抓取到通訊的資料,抓到的資料如下,綠色的是請求包,紅色的是響應包。

資料包又分為兩部分,一個是請求行和請求頭。

一個是請求正文。

拼接起來即可放到BurpSuite中進行資料包的重放

測試過程

可看到請求包經過了加密再傳輸,返回的響應包也經過了加密。但是加解密總歸是在客戶端進行的,所以可從分析客戶端入手。

使用Exeinfo PE查殼,可得知使用的是.NET框架 C#開發的程式。

可以使用dnspy,針對.NET程式的逆向工程工具,對客戶端的加解密進行分析。開啟後發現類及方法的命名都是無規律的數字字母,程式碼做了混淆。

混淆了的程式碼不利用閱讀分析,可使用De4Dot嘗試反混淆,支援很多種混淆加密工具混淆過的原始碼。

de4dot-x64.exe origin.exe
  • 1

即可得到反混淆後的程式 origin-cleaned.exe

將反混淆後的程式拖入dnspy檢視,可看到基本已還原,提高了可讀性。


因為其通訊採用的是HTTP協議,又發現有個類名為HttpHelper,跟進分析,程式碼不多看到一個Post函式,疑似為對資料加密併發起Post請求的方法,如圖。
呼叫了MM.Encrypt()對請求的引數進行加密,跟進方法,發現其中關鍵的加密函式應該就是MM類下的test05函式。

下斷點,驗證程式是否呼叫此函式進行加密並傳輸,我在明文及密文處下了斷點。

F5啟動程式,輸入賬號密碼test123456,登入。

程式在斷點處停了下來,明文中包含我輸入的賬號test123456和md5加密過的密碼。
放行,得到經過加密的內容,可確定就是呼叫了此處的加密函式。

後又證實響應包解密呼叫的是MM類下的test06函式,請求包加密函式test05及響應包解密函式test06都是呼叫Dll中對應的函式。
此處加解密呼叫的是兩套方法,不能用解密函式去解密請求包加密後的資料。為了方便測試,以及快速加解密,將其加解密函式扣出來,同樣呼叫Dll裡的函式,編譯成一個獨立的程式,這樣也不用分析演算法。

這裡我使用的是SharpDevelop編譯的,使用Visual Studio總是會報錯…

public static string decryptResponse(string cipher){
	byte[] bytes = Encoding.UTF8.GetBytes(cipher);	
	byte[] array = new byte[bytes.Length + 128];
	int count = Program.test06(ref bytes[0], ref array[0]);
	string text = Encoding.UTF8.GetString(array, 0, count);
	return text;
}	
	
public static string encryptRequest(string plain){
	byte[] bytes = Encoding.UTF8.GetBytes(plain);		
	int num = bytes.Length * 2 + 128;
	if(num<32){
		num = 64;
	}
	byte[] array = new byte[num];
	int num2 = 0;
	num2 = test05(ref bytes[0], ref array[0]);
	string result = Encoding.UTF8.GetString(array, 0, num2);
	return result;
}

加密
解密

再用Python的Flask框架在本地寫一個代理轉發程式,方便在BurpSuite中進行重放測試。
流程如下:

  1. 本地傳送明文資料包到代理
  2. 代理接收到請求包
  3. 呼叫程式對請求包進行加密
  4. 將加密後的資料包轉發給伺服器
  5. 呼叫程式對伺服器返回的內容解密
  6. 返回給明文資料到本地
from flask import request, Flask
from urllib.parse import quote
import requests
import os

headers = {
	'User-Agent': 'Mozilla',
	'Content-Type': 'application/x-www-form-urlencoded',
	'Accept-Encoding': 'gzip, deflate',
}

app = Flask('example')
@app.route('/example', methods=['POST'])


def proxy():
	form = request.form
	request_plain = ''
	for key in form:
			request_plain += '&{}={}'.format(key, form[key])
	response_plain = test(request_plain)
	return response_plain

def encrypt(filename):
	encrypt_cmd = 'crypto.exe -encrypt {}'.format(filename) #要加密的內容 從檔案讀取
	result = os.popen(encrypt_cmd) # 執行exe
	request_cipher = quote(result.read()) #加密後的內容 經過一次url編碼把 + 號 轉成 %2B 服務端才能識別
	return request_cipher

def decrypt(filename):
	decrypt_cmd = 'crypto.exe -decrypt {}'.format(filename) #要解密的內容 從檔案讀取
	result = os.popen(decrypt_cmd) # 執行exe
	response_plain = result.read() # 讀取解密後的內容
	return response_plain

def test(request_plain):
	url = 'http://example.com/api/'
	plain_txt = 'plain.txt'
	with open(plain_txt, 'w') as f1:
		f1.writelines(request_plain) # 存放明文到plain.txt
	request_cipher = encrypt(plain_txt) # 加密明文
	response = requests.post(url=url, data=request_cipher, headers=headers) #傳送請求
	cipher_txt = 'cipher.txt'
	with open(cipher_txt, 'w') as f2:
		f2.writelines(response.text) #存放密文到cipher.txt
	response_plain = decrypt(cipher_txt) # 解密密文
	return response_plain

if __name__ == '__main__':
	app.run(host='0.0.0.0', port=9999, debug=True)


這裡每次請求的介面都是一樣的,改變的只是請求體中的引數。在CodeService中有所有介面的明文,全部提取出來。
即可正常的在BurpSuite中進行測試~
最後成功在一個介面中發現SQL注入。

原文轉載至:https://blog.csdn.net/qq_32727277/article/details/102783316