久久久久av_欧美日韩一区二区在线_国产精品三区四区_日韩中字在线

返回列表 發(fā)帖
查看: 9996|回復(fù): 4

Discuz!基礎(chǔ)的代碼安全和代碼規(guī)范

83

主題

-6

回帖

329

積分

爐火純青

貢獻
2 點
金幣
241 個
樓主
發(fā)表于 2019-6-3 13:24:08 | 只看樓主 |倒序瀏覽 |閱讀模式

變量
所有漏洞都來源于變量,因此變量首先要做的就是定義初始化。用任何一個變量前一定要先定義,初始化它
雖然現(xiàn)在Discuz!X來說,GPC不會被全局覆蓋了,但是大家寫插件的過程中也不要忽視了
因為在服務(wù)器php.ini的配置中 global on 時
所有的GET POST 都會變成變量
$_GET['xxx']  如果存在
就會變成 $xxx 而產(chǎn)生在程序里
因此,你自己要用的變量,一定要初始化

第一點,變量的初始化
無論你要怎么利用變量,一定要初始化
不管是Discuz!還是Discuz!X
由于PHP的歷史原因
你不能相信任何一個服務(wù)器
只因為php有個global on 的參數(shù)
他會讓GPC變量直接變成全局變量
因此,你自己的變量一定要初始化

第二點,認清變量的類型
整剛才說到,變量一定要初始化,那么初始化成什么類型
如果你要用于數(shù)組

初始化$a = array();
字串 $a ='';
數(shù)字 $a = 0

這樣子,這里說說數(shù)組,這里又存在一個php歷史問題,這歷史延續(xù)至今。

$s = '123456';
echo $s[2];
等于什么?

[]大家都知,這是數(shù)組的用法,但php太自由了 $s[3] 的數(shù)組用法,竟然可以用在字串里,這個在大家認為很自然。
但是,很多漏洞會從此誕生,這就是認清自己的變量類型的道理所在。
$s[1] 是數(shù)組的用法,可以用在字串中,但是我不推薦大家用,黑客會這么用在GET中更改你的變量類型。

舉例
echo $s[2];
簡單這一句,你認為這是輸出數(shù)組的一個項,還是字串?
大多數(shù)人會認為這明顯是輸出數(shù)組的一個項目,但是剛才也看到了,它輸出字串的一個字節(jié)也可以。
那,我們反過來思考,如果程序的某邏輯需要輸出字串的某字節(jié),但是,如果你沒明確告知變量類型。那么有可能會讓這一個字節(jié)變成一個字串 xxx.php?s[2]=hello

初始化+認清自己的變量類型
特別是數(shù)組和字串,如果你要取字串的某一位,安全的方法,可能還是 substr($s, 2, 1)
切忌[]的用法,一定要$a = array() 不要讓他和字串類型的變量產(chǎn)生互用理中

第三點、不要相信任何一個即將入庫的變量
進很多SQL注入都是從變量開始,要仔細看每一個SQL語句中可能出現(xiàn)的變量,如,整數(shù)一定要intval;字串一定要addslashes處理,說到addslashes,說說Discuz!的特點,國外某些論壇是,所有變量都無需addslashes,addslashes只在SQL數(shù)據(jù)庫類中統(tǒng)一處理,但Discuz!不是,Discuz!會統(tǒng)一給GPC變量自動addslashes。

注意,是只給GPC變量加addslashes,其他的都沒加。所以,你要注意兩件事:
1. GPC變量你想用于顯示?
那么別忘記stripslashes 后在顯示,否則萬一遇到有帶有 ' 的,那就會多一個\,I'm 變成 I\'m
htmlspecial只處理<>這些,和單引號無關(guān)

