不用寄信 檢查 Email 是否 真實 存在 PHP

01

最近很常研究 Email,由於是自己架設伺服器,比較麻煩,所以更深入研究了一下下。

今天想到就寫一篇,真實檢查 Email 的方法,因為這個不是驗證 Email 格式與否,而是直接驗證 此Email是否存在,並且無須寄信即可以檢查。

首先先查詢 Email @後域名的MX紀錄,再查此IP,得到 IP 後即可透過 TCP 連線至該 SMTP 伺服器驗證以確立此 Email 確實存在,而不是亂打的。

代碼醜陋,請各位看官不要介意。

淺談Telegram開發機器人

01

我做了一個很簡單的計時器,為了某群組裡面的高中生而設計,這也是我首次製作 tg 的機器人。我才做兩個而已,所以有些功能我真的不知道的我也沒辦法為您解答。

以下是講我的經歷:

首先必須先註冊個telegram帳號(廢話),然後搜索聯繫人@BotFather  這很重要,加入這個機器人之後,首先輸入:/newbot ,然後再輸入你想要取的名子(可以是中文),接著系統會提示你再輸入用戶名稱,結尾必須是 bot ,而且僅英文以及下畫線,接著你的機器人就創立了,BotFather會告訴你,你的Token,這很重要,因為等下傳送或是接收訊息都要用到這組文字。

開始就是程式設計的部分,我個人是比較熟PHP,所以用PHP開發。而且還是改寫自官方的腳本。但我現在已經明白原理了。

程式碼都獻上了,現在開始講原理。

首先必須要有一台服務器,來執行WebHook,把你寫好的PHP檔案上傳到伺服器上面,注意檔名最好建立很特殊的名稱,讓一般使用者無法猜到你用什麼檔名,以預防惡意人士直接訪問你的程式。(洪水轟炸,或偽造請求之類的。)

上傳後,請直接訪問 https://api.telegram.org/botTOKEN/?method=setWebhook&url=https://www.example.com/secretbot.php

參數url後面接的就是你要接收的位置,僅支援https,完畢後一旦直接對bot講話輸入指令,telegram就會立刻送出對話內容傳到你的程式,而你的程式處理完之後再回傳給telegram,這就是它的工作原理。

得到的內容長得像:

簡單明瞭,這只是message的部分,有可能會出現其他資料,例如傳圖片,有人加入群組時,就會不同了,請參閱 telegram 文檔,https://core.telegram.org/bots/api

而我的設計是當使用者輸入 /start 時,就會回傳 聊天室 id,因為我需要 id 才可以讓我直接發訊息回去,否則必須每次都是被動型傳輸,這樣我就可以主動傳送了,因為我不需要依靠對方先傳訊息給我才可以取得 id 回傳。

而我設定輸入指令 /show 時 就會彈出距離目標時間還有多久。而且利用 cron job 定時任務,每天都會 run 這程式發送一次倒數訊息。這就是整個簡單的概念。

接下來,在 tg 上就可以直接操作並直接顯示結果了,唯一缺陷就是沒有指令選單。這時可以再向 BotFather設定,輸入 /setcommands,再輸入 @botname指令(英文)+空格+簡介。(可以多行輸入)

最終預防機器人被濫用亂加入群組,可以設定鎖定,/setjoingroups@botname → Disable

這樣就大功告成了。其他功能自己探索,其實很簡單的。

PHP 利用 cUrl 抓取 HTTPS/HTTP 網頁

最近不知道要發什麼,這篇這是純當筆記用。

 

基本程式語法整理 Python, PHP, JS, Java, C#, C, C++

最近學C、C++,想一塊學,因為大學程式的緣故,我想,我還是先修好了,練習演算法,順便複習以前的程式。我已經語法大混亂了,沒有編譯器糾正我,基本很難寫正確程式,除非最近都在攻某個專案,否則我平時都是一天寫好幾種不同語言的程式,函數偶爾會亂調用。我知道有些工程師很討厭什麼語言都碰一點的人,但,我不管啦,我就是什麼都學,反正最後我也只會主攻少數幾項,也不至於什麼語言都很淺。

PythonPHPJS 
if state:
    #do sth
elif state:
   
#do sth
else:
    #do sth
if(state){
   
//do sth
}elseif(state){
    //do sth
}else{
   
//do sth
}
if(state){
    //do sth
}else
if(state){
    //do sth
}else{
   
//do sth
}
 
for x in range(0,10):
    #do sth
for($i=0;$i<10;$i++){
    //do sth
}
for(var i=0;i<10;i++){
    //do sth
}
 
for k in arr:
    #do sth
foreach ($arr as
$value) {
   //do sth
}
for(var key in arr){
   
//value=arr[key];
}
 
Not Existswitch($mod){
    case 1:
      
//do sth
    break;
    case 2:
      
//do sth
    break;
    default:
      
//do sth
}
switch(mod){
    case 1:
      
//do sth
    break;
    case 2:
      
//do sth
    break;
    default:
      
//do sth
}
 
