در این مطلب تا جایی که دانشم کفاف می‌دهد درباره‌ی درخواست‌های HTTP صحبت می‌کنم.

در قسمتِ «شروع سریع» از پستِ «هدف‌گذاری و یک شروع در حوزه‌ی بات‌ها!»، راه‌اندازیِ پراکسی‌سرورِ واسطِ BurpSuite را شرح دادم؛ در نتیجه برای شروعِ کار با شنودگرِ BurpSuite، شاید لازم باشد آن قسمت را مطالعه کنید.

Taking Up Where Left Off

نکته: این تیتر سعیِ ناکامی در ترجمه‌ی Taking up where left off است که نمی‌دانم فارسیِ خوبش چه می‌شود. خیلی عجیب بود، همین انگلیسی بهتره.

در قسمتِ قبل دیدیم که یک درخواست Intercept شد و ما محتوای آن‌را در BurpSuite مشاهده کردیم.
Intercept شدنِ درخواست: وقتی می‌گوییم یک درخواست Intercept شده است؛ بدان معناست که درخواست از مرورگر به سمتِ سرور ارسال شده است، ولی از آن‌جا که درخواست می‌بایستی از پراکسی‌سرور(که Burp است) هم عبور کند، در هنگامِ عبور از Burp، جلوی ادامه‌ی مسیرش گرفته شده و حال در آن قسمت منتظرِ این است که ما به آن اجازه‌ی عبور بدهیم یا خیر.
نمودارِ یک درخواست که از طریقِ Burp به اینترنت می‌رود
حال که همه‌کاره ما هستیم و مسئله این است که اجازه‌ی عبور بدهیم یا ندهیم(دادن یا ندادن، مسئله این است!)، می‌شود محتوای درخواست را نیز تغییر داد.
برای مثال اگر درخواست قرار است به طورِ طبیعی به دنبالِ «مهدی» بگردد، ما می‌توانیم با تغییراتی که در آن اعمال می‌کنیم، کاری کنیم که به دنبالِ «محمد» بگردد.
مثال: بیایید فرض کنیم با مرورگرِ خود در سایتِ bing.com به دنبالِ عبارتِ «مهدی» می‌گردیم. (یعنی مهدی را نوشته و اینتر می‌کنیم(یا روی آن علامتِ ذره‌بین کلیک می‌کنیم))
اینترسپت شدنِ سرچ برای مهدی
در تصویرِ فوق(که با دو کلیک(ابتدا رویش و سپس روی «اندازه واقعی تصویر») می‌توانید سایزِ کاملش را ببینید)، مشاهده می‌کنید که درخواستِ ارسال شده به بینگ برای سرچِ عبارتِ مهدی چگونه است.
در ابتدا قطعاً عباراتِ ارسال شده دستِ کمی از یک نوارِ قلب(از نظرِ گیج‌کننده‌بودن) ندارند، اما در ادامه و با مطالعه‌ی ساختارشان، به درکی درست نسبت به آن‌ها خواهیم رسید.
عبارت‌ها در اصل بدین صورت هستند:
GET /search?q=%D9%85%D9%87%D8%AF%DB%8C&go=Submit&qs=n&form=QBLH&pq=%D9%85%D9%87%D8%AF%DB%8C&sc=0-0&sp=-1&sk=&cvid=9b01394079ba4707b6de42c99de7cce3 HTTP/1.1
Host: www.bing.com
Proxy-Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Referer: http://www.bing.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,fa;q=0.6
Cookie: SRCHUID=V=2&GUID=0B7B5FB669B243B5ACDA7AF1D0769043; SRCHUSR=AUTOREDIR=0&GEOVAR=&DOB=20151003; _EDGE_V=1; MUID=1D99561EB1426E1111DE5E2BB0EA6FC7; MUIDB=1D99561EB1426E1111DE5E2BB0EA6FC7; SRCHHPGUSR=CW=1366&CH=677&DPR=1; SRCHD=D=4079323&AF=NOFORM; SCRHDN=ASD=0&DURL=#; WLS=TS=63579983169; _SS=SID=28184B9573844114A3EACA35912C9396&bIm=333241&HV=1444386376; _EDGE_S=mkt=fa-ir&SID=272116DE6AFB674E3DB21EE46B9D66E3; _HOP=