2. 再次,剛才說過DZ只處理GPC。因此,GPC之外的所有變量一定要自己addslashes,特別是有些時候時,把A庫的東西讀出來后,直接復(fù)制到B庫的情況。有人說A庫的東西都入進去了,直接入B庫還不安全嗎?這可不一定,I'm 被A讀取出來后 直接入B庫,肯定是sql error,必須addslashes。如果要 serialize ,那么 serialize前無需addslashes,serialize后要,從數(shù)據(jù)庫中去出來的肯定是I'm,不是I'\m,serialize是好東西,但不要把addslashes后的也給serialize進去。

那么,我再繼續(xù)深一步,剛才說到了數(shù)據(jù)庫。
我們保證了入庫前的所有變量必須是addslashes,但是,如果你不做下面的一件事。那么你再addslashes也是白搭
哪件事呢?
select * from table where id=$id
select * from table where id=I\'m
看,依然sql錯誤,而且還被注入

我舉例子
沒錯,單引號封閉,無論你是什么類型的字段
在Discuz!的規(guī)范里,必須都加單引號
select * from table where id='$id'
WHERE后面的所有條件
變量必須加單引號,這是規(guī)范。也許你少加一個,并不會產(chǎn)生漏洞,也只是也許。

但,有些隱形的漏洞就是在七拐八拐中產(chǎn)生的。你少寫一個,那些黑客就會用七拐八拐的方式去分析,看看可否利用行中。
intval是必須的,規(guī)則也是必須遵守的,然后是html的問題,不要漏掉任何一個字串類型。
所有字串類型,如果你不希望他們顯示html,入庫前一定要htmlspecialchars后再入庫,或者strip_tags下

數(shù)字類型
大家都知道intval,字串是htmlspecialchars,當(dāng)然,后臺無所謂!后臺比較安全,但是,最好也有,一個習(xí)慣,僅作參考。

$a = '12345';
$a_en = htmlspecialchars($a)
$a_ad = addslashes($a);

這樣,入庫的時候sql查詢語句里應(yīng)該都是_ad結(jié)尾的
html模版中的應(yīng)該都是_en結(jié)尾的
我說不出很多黑客的那些漏洞屬于
但是剛才說的那些如果都做到了,代碼安全不成問題

然后說說Discuz!內(nèi)置的一些變量

Discuz!X中,理論上你要用 $_G ($_G['gp_*'] 除外) 里的變量,都要考慮htmlspecialchars和addslashes
$_G['gp_*'] 是DX里的GPC
GP
GET POST 都經(jīng)過了 addslashes后存放到了$_G['gp_*]中
但_G中的其他,均沒addslashes
GPC都addslashes過
dhtmlspecialchars 支持?jǐn)?shù)組
其他同理
如果你有一個良好的代碼規(guī)范,也會讓代碼安全性提高
很多規(guī)范大家可以給自己定,像剛才的$a_en $a_ad

