99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python程序猿必知的新型字符串格式漏洞

發(fā)布時間:2017-02-13 13:00  回復(fù):0  查看:2120   最后回復(fù):2017-02-13 13:00  
本文對 Python開發(fā)中引入的一種格式化字符串的新型語法的安全漏洞進(jìn)行了深入的分析,并提供了相應(yīng)的安全解決方案。
  當(dāng)我們對不可信的用戶輸入使用str.format的時候,將會帶來安全隱患——對于這個問題,其實我早就知道了,但是直到今天我才真正意識到它的嚴(yán)重性。因為攻擊者可以利用它來繞過Jinja2沙盒,這會造成嚴(yán)重的信息泄露問題。同時,我在本文最后部分為str.format提供了一個新的安全版本。
  需要提醒的是,這是一個相當(dāng)嚴(yán)重的安全隱患,這里之所以撰文介紹,是因為大多數(shù)人很可能不知道它是多么容易被利用。
  核心問題
  從Python 2.6開始,Python受.NET啟發(fā)而引入了一種格式化字符串的新型語法。當(dāng)然,除了Python之外,Rust及其他一些編程語言也支持這種語法。借助于.format()方法,該語法可以應(yīng)用到字節(jié)和unicode字符串(在Python 3中,只能用于unicode字符串)上面,此外,它還能映射為更加具有可定制性的string.Formatter API。
  該語法的一個特點是,人們可以通過它確定出字符串格式的位置和關(guān)鍵字參數(shù),并且隨時可以顯式對數(shù)據(jù)項重新排序。此外,它甚至可以訪問對象的屬性和數(shù)據(jù)項——這是導(dǎo)致這里的安全問題的根本原因。
  總的來說,人們可以利用它來進(jìn)行以下事情:
  >>> 'class of {0} is {0.__class__}'.format(42)
  "class of 42 is"
  實質(zhì)上,任何能夠控制格式字符串的人都有可能訪問對象的各種內(nèi)部屬性。
  問題出在哪里?
  第一個問題是,如何控制格式字符串。可以從下列地方下手:
  1.字符串文件中不可信的翻譯器。我們很可能通過它們得手,因為許多被翻譯成多種語言的應(yīng)用程序都會用到這種新式Python字符串格式化方法,但是并非所有人都會對輸入的所有字符串進(jìn)行全面的審查。
  2.用戶暴露的配置。 由于一些系統(tǒng)用戶可以對某些行為進(jìn)行配置,而這些配置有可能以格式字符串的形式被暴露出來。需要特別提示的是,我就見過某些用戶可以通過Web應(yīng)用程序來配置通知郵件、日志消息格式或其他基本模板。
  危險等級
  如果只是向該格式字符串傳遞C解釋器對象的話,倒是不會有太大的危險,因為這樣的話,你最多會暴露一些整數(shù)類之類的東西。
  然而,一旦Python對象被傳遞給這種格式字符串的話,那就麻煩了。這是因為,能夠從Python函數(shù)暴露的東西的數(shù)量是相當(dāng)驚人的。 下面是假想的Web應(yīng)用程序的情形,這種情況下能夠泄露密鑰:
  CONFIG = {
  'SECRET_KEY': 'super secret key'
  }
  class Event(object):
  def __init__(self, id, level, message):
  self.id = id
  self.level = level
  self.message = message
  def format_event(format_string, event):
  return format_string.format(eventevent=event)
  如果用戶可以在這里注入format_string,那么他們就能發(fā)現(xiàn)下面這樣的秘密字符串:
  {event.__init__.__globals__[CONFIG][SECRET_KEY]}
  將格式化作沙箱化處理
  那么,如果需要讓其他人提供格式化字符串,那該怎么辦呢? 其實,可以利用某些未公開的內(nèi)部機(jī)制來改變字符串格式化行為。
  from string import Formatter
  from collections import Mapping
  class MagicFormatMapping(Mapping):
  """This class implements a dummy wrapper to fix a bug in the Python
  standard library for string formatting.
  See http://bugs.python.org/issue13598 for information about why
  this is necessary.
  """
  def __init__(self, args, kwargs):
  self._args = args
  self._kwargs = kwargs
  self._last_index = 0
  def __getitem__(self, key):
  if key == '':
  idx = self._last_index
  self._last_index += 1
  try:
  return self._args[idx]
  except LookupError:
  pass
  key = str(idx)
  return self._kwargs[key]
  def __iter__(self):
  return iter(self._kwargs)
  def __len__(self):
  return len(self._kwargs)
  # This is a necessary API but it's undocumented and moved around
  # between Python releases
  try:
  from _string import formatter_field_name_split
  except ImportError:
  formatter_field_name_split = lambda \
  x: x._formatter_field_name_split()
  class SafeFormatter(Formatter):
  def get_field(self, field_name, args, kwargs):
  first, rest = formatter_field_name_split(field_name)
  obj = self.get_value(first, args, kwargs)
  for is_attr, i in rest:
  if is_attr:
  obj = safe_getattr(obj, i)
  else:
  objobj = obj[i]
  return obj, first
  def safe_getattr(obj, attr):
  # Expand the logic here. For instance on 2.x you will also need
  # to disallow func_globals, on 3.x you will also need to hide
  # things like cr_frame and others. So ideally have a list of
  # objects that are entirely unsafe to access.
  if attr[:1] == '_':
  raise AttributeError(attr)
  return getattr(obj, attr)
  def safe_format(_string, *args, **kwargs):
  formatter = SafeFormatter()
  kwargs = MagicFormatMapping(args, kwargs)
  return formatter.vformat(_string, args, kwargs)
  現(xiàn)在,我們就可以使用safe_format方法來替代str.format了:
  >>> '{0.__class__}'.format(42)
  ""
  >>> safe_format('{0.__class__}', 42)
  Traceback (most recent call last):
  File "", line 1, in
  AttributeError: __class__
  小結(jié)
  在本文中,我們對Python引入的一種格式化字符串的新型語法的安全漏洞進(jìn)行了深入的分析,并提供了相應(yīng)的安全解決方案,希望對讀者能夠有所幫助。


來源:51CTO

您還未登錄,請先登錄

熱門帖子

最新帖子

?