که می‌توان آن‌ها را به بخش‌های ریزتری تقسیم کرد و بررسی را روی آن بخش‌ها انجام داد.

مطالبی که در این بخش می‌آیند، برای کاربرانی است که آشناییِ قبلی‌ای با درخواست‌های HTTP ندارند و مایلند از پایه با آن‌ها آشنا شوند.
کلمه‌ی HTTP، مخففِ Hypertext Transfer Protocol(پروتکلِ انتقالِ ابرمتن :دی) است. کلِ وب از این پروتکل که در سالِ 1990 ساخته شده است، استفاده می‌کند. تقریباً هر چیزی که شما در مرورگرهای وبِ خود می‌بینید، از طریقِ HTTP به سیستمِ شما انتقال یافته است. برای مثال زمانی که این صفحه را روی مرورگرتان باز می‌کنید، مرورگرِ شما نزدیک به 15 درخواستِ HTTP ارسال می‌کند و همین مقدار پاسخِ HTTP دریافت می‌کند. (HTTP Request, HTTP Response)
هدرهای HTTP مهم‌ترین بخشِ درخواست‌های HTTP هستند، و حاویِ برخی اطلاعات درباره‌ی مرورگرِ شما، صفحه‌ای که آن‌را درخواست کرده‌اید، و سرور هستند.
نمودارِ یک درخواستِ HTTP
همان‌طور که در نمودارِ بالا قابلِ مشاهده‌است، مرورگرِ شما یک درخواستِ HTTP به سرور ارسال می‌کند که حاویِ یک خطِ درخواست و برخی هدرها می‌باشد(این مفاهیم را در ادامه توضیح داده‌ایم). سرور این درخواست را دریافت کرده و آنالیز می‌کند، و در نهایت یک پاسخ(Response) به این درخواست ارسال می‌کند؛ که از یک خطِ وضعیت، چند هدر و محتوا تشکیل شده است.
مثال. زمانی که من عبارتِ سرچی را در بینگ وارد کردم و روی علامتِ ذره‌بین کلیک کردم، درخواستِ بالا توسطِ مرورگرم به سرور ارسال شد.

ساختارِ یک درخواستِ HTTP می‌تواند به صورتِ زیر خلاصه شود:

یک درخواستِ HTTP و هدرهای آن

خطِ درخواست

خطِ اول همیشه خطِ درخواست است؛ یعنی در این خط، مشخص می‌شود قرار است چه چیزی از سرور درخواست شود.
این خط به بخش‌های زیر تقسیم می‌شود:
  • متدِ درخواست
  • آدرس(URI)ـــِ درخواست
  • ورژنِ پروتکل
و در انتهای خط هم یک کاراکترِ اینتر(CRLF) وجود دارد که مشخص می‌کند «خطِ درخواست» به پایان رسیده است.
لازم به ذکر است که بخش‌های مختلفِ خطِ درخواست، با کاراکتر فاصله(Space یا SP) از یک‌دیگر جدا می‌شوند.
فرمِ کلیِ خطِ درخواست به شکلِ زیر است:
Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

در درخواستی که ما به bing فرستادیم، مقدارِ خطِ درخواستمان برابر با مقدارِ زیر بود:

GET /search?q=%D9%85%D9%87%D8%AF%DB%8C&go=Submit&qs=n&form=QBLH&pq=%D9%85%D9%87%D8%AF%DB%8C&sc=0-0&sp=-1&sk=&cvid=9b01394079ba4707b6de42c99de7cce3 HTTP/1.1

متدِ درخواست

