標籤:模型 post tab 固定 流行 content 根目錄 abd 哪些
寫在前面
認識一些主流的開發架構與現在程式設計理念,包含了一些WEB設計上的趨勢與概念。另外以我自己的角度去說明一下怎麼去看一個PHP程式,方法適合於以上開源架構和一些公司內部開發的架構(只要能看到源碼)。
架構的選擇
ThinkPHP V3.2
CodeIgniter V2.2.2
Laravel V5.1
選擇以上三個架構也是以為這三個架構算是比較有代表性的!ThinkPHP(TP)在國內很受歡迎,特別是小公司。CodeIgniter(CI)是傳統且很流行的架構,並且也是很成熟的架構,據我說知sina的大多數地方站都是這個架構寫的。Laravel是一個充滿設計感的架構,應用了目前PHP上的所有新技術,並且借鑒了大量java與python的架構設計結構,也是目前調查的最流行的的Laravel架構(國內外)!
認識架構
依次排開:Laravel-> CodeIgniter(CI)->ThinkPHP(TP)
中間的CI並未包含composer.json這個檔案,這是PHP的包管理設定檔,在CI的3.0+版本中同樣加入了PHP的包管理,真的是方便了大多數程式員。這樣的目錄結構很明顯,一眼就能看出來。
架構的基本設計模式
基本的設計模式就是MVC設計模式。注意:多層級的分層模式為HMVC模式。HMVC就是把用戶端應用程式分解為有層次的父子關係的MVC。
MVC對應的檔案位置
看一個cms程式首先就是找控制器代碼在哪個位置,之後就是模型檔案的位置,視圖檔案最後,不過我真的在使用架構開發的程式中發現了模型控制碼而找到漏洞,這個程式員簡直是B了dog!
控制器
Laravel-> CodeIgniter(CI)->ThinkPHP(TP)
模型
Laravel-> CodeIgniter(CI)->ThinkPHP(TP)
資料庫連接檔案
TP:(通用2.0|3.0)
(Application)\(Home)\Conf\config.php
//(Application) 預設為Application,保不齊修改,可以直接查看index.php
//(home) 項目目錄,因項目而異!
‘DB_TYPE’ => ‘mysql’, // 資料庫類型‘DB_HOST’ => ‘localhost’, // 伺服器位址‘DB_NAME’ => ‘chopperproxyl’, // 資料庫名‘DB_USER’ => ‘root’, // 使用者名稱‘DB_PWD’ => ‘root’, // 密碼‘DB_PORT’ => 3306, // 連接埠‘DB_PREFIX’ => ‘xl_’, // 資料庫表首碼
CI:(通用2.0|3.0)
(application)\config\database.php
//一般是固定形式application,保不齊修改一樣可以到index.php裡面查看項目命名。
Laravel:(5.0|4.0的目錄少一個app)
這玩意特殊一些!在代碼目錄下有一個.env檔案,裡面存在項目的一些配置,可以在這裡設定資料庫連接資訊。(當然可以不)
另外可以直接寫在檔案中:
config\database.php檔案
//定義預設的資料庫類型
備忘:具體的配置可能是這樣兩種類型,使用env中定義,或者寫入檔案。如果設定檔中同時存在中的兩套配置,說明系統可能使用了多資料庫。
結束了!?
這是幾個架構最基本的東西了,下面把其中的關於安全的部分以及自己的一部分見解寫出來,會挺有意思的。
SQL操作模型
在PHP開發過程中,一般都會使用兩種技術。
技術一:
Active
Record(ORM)
ORM技術:Object-Relational
Mapping,把關聯式資料庫的表結構映射到對象上。
例如
ThinkPHP中:
CI中的:
二:查詢構造器方式
定義一個抽象資料庫類,包含常用的各種方式。例如:在laravel中的
注意:這兩種方式的區別簡單說就是需不需要自己去頂一個model檔案。
可能存在的SQL注入問題:
1、 由於業務的複雜性導致SQL語句有時候很變態,幾乎每種架構都支援使用原生SQL語句。
CI:
TP:
Laravel:
注意:凡是這些方式中帶入的參數未經過過濾,底層的解析都是不會進行注入處理的,都有可能造成注入。
2、 錯誤的安全函數用法(先行編譯)
TP官方方法:
如果使用3.1以上版本的話,使用字串條件的時候,建議配合預先處理機制,確保更加安全,例如:
$Model->where(“id=%d and
username=’%s’ and xx=’%f’”,array($id,$username,$xx))->select();
或者使用:
$Model->where(“id=%d and
username=’%s’ and xx=’%f’”,$id,$username,$xx)->select()
底層實現原理:擷取函數輸入參數,所有參數經過一次addslashes,然後使用vsprintf格式化字串。問題:如果在數字欄位帶入%s,且沒有引號,一樣能注入。
3、 where子查詢中key欄位可控
CI:控制器代碼
模型代碼:
針對查詢數組中的value欄位是會做處理的,但是針對key欄位並不會。
訪問查看:
Laravel:同樣的Laravel這個架構也存在這個問題。
其中$type可控一樣可以造成注入。
備忘:Thinkphp這種架構就沒有,它自己寫瞭解析where字句的方式,雖然在這點上很安全,可是曆史上出事最多的就是它了。
URL路由
一般看一個CMS就是要去找URL對應的代碼是哪些,這樣才有辦法進行審計!WEB開發過程中有一個概念是URL語義化。
傳統的URL
https://g.wen.lu/search?newwindow=1&site=&source=hp&q=URL+%E8%AF%AD%E4%B9%89%E5%8C%96&btnG=Google+%E6%90%9C%E7%B4%A2&gws_rd=cr&ei=Jli4VeX_Bciy0gSNjZvgDA
就是參數=值的形式。
做了語義化的URL
http://blog.suchasplus.com/2008/10/uri-pretty-and-url-mapping-with-apache-and-php-how-to.html
簡單解釋就是從URL上就能知道該頁面具體展示的資料或者是什麼功能,這是以後WEB開發的一個趨勢。這裡不光指這三個架構,其他架構或者自己開發的架構都將會有這樣的功能。作為一個先進的PHP架構,都是存在路由綁定這個功能的!路由綁定就是將使用者訪問URL對應到項目的具體控制器中去。(代碼審計過程中就是怎麼通過URL去訪問對應的代碼)
Laravel:
項目目錄中app\Http\routes.php
CI:
TP:
像TP這種架構,到3.2預設的URL方式還是
http://serverName/index.php/模組/控制器/操作
這種傻逼方式。但是也有路由綁定的功能。
尋找配置項
‘URL_ROUTER_ON’ => true,
然後尋找配置項
URL_ROUTE_RULES
備忘:通過這些設定項目可以快速的找到URL對應的控制器代碼是什麼!說這個還有一個原因就是以後可能會接觸到REST模式的URL,這個也是趨勢!
同一條URL可能對應不同的幾個控制器代碼。HTTP協議存在GET POST PUT DELETE方法。web程式就是增刪改查,對應的操作就是CURD,直接對應到的方法就是:
C對應POST,R對應GET,U對應PUT,D對應DELETE
具體代碼就是通過判斷要求方法來調用對應的控制器。
架構的過濾機制(審計過程需要注意的點)
一:針對URL的過濾
由於URL路由的關係,現在的架構在GET方式上都或多或少的存在過濾或者說驗證。
TP:
1、例如\d就限制了該參數只能是數字。
2、或者是使用正則的方式來匹配,達到過濾的效果。
CI:
CI的過濾也一樣,就是使用正則去匹配。
Laravel:
同樣可以在定義URL路由的時候定義過濾,直接在路由上用where函數限制參數的類型。
或者在檔案app\Providers\RouteServiceProvider.php中存在boot的函數,可以定義全域過濾,可以在這裡面找找。
二:針對接收參數的過濾
現在的架構一般都會重寫$_GET/$_POST/$_REQUEST,自建系統的輸入,然後這些輸入存在一些參數可以選擇是否過濾。
TP:
重寫的函數 I()
用法
I(‘get.id’); | I(‘post.id’);
利用設定預設值,設定過濾函數來達到過濾的效果。
I(‘get.name’,’test’,’htmlspecialchars’);
CI:
CI中所有的系統方法都是$this開頭的。重寫的輸入函數 $this->input
用法
$this->input->post(‘something’);
針對輸入的第二個參數僅針對XSS,設定成true會進過一次CI內奸的xss_clean函數。
Laravel:
這個吊了!這玩意自己定義了一個中介軟體Middleware類型(借鑒java)。中介軟體的作用就是在HTTP請求實際接觸應用程式之前,進行層層的檢查跟過濾,甚至完全拒絕。一般被用來做許可權驗證,參數過濾,資料加解密等等。所有中介軟體都在app\Http\Middleware目錄下面,根據具體情況查看是否將過濾寫在這裡面了。
重寫的輸入函數
Request $request
$request->input(‘ip’);
第二個參數僅有設定預設值的作用,並沒有實際的過濾。
三:預設設定的全域安全機制
CI:
預設還有一個參數
$config[‘global_xss_filtering’] = TRUE;
開啟後所有的參數都會經過xss_clean函數一遍。
TP:
全域的過濾參數
‘DEFAULT_FILTER’ =>’strip_tags,stripslashes’,
對接收資料進行依次的過濾。
Laravel:
預設開啟的全域CSRF過濾(借鑒django等架構)。
其他貌似就沒了0-0
由各個架構編寫過程聯想到的一些東西
1、 測試的時候如果一個正常的請求就是擷取不到資料,可以在HTTP頭裡面加上
X-Requested-With:XMLHttpRequest
就是ajax請求。現在一般程式員的編寫純api介面的時候習慣是會區分直接存取還是ajax的,這樣可以減少亂七八的資料請求。
例如:
Laravel:
CI:
TP:
常量IS_AJAX 判斷是否是AJAX提交,不寫了!
2、 如果上傳成功一個檔案,但是就是訪問不到,有幾個原因。
.htaccess 檔案限制了根目錄下index.php以外的所有檔案的存取權限,配合URL路由這個功能所有不在路由中的路徑
http://testtest.net/test/test.php
都是無法訪問的。這個也是django類似的架構難以攻擊的一個原因。(PHP正在往規範嚴謹的方向去)這種時候要麼能覆蓋route檔案,要麼能覆蓋對應的方法(這個太難,需要不破壞檔案,只是修改對應的方法。)Laravel這樣的架構本身www設定的時候就是一個public目錄(預設)。
這個目錄除了index.php檔案啥也沒有了,上傳檔案一般都在www目錄的外層目錄,無法直接存取。這種時候只能靠跳轉目錄來跳到public下面才能訪問,或者檔案包含。
關於攻擊PHP架構的幾種思路