第四點,下面簡單說說代碼規(guī)范
大家閱讀代碼的時候也許都看到了
$a = 1;
賦值語句前后空格
if(.........
if后面沒空格,這些細節(jié)涉及不到安全,但有一點,這些也有安全影響?

SQL
良好的代碼規(guī)范可增加自己的可讀性
DB::query("UPDATE ".DB::table('common_member_count')." set $giftunit = $remaining where uid = $_G[uid]");

Discuz!規(guī)定sql語句中的SQL關(guān)鍵詞必須大寫
DB::query("UPDATE ".DB::table('common_member_count')." SET $giftunit='$remaining' WHERE uid='$_G[uid]'");
修正過的

$giftunit = $remaining
沒引號,而且大小寫不明,閱讀起來很累,規(guī)范的不規(guī)范的寫在一起
雖然站長,不會看代碼。但是,一個漂亮代碼文檔,就像一篇好作文。

有一個SQL上的細節(jié) notifications=notifications+1
這種SQL語句,理論上我們不推薦,雖然這么寫本身是正確的
如果a字段是unsigned類型,那么會產(chǎn)生數(shù)暴增
產(chǎn)生溢出

a=a+'-1'
就不會

mysql好奇怪的
這點大家通過pma試試就知道了

插件如有減分操作的時候
當(dāng)a=0的時候
1、a=a-1
2、a=a+'-1'
3、a=a+(-1)
三種方法,你看哪個ok

下面說最后一點
涉及安全的,代碼的流程,你的程序,如果只在你的流程下運作
允許100、1000次也許都不會出錯。但是,在別人那里,不一定

舉例
foreach($array as $k => $v)
嗯,$array是數(shù)組,并且存在的時候。。。

沒錯,是,你自己調(diào)試的時候,這數(shù)組肯定有
但是在用戶那里,有可能就沒了
這時候,這語句有錯

如果$array不是數(shù)組的情況下,這句就錯了
你可以if(is_array($array))
也可以(array)$array

類似影響流程的不僅僅是foreach
如rawurlencode
echo rawurlencode('sss');
誰都知沒問題
但!!回到剛才我曾說過的,認清變量類型
echo rawurlencode(array('11'));

肯定出錯,大家可以測試下
因此 rawurlencode($s) 的時候
一定要確保$s是字串還是數(shù)組

用php的每一個函數(shù)的時候都要看清接受參數(shù)的類型
如果是字串,切記剛才說的
php很傻,有時候字串、數(shù)組不分
這是最后一點,爆路徑,爆路徑后能干啥,黑客最清楚
回復(fù)

使用道具 舉報

15

主題

1796

回帖

2076

積分

應(yīng)用開發(fā)者

discuz 老兵

貢獻
10 點
金幣
188 個
QQ
沙發(fā)
發(fā)表于 2019-6-7 23:01:14 | 只看Ta
收藏了~~  下次開發(fā)插件前注重以下
回復(fù)

使用道具 舉報

3

主題

121

回帖

188

積分

應(yīng)用開發(fā)者

貢獻
0 點
金幣
58 個
板凳
發(fā)表于 2019-6-9 08:38:28 | 只看Ta
感謝分享,
回復(fù)

使用道具 舉報

0

主題

4

回帖

8

積分

初學(xué)乍練

貢獻
0 點
金幣
4 個
地板
發(fā)表于 2019-8-9 10:38:27 | 只看Ta
本帖最后由 ssbaoer89 于 2019-8-9 10:40 編輯

機會是留給
回復(fù)

使用道具 舉報

12

主題

87

回帖

220

積分

應(yīng)用開發(fā)者

貢獻
1 點
金幣
71 個
5#
發(fā)表于 2019-8-9 11:56:12 | 只看Ta
還有很多歷史原因遺留的嚴(yán)重BUG,
php的正則匹配中小數(shù)點.即使你后面沒有加/s也是包括\r這個換行符的(網(wǎng)絡(luò)上所有的教程說法都是錯誤誤導(dǎo)的),

還有PHP_EOL這個常量千萬不能用,因為它在windows下等同于\r\n,linux下等同于\n, 比如現(xiàn)在是windows寫入和讀取后分割都是用\r\n確實沒有問題, 但如果你以后服務(wù)器換到了linux的話分割用PHP_EOL \n那么以前在windows時寫入的數(shù)據(jù)分割后后面全部會平白無故多一個\r出來,長度完全就不對了
回復(fù) 1

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

  • 關(guān)注公眾號
  • 有償服務(wù)微信
  • 有償服務(wù)QQ

手機版|小黑屋|Discuz! 官方交流社區(qū) ( 皖I(lǐng)CP備16010102號 |皖公網(wǎng)安備34010302002376號 )|網(wǎng)站地圖|star

GMT+8, 2025-7-1 15:42 , Processed in 0.064524 second(s), 20 queries , Redis On.

Powered by Discuz! W1.0 Licensed

Cpoyright © 2001-2025 Discuz! Team.

關(guān)燈 在本版發(fā)帖
有償服務(wù)QQ
有償服務(wù)微信
返回頂部
快速回復(fù) 返回頂部 返回列表