متدِ درخواست که در ابتدای خطِ درخواست می‌آید، مشخص می‌کند که این درخواست قرار است چه نوعی از درخواست باشد؛ برای مثال یک GET باشد(که به معنای درخواست برای یک فایل یا صفحه از سرور است)، یا یک POST(که یعنی ارسالِ عباراتی به سرور برای پردازش شدن) و یا نوعی دیگر.
مقدارِ متدِ درخواست، یک مقدارِ Case Sensitive یا حساس به بزرگ و کوچک است؛ در نتیجه Post با POsT و با PoST فرق دارد و باید همواره عبارتِ صحیح که POST است به سرور ارسال گردد.
عبارت‌های معمول که به عنوانِ مقدارِ متدِ درخواست ست می‌شوند، به شرحِ زیرند:
       Method         = "OPTIONS"                ; Section 9.2
                      | "GET"                    ; Section 9.3
                      | "HEAD"                   ; Section 9.4
                      | "POST"                   ; Section 9.5
                      | "PUT"                    ; Section 9.6
                      | "DELETE"                 ; Section 9.7
                      | "TRACE"                  ; Section 9.8
                      | "CONNECT"                ; Section 9.9

در درخواستی که ما به bing فرستادیم، مقدارِ متدِ درخواستمان برابر با GET بود.

آدرسِ درخواست (Request URI)

این مقدار مشخص می‌کند که درخواستِ ما به کدام قسمت از سایت یا سرور ارسال خواهد گشت؛ هر مقداری می‌تواند به عنوانِ Request URI به سایت ارسال گردد؛ مقادیرِ زیر همگی مقادیرِ مناسبی برای Request URI هستند:
*
http://www.w3.org/pub/WWW/TheProject.html
/pub/WWW/TheProject.html

در درخواستی که ما به bing فرستادیم، مقدارِ آدرسِ درخواستمان برابر با مقدارِ زیر بود:

/search?q=%D9%85%D9%87%D8%AF%DB%8C&go=Submit&qs=n&form=QBLH&pq=%D9%85%D9%87%D8%AF%DB%8C&sc=0-0&sp=-1&sk=&cvid=9b01394079ba4707b6de42c99de7cce3

نکته: در آینده نحوه‌ی قابلِ فهم‌تر کردنِ عباراتِ عجیب و غریبِ آدرس را با هم بررسی می‌کنیم.

ورژنِ پروتکل

در انتها هم ورژنِ پروتکل به سایت ارسال می‌شود.
در درخواستی که ما به bing فرستادیم، مقدارِ ورژنِ پروتکلمان برابر با مقدارِ زیر بود:
HTTP/1.1

این مقدار مشخص می‌کند که درخواستِ ما بر طبقِ چه پروتکلی ارسال می‌شود. در نتیجه سرور در فهمِ حرف‌های ما از همان پروتکل برای خواندن استفاده می‌کند.

قابلِ فهم‌ـیزاسیون

همان‌طور که احتمالاً متوجه شدید، فهمِ مقدارِ RequestURI کمی پیچیده است؛ زیرا به شکلی اِنکد شده است. برای دیکد کردنِ مقدارِ آن ابتدا باید متوجه شویم که این انکدینگ با چه متدی صورت گرفته است.

اگر دقت کنید، متوجه می‌شوید که کاراکترِ فاصله(Space)، در خطِ درخواست برای جداکردنِ مقادیرِ ارسالی صورت می‌گیرد، حال فرض کنید ما درخواستی می‌خواهیم به سایت ارسال کنیم که در مقدارِ آدرسِ درخواستِ آن، یک کاراکترِ فاصله داریم.
اگر بخواهیم آن کاراکترِ فاصله را به همان شکلِ خام در درخواست وارد کنیم، مسلماً نگارشِ ما غلط می‌شود و مقدارِ بعد از فاصله به عنوانِ «ورژنِ پروتکل» در نظر گرفته می‌شود.

