php安全編程&python測試實例編寫

前言php

本文首發i春秋論壇。
html

本篇文章主要分享一個python暴破腳本,該腳本採用optparse模塊,支持自定義字典位置;用了多線程(雖然我感受和單線程速度差很少。。是個人錯覺仍是線程寫的不對。。求表哥們指教)。

1、PHP安全編程
這篇文章暴破的目標是本身寫的一個簡單demo,php寫的,用了PDO預編譯預防SQLI,用了htmlspecialchars簡單防護xss,源碼放出來:
數據庫配置文件(dbname:pybp;table:pybp_table;column:username,passwd)Con_self.php:
    <?php  
    $pdo = new PDO('mysql:host=localhost;dbname=pybp', 'root', 'root');  
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    $pdo->exec("set names 'utf8'");  
    ?>  

 



登陸處文件login_self.php:
    <?php  
    include('con_self.php');  
    ?>  
    <form action='' method='POST' name='form1'>  
    user:  <input type='text' name='username'><br>  
    passwd:<input type='text' name='passwd'><br>  
    <input type='submit' value='login' name='login'>  
    <input type='submit' value='add' name='add'>  
    </form>  
    <?php  
    if(isset($_POST['add'])){  
        $username = htmlspecialchars($_POST['username']);  
        $passwd = htmlspecialchars($_POST['passwd']);  
        $sm = $pdo->prepare("insert into pybp_table(username,passwd) values(?,?)");  
        $sm->execute(array($username,md5($passwd)));  
    }  
    if(isset($_POST['login'])){  
        $username = htmlspecialchars($_POST['username']);  
        $passwd = htmlspecialchars($_POST['passwd']);  
        $smt = $pdo->prepare("select * from pybp_table");  
        $smt->execute(array());  
        $result = $smt->fetchAll();  
        if($username===$result[0]['username']&&md5($passwd)===$result[0]['passwd']){  
            header("Location:/pybp_pdo/welcome_self.php"."?user=".$username);  
        }  
        else{  
            echo 'login fail';  
        }  
    }  
    ?>  

 



以及登陸認證成功後跳轉的welcome.php:        
    <html>  
    <p>welcome <?php echo $_GET['user'];?></p>  
    <html>  

 


有關於csrf防護,參見http://bbs.ichunqiu.com/thread-15186-1-1.html,就不贅述了。
Ok,看看界面:


而後我們就試試爆破這個登錄界面了

2、python登錄暴破
py腳本原版先放出來:
    #coding: utf-8  
    #author: xiaoye  
    import requests  
       
    if __name__ == '__main__':  
        data = {}  
        headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0'}  
        url = 'http://localhost/pybp_pdo/login_self.php'  
        #data = {'username':'admin','passwd':'admin','login':'login'}  
        userlist = [x.strip('\n') for x in open('pybp_self_user.txt').readlines()]  
        #print userlist  
        passwdlist = [x.strip('\n') for x in open('pybp_self_passwd.txt').readlines()]  
        #print passwdlist  
        for user in userlist:  
            for passwd in passwdlist:  
                data['username'] = user  
                data['passwd'] = passwd  
                data['login'] = 'login'  
                print data  
                r = requests.post(url,data=data,headers=headers)  
                if r.status_code == 200:  
                    if r.content.find('welcome') != -1:  
                        print 'user:%s, passwd:%s' % (user,passwd)  
                        exit(0)  
                data.clear()  

 


運行截圖:



整個程序用列表生成式,獲取了user 、passwd兩個字典的所有內容,而且將它們組合爲dict形式,用requests.post去一一模擬登錄,並從返回的頁面源碼中提取響應的關鍵字來判斷是否已經登錄成功。

基本的思想就是這樣,可是前面的這個程序很死,連字典位置都不能自定義,速度有點慢(這個其實正常,兩個只含有10個詞字典,10*10的話,就要爆破100次,並且requests的速度還受網絡的限制)

改善版:

optparse自定義字典位置(多線程出了點問題,我改完後放出來):
    #coding: utf-8  
    #author: xiaoye  
    import requests  
    from optparse import OptionParser  
       
    if __name__ == '__main__':  
        parse = OptionParser()  
        parse.add_option('-u','--u',dest='userfile',type='string',help='specify user file')  
        parse.add_option('-p','--p',dest='passfile',type='string',help='specify passwd file')  
        option,args = parse.parse_args()  
        data = {}  
        headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0'}  
        url = 'http://localhost/pybp_pdo/login_self.php'  
        #data = {'username':'admin','passwd':'admin','login':'login'}  
        userlist = [x.strip('\n') for x in open(option.userfile).readlines()]  
        #print userlist  
        passwdlist = [x.strip('\n') for x in open(option.passfile).readlines()]  
        #print passwdlist  
        for user in userlist:  
            for passwd in passwdlist:  
                data['username'] = user  
                data['passwd'] = passwd  
                data['login'] = 'login'  
                print data  
                r = requests.post(url,data=data,headers=headers)  
                if r.status_code == 200:  
                    if r.content.find('welcome') != -1:  
                        print 'user:%s, passwd:%s' % (user,passwd)  
                        exit(0)  
                data.clear()  

 


看運行gif:



Optparse模塊仍是挺好用的,命令行參數用着方便些

關於爆破,有個坑得說一說,驗證碼
關於驗證碼識別,我經常使用的是tesseract-ocr,效果還行吧,對中文的識別比較蛋疼。。。。。。
從csdn截了個驗證碼,試試看效果:



效果還能夠
對於python這種輪子衆多的語言來說,也有本身處理驗證碼的模塊,pytesseract (依賴於tesseract&&PIL)
用法以下:
#coding: utf-8  
import pytesseract  
import PIL  
image = PIL.Image.open('v2code.png')  
v = pytesseract.image_to_string(image)  
print v 

 


效果:



碰見有驗證碼的登錄窗口,咱們能夠向上面的小程序用python作簡單處理

3、小彩蛋
此次小彩蛋挺有意思的,介紹了python selenium,有關於selenium,光是安裝就是個大坑,能夠試着去踩踩~。。。。。。tips:selenium 啓動不了太高版本firefox,要安裝引擎文件;默認selenium操做firefox會打開一個初始的,沒有任何插件的火狐瀏覽器,這時候能夠指明firefox profile,啓動咱們平常用的瀏覽器(安裝一下就知道我說的意思了。。)

代碼:(自動化打開firefox,打開csdn登錄界面,自動化輸入用戶名/密碼登錄)
截圖工具崩了。。借個網上的圖來看看狀況http://img.blog.csdn.net/20150821031951877
下面代碼運行狀況和這個狀況差很少,全程是不須要人手工點擊的,自動化完成,自動化登陸csdn源碼以下:
    from selenium import webdriver   
    from selenium.webdriver.common.keys import Keys   
    import time   
    import re  
         
    profile_dir = r"C:\Users\xiaoye\AppData\Roaming\Mozilla\Firefox\Profiles\3xhizvy7.default"  
    profile = webdriver.FirefoxProfile(profile_dir)  
    driver = webdriver.Firefox(profile)   
    driver.get("https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn")   
    elem_user = driver.find_element_by_name("username")   
    elem_user.send_keys("your username")  
    elem_pwd = driver.find_element_by_name("password")   
    time.sleep(2)  
    elem_pwd.send_keys("your passwd")   
    elem_pwd.send_keys(Keys.RETURN)   
    time.sleep(5)   
    assert "baidu" in driver.title   
    driver.close()   
    driver.quit()    

 


其中,profile_dir是火狐的配置文件地址,每一個人都不同
your username是你的用戶名,passwd是你的密碼
運行以後,就自動化操做了
爲啥python爆破會講到這個呢?。。自動化能不能爆破呢?固然能夠,下次有時間試試吧
Selenium常常應用在自動化測試以及爬蟲上,普通靜態頁面抓取通常只須要三個模塊:re正則模塊  bs4解析模塊 requests請求模塊;可是對於像ajax動態生成的頁面,selenium是個不錯的選擇。
相關文章
相關標籤/搜索