def foo(v1,v2):
    return sth
function
foo($v1,$v2){
    return sth;
}

//call by
reference

function foo(&$v1,&$v2){
    return
sth;
}

function foo(v1,v2){
    return sth;
}
 
JavaC#CC++
if(state){
    //do sth
}else if(state){
   
//do sth
}else{
    //do sth
}
if(state){
    //do sth
}else if(state){
   
//do sth
}else{
    //do sth
}
if(state){
    //do sth
}else if(state){
   
//do sth
}else{
    //do sth
}
if(state){
    //do sth
}else if(state){
   
//do sth
}else{
    //do sth
}
for(int i=0;i<10;i++){
    //do sth
}
for(int i=0;i<10;i++){
    //do sth
}
for(i=0;i<10;i++){
    //do sth
}
for(i=0;i<10;i++){
    //do sth
}
for(int k : arr){
    //do sth
}
foreach (int k in arr){
    //do sth
}
Not
Exist
for(int k : arr){
    //do sth
}
switch(mod){
    case 1:
      
//do sth
    break;
    case 2:
      
//do sth
    break;
    default:
      
//do sth
}
switch(mod){
    case 1:
      
//do sth
    break;
    case 2:
      
//do sth
    break;
    default:
      
//do sth
}
switch(mod){
    case 1:
      
//do sth
    break;
    case 2:
      
//do sth
    break;
    default:
      
//do sth
}
switch(mod){
    case 1:
      
//do sth
    break;
    case 2:
      
//do sth
    break;
    default:
      
//do sth
}
public int foo(int v1, int v2){
    return sth;
}
public int foo(int v1, int v2){
   
return sth;
}

//call by reference

public int foo(ref
int v1, ref int v2){
    return sth;
}

foo(ref a,ref b);

public int foo(out int v1, out int v2){
   
return sth;
}

foo(out a,out b);

int foo(int v1, int
v2){
    return sth;
}

//call by reference

int foo(int *v1, int *v2){
    //調用引數都要加*
   
return sth;
}

foo(&a,&b);

int foo(int v1, int v2){
   
return sth;
}

//call by reference

int foo(int &v1, int
&v2){
    return sth;
}

foo(a,b);

//call by pointer

int foo(int *v1, int *v2){
   
//調用所有引數都要加*
    return sth;
}

foo(&a,&b);

PHP string to html characters 字串轉HTML碼

緣由:
最近因為裝了PHP7的緣故,又加上有一點點的閒,故研究PHP這塊。尤其是運算耗時方面,因為我本身就是要測試PHP7可以快到何種地步。聽說是快20倍的樣子。

結果,到最後我反而開始寫程式碼,昨天修正BBcode檢查的函數,運行約一萬字的代碼,結果速度慢到極致,被我修改後,倒加速不少,總速度提升82倍,原本12.3秒,修正到0.15秒(如果僅比較檢查BBcode的函數,加快上萬倍。),後來遇上了這個轉HTMLcode的問題,原先寫得太慢了,這是我第三次修正!

 

程式設計缺陷足以修改Header偽造IP

這其實是個老梗,很久以前就知道了。今天又突然想到,發篇文章好了。

很多網站上的程式教學都是錯誤的,取得IP方法用get Header 的 Client-IP 及 X-Forwarded-For

真的是禍害,Header是可以給用戶隨意變更的。

我修改了 Header 在網站上隨意搜尋 What is my ip ?。

1

結果大部分網站都有問題!

2
4

3

我怎麼改,網站就怎麼顯示,怎麼都對。如果今天我把Header改成<script>標籤,不就造成了XSS攻擊漏洞?改成SQL語法,造成SQL注入漏洞。

5

6

只是剛好想到,之前也沒發過類似的文章,補發。

淺談 – 資安 – 表單防禦

閒閒沒事在Google搜尋我自己部落相關的關鍵字,想看看能見度多高還有會顯示什麼東西,我搜尋表單攻擊,卻看到別人部落上寫了一篇表單安全性的文章,突然有感而發,我也來發表這類的東西。

–只是個人淺見,若有高手歡迎指正。–

首先撰寫表單堅持一些要點就不容易被攻擊。

一、過濾所有Request變數。

最基本的防禦XSS,那些JavaScript寫成的惡意程式碼,還有跨站框架……等等攻擊。最主要只要擋掉「HTML」標籤就可以了,問題是,萬一我要開放HTML給使用者使用,這下才是真的麻煩,如果真如此就只好開放BBcode囉。千萬不要直接允許用戶輸入HTML,即使是限制也是有問題的。

攻擊者可以利用事件 onClick、onError、onLoad 之類的方式觸發XSS攻擊。危險。

Replace掉所有「<」、「>」、單雙引號,就安全了嗎?Maybe,Maybe Not。

有些人就直接 Replace 掉 <script ,感覺上很對,實際上有很大的漏洞。