حالا چی‌کار کنم؟ :(

برای این‌که کاراکترِ فاصله به صورتِ خام در درخواست وارد نشود و نگارشِ ما به مشکل نخورد، می‌آییم و نوعی Encoding تعریف می‌کنیم تا این مشکل حل شود؛ یعنی به جای کاراکترِ فاصله، از یک معادل استفاده می‌کنیم که با نگارش به مشکل نخورد.
این Encoding را URL Encode می‌نامیم و عکسِ آن‌را URL Decode می‌گوییم.

URL Encode

طرزِ کارِ این نوع انکدینگ، Substitute(جای‌گزین) کردنِ برخی عبارات با برخی عباراتِ دیگر است، برای مثال، URL Encode شده‌ی کاراکترِ Space، برابرِ 20% است. 
نیازی نیست که دیکشنریِ کاملِ URL Encode را حفظ کنید(حتی بعید است سازندگانش هم همه‌ی عباراتش را حفظ باشند)؛ زیرا این کار قرار است توسطِ سیستم‌ها انجام شود. و برای مثال می‌توانید این ابزارِ خوب را مشاهده کنید که هر دو عملِ Encode, Decode را روی این انکدینگ انجام می‌دهد.

در نتیجه حالا وقتِ آن است که عبارتِ پیچ‌درپیچی که در آدرسِ درخواست به bing فرستاده بودیم را Decode کنیم تا ببینیم چه رازی در پیِ آن نهفته است!
/search?q=%D9%85%D9%87%D8%AF%DB%8C&go=Submit&qs=n&form=QBLH&pq=%D9%85%D9%87%D8%AF%DB%8C&sc=0-0&sp=-1&sk=&cvid=9b01394079ba4707b6de42c99de7cce3

دیکد می‌شود به:

/search?q=مهدی&go=Submit&qs=n&form=QBLH&pq=مهدی&sc=0-0&sp=-1&sk=&cvid=9b01394079ba4707b6de42c99de7cce3

همان‌طور که می‌بینید مقدارهای «مهدی» و «مهدی»(۲بار در درخواست آمده)، به صورتِ URL Encode شده در آمده و به سرور ارسال شده‌اند؛ این یعنی مقادیرِ فارسی به صورتِ خام نمی‌توانند در آدرسِ درخواست بیایند و باید حتماً قبل از اضافه شدن به درخواست، URL Encode شوند.

هدرِ Host

بقیه‌ی درخواست بر اساسِ آن‌که مقدارِ  آدرسِ درخواستِ(Request URI) چگونه باشد، متغیر است.
1. اگر مقدارِ آدرسِ درخواست، یک آدرسِ کامل باشد، مقدارِ Host در خودِ Request URI می‌آید؛ یعنی هیچ مقدارِ Hostـی به سایت ارسال نمی‌شود(و در صورتِ ارسال نادیده گرفته می‌شود).
برای مثال اگر خطِ درخواستمان این باشد:
 GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

دیگر احتیاجی به ارسالِ مقدارِ Host نخواهیم داشت(چرا که مقدارِ هاست در خودِ آدرسِ درخواست ارسال شده است).

2. اگر مقدارِ آدرسِ درخواست، یک آدرسِ کامل نباشد، نیاز است که مقدارِ Host نیز ارسال شود تا مشخص شود کدام یک از سایت‌های روی سرور موردِ درخواستِ ما است. (چون درخواست مستقیماً به سرور ارسال می‌شود و باید مشخص کنیم کدام یک از سایت‌های روی سرور مطلوبِ ماست)

برای مثال اگر خطِ درخواستمان این باشد:

GET /pub/WWW/TheProject.html HTTP/1.1

لازم است تا با ارسالِ یک مقدارِ Host مشخص کنیم هدفمان کدام سایت روی سرور است:

GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.w3.org

هدر

به یک مقدار که به صورتِ زیر مشخص می‌شود؛ یک Header گفته می‌شود:

HEADER_NAME: HEADER_VALUE
مقدارِ هدر :نامِ هدر

مقدارِ یک Header، برخلافِ مقادیرِ خطِ درخواست، می‌تواند دارای کاراکتر اسپیس باشد؛ زیرا از دونقطه(:) تا انتهای خط که با یک کاراکترِ اینتر(CRLF) مشخص می‌شود، همگی جزوِ مقدارِ هدر در نظر گرفته می‌شود؛ پس روی مقدارِ یک هدر، URL Encode شدن صورت نمی‌گیرد و داده‌ها به صورتِ خام در آن قرار می‌گیرند. (هر چند Enter هم نمی‌توان در مقدارِ یک هدر داشت)

هدرهای دیگر

بقیه‌ی هدرها اطلاعاتِ بیشتری در موردِ درخواست و ارسال‌کننده‌ی آن مشخص می‌کنند.
هدرهای معروف عبارتند از:
request-header = Accept                   ; Section 14.1
                      | Accept-Charset           ; Section 14.2
                      | Accept-Encoding          ; Section 14.3
                      | Accept-Language          ; Section 14.4
                      | Authorization            ; Section 14.8
                      | Expect                   ; Section 14.20
                      | From                     ; Section 14.22
                      | Host                     ; Section 14.23
                      | If-Match                 ; Section 14.24
                      | If-Modified-Since        ; Section 14.25
                      | If-None-Match            ; Section 14.26
                      | If-Range                 ; Section 14.27
                      | If-Unmodified-Since      ; Section 14.28
                      | Max-Forwards             ; Section 14.31
                      | Proxy-Authorization      ; Section 14.34
                      | Range                    ; Section 14.35
                      | Referer                  ; Section 14.36
                      | TE                       ; Section 14.39
                      | User-Agent               ; Section 14.43

که ما فقط آن‌هایی را بررسی می‌کنیم که به کارمان می‌آیند.

User-Agent

این هدر حاویِ اطلاعاتی درباره‌ی مرورگرِ کاربر است؛ یعنی مشخص می‌کند کاربری که این درخواست را به سرور ارسال کرده است از چه مرورگر و چه نسخه‌ای از آن استفاده می‌کند.
این هدر توسطِ مرورگرها پر می‌شود و در نتیجه از آن‌جا که ما قادر هستیم درخواست‌ها را تغییر دهیم، این هدر را نیز می‌توانیم تغییر دهیم(یعنی اگر جایی دیدید که ورژن و نوعِ مرورگر مهم است و شما آن مرورگر را ندارید، جای نگرانی نیست، زیرا این مقدار به سادگی قابلِ تغییر است).
مقدارِ User-Agentـی که مرورگرِ من به bing فرستاد، بدین شکل بود:
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36

Referer

این مقدار که از نظرِ املایی غلط است(و قرارداد است دقیقاً از همین واژه استفاده شود)، حاویِ آدرسی است که کاربر از طرفِ آن به این برگه هدایت شده است(یعنی مثلاً روی لینکی کلیک کرده است که به این صفحه منتقل گشته)، و در مقصد با خواندنِ آن می‌توان تشخیص داد کاربران از چه سایت‌ها و برگه‌هایی به سایتِ ما منتقل شده‌اند.
این هدر اساسِ کارِ بسیاری از آمارگیرها، مثلِ همین آمارگیرِ بلاگِ بیان می‌باشد.
کاربردِ هدرِ Referer

Cookie

مقدارِ این هدر توسطِ کوکی‌های سیستمِ شما که برای این دامنه تعیین شده‌اند پر می‌شود. (کوکی عبارتی‌است که به لوگینِ شما در یک سایت اختصاص می‌یابد و پس از آن دیگر برای این‌که مشخص شود شما کدام کاربر در آن سایت هستید، از کوکی به جای یوزرنیم و پسوردِ شما استفاده می‌شود. برخی تنظیماتِ دیگر و مواردی غیر از لوگین نیز ممکن است توسطِ کوکی‌ها نگهداری شوند)
نکته: کوکی‌ها با کاراکترِ  ; (سمی‌کالن یا نقطه‌ویرگولِ انگلیسی) از یکدیگر جدا می‌شوند.

اعمالِ قدرت در BurpSuite

حال که با نحوه‌ی نوشته‌شدنِ یک درخواستِ HTTP آشنا شدیم، می‌توانیم تغییراتِ دلخواه را روی درخواستمان انجام دهیم؛ در نهایت با کلیک روی کلیدِ کلیدِ Forward در BurpSuite می‌توانیم درخواست را به سرور بفرستیم و یا با استفاده از کلیدِ کلیدِ Drop در BurpSuite جلوی رهسپار شدنِ درخواست به سمتِ سرور را بگیریم!

در پستِ بعدی به طورِ رسمی با دیوار شروع به کار می‌کنیم و برخی درخواست‌ها را موردِ بررسی قرار می‌دهیم.

منبعز