如果我寫 「<script<scr<scriptipt>」被過濾掉一次之後會變為「<script>」,像這種清除字串,最好寫一個 while true ,刪乾淨,搜尋到就刪,直到沒搜尋到為止。(萬不得已才這樣做)

個人建議全部改用 HTML 編碼,全面HTML編碼(HTML編碼就是 &#Unicode; 的形式的字串),若有引數是在資料庫語句的話就請不要用 XXX=XXX 的形式(數字型態),全部改用 XXX=”XXX” 之類的,一定要有引號框住。並且過濾掉所有單雙引號<>以及反斜線。

至於傳進變數的方式,建議通通改成 POST ,不要使用 GET ,除非分頁設計還是什麼的,不然絕對沒必要使用 GET ,很危險。這有牽扯到某些伺服器的有啟用magic quotes,會自動脫逸引號字元,所以用POST會較為安全一些。而且POST,攻擊者比較不好攻擊。

還有COOKIE、Header 傳進來的 也建議 過濾掉。

二、不使用cookie、鎖定session以及IP。

又要再次重申 cookie 的危險程度,我幾乎寫程式只用 session 完全不使用 cookie,我知道session 有所謂的 SESSION_id 是透過 cookie 所存,所以攻擊者只要獲取其他人的 session ID,即可使用 cookie 欺騙 就這樣簡單的取得他人的帳號權限。

網路上有一堆防禦方法是 透過IP UserAgent 算出來的 MD5 作為安全碼,只要進來的安全碼和之前不同就登出用戶,是一個很棒的方式,不過很麻煩。這對登入表單有一些效果,如果是留言表單,我故意關閉cookie,讓server的session id 跳錯,這樣就很有可能可以直接不經過驗證碼就可以留言(前提是對方沒有檢查session驗證碼的值是否為空)。

我的作法是強制鎖定 session ID 為 IP 的 md5 值,這樣也許會有點不方便,不過我覺得這樣反而好一點,不需要擔心什麼 session 挾持,或是 對方換一個新的 ID 進來,明明被 ban 15分鐘又可以繼續留言。

三、防止表單偽造、防止惡意灌水

什麼是表單偽造,表單傳入的值可以直接當成 name=value&name2=value2 … 無限延伸,檢查也是檢查值,很多後端程式 根本不管從哪來 Request 進來的,這給攻擊者很大的方便,只要複製一分一模一樣的表單,就可以無限偽造一堆請求過去。

有些會透過 Header 的 Referer 來檢查 轉介站,不過 Header 也是可以偽造的。

所以,最好是在 表單一訪問的情況 就立刻生成一個 Key ,當值傳到後端處理的時候,就檢查那個 Key 有沒有相同,不同就是表單偽造,然後每次通過驗證就銷毀 Key重新生成一個新的,而攻擊者為了取得Key,必須一直不斷的向 「原始」 表單請求 ,獲取裡面的 Key 才可以發送資料。

這原理跟驗證碼有點相似,現在很多網站都有圖形驗證碼了。不過一樣也有一些是沒有驗證碼的,驗證碼是一定要有的!不然會被惡意攻擊,

而那些使用 「文字」驗證碼的人,自以為很安全,其實很危險。我近期開發出來的表單攻擊程式就可以破解文字驗證碼!即使是要經過數學運算的也是一樣可以破解。

意味著我可以提交完就訪問原始網站,分析驗證碼,又提交,又訪問原始網站,分析驗證碼,又提交……

唯有圖形驗證碼才可以防禦此類攻擊。文字驗證碼根本不可靠。

PHP/VB__ASCII轉換器

關於這點,真的是有夠麻煩的,我經常寫php,php通常UTF-8的網頁都是 “一個中文字”
轉成三個Ascii碼,現在才開始研究,到底要怎樣才可以像 VB 一樣 轉成 5位數的代碼。
又或者 VB 轉成 UTF-8形式的 3 個 ASCII。

好吧,結果出來了。

Unicode 介於 2048(800) ~ 65535(ffff) 之間:
套用形式:
1110****
10******
10******

比如:「我」,Unicode 為 25105 (6211),介於上述的情況。
所以:轉成 2進位 110001000010001
切成 三等分,第一等分 四位數,第二等分 六位數,第三等份六位數。不足則補0。
所以變成 0110001000010001,切割後變成:
0110
001000
010001
套進去變成
11100110
10001000
10010001
轉回 10 進位:
230
136
145
形成 UTF8形式的 三個ASCII碼。

另外,介於 128(80) ~ 2047(7ff) 間 則是另一個形式。
110*****
10******

大概就這樣。
有夠複雜的。

其實網頁 也可以 直譯 ASCII碼。
&#65;&#66;&#67;
ABC

&#36889;&#26159;&#28204;&#35430;
這是測試

我自己本身也寫了 PHP函數 轉 成 像 VB那樣的UTF16

再次更新,這個PHP代碼速度更快。

又寫了等價VB的ChrW於PHP版。