Python ベースの Web アプリケーションのユーザー入力をサニタイズする最良の方法は何ですか? XSSまたは SQL インジェクション攻撃を防ぐために、HTML 文字とその他の必要な文字の組み合わせを削除する単一の機能はありますか?
7 に答える
以下は、ホワイト リストにないすべてのタグと、属性ホワイトリストにないすべてのタグ属性を削除するスニペットです (したがって、 は使用できませんonclick
)。
これはhttp://www.djangosnippets.org/snippets/205/の修正版であり、属性値に正規表現を使用して人々が を使用できないようにしhref="javascript:..."
、その他のケースについてはhttp://ha.ckers.org/xssで説明されています。 .html .
(例:<a href="ja	vascript:alert('hi')">
または<a href="ja vascript:alert('hi')">
など)
ご覧のとおり、(素晴らしい) BeautifulSoupライブラリを使用しています。
import re
from urlparse import urljoin
from BeautifulSoup import BeautifulSoup, Comment
def sanitizeHtml(value, base_url=None):
rjs = r'[\s]*(&#x.{1,7})?'.join(list('javascript:'))
rvb = r'[\s]*(&#x.{1,7})?'.join(list('vbscript:'))
re_scripts = re.compile('(%s)|(%s)' % (rjs, rvb), re.IGNORECASE)
validTags = 'p i strong b u a h1 h2 h3 pre br img'.split()
validAttrs = 'href src width height'.split()
urlAttrs = 'href src'.split() # Attributes which should have a URL
soup = BeautifulSoup(value)
for comment in soup.findAll(text=lambda text: isinstance(text, Comment)):
# Get rid of comments
comment.extract()
for tag in soup.findAll(True):
if tag.name not in validTags:
tag.hidden = True
attrs = tag.attrs
tag.attrs = []
for attr, val in attrs:
if attr in validAttrs:
val = re_scripts.sub('', val) # Remove scripts (vbs & js)
if attr in urlAttrs:
val = urljoin(base_url, val) # Calculate the absolute url
tag.attrs.append((attr, val))
return soup.renderContents().decode('utf8')
他の投稿者が言っているように、ほとんどすべての Python db ライブラリが SQL インジェクションを処理するので、これでほぼカバーできるはずです。
編集:bleachは、ホワイトリストベースのサニタイザーとしてさらに使いやすくするhtml5libのラッパーです。
html5lib
ホワイトリストベースの HTML サニタイザーが付属しています。サブクラス化して、ユーザーがサイトで使用できるタグと属性を制限するのは簡単です。属性の使用を許可している場合は、CSS のサニタイズも試みstyle
ます。
スタック オーバーフロー クローンのsanitize_html
ユーティリティ関数で使用しています。
http://code.google.com/p/soclone/source/browse/trunk/soclone/utils/html.py
私は、ha.ckers.org の XSS チートシート( python-markdown2を使用して Markdown から HTML への変換を実行した後、XML 形式で簡単に入手できる) にリストされているすべての攻撃を投げました。
ただし、Stackoverflow が現在使用している WMD エディター コンポーネントには問題があります。XSS Cheatsheet 攻撃をテストするために、実際には JavaScript を無効にする必要がありました。それらをすべて WMD に貼り付けると、アラート ボックスが表示され、ページが空白になってしまうからです。
XSS を防止する最善の方法は、すべてをフィルタリングしようとするのではなく、単純に HTML エンティティ エンコーディングを行うことです。たとえば、自動的に < を < に変換します。これは、HTML 入力を受け入れる必要がない場合に理想的なソリューションです (マークアップとして使用されるフォーラム/コメント領域の外では、HTML を受け入れる必要があることはほとんどありません)。代替エンコーディングを介した非常に多くの順列があるため、非常に制限的なホワイトリスト (たとえば、az、AZ、0-9) 以外は何かを通過させます。
他の意見とは反対に、クエリ文字列を構築するだけであれば、SQL インジェクションは依然として可能です。たとえば、受信パラメーターをクエリ文字列に連結するだけの場合、SQL インジェクションが発生します。これを防ぐ最善の方法はフィルタリングではなく、パラメーター化されたクエリを宗教的に使用し、ユーザー入力を決して連結しないことです。
これは、フィルタリングがまだベスト プラクティスではないということではありませんが、SQL インジェクションと XSS に関しては、パラメーター化クエリと HTML エンティティ エンコーディングを宗教的に使用すると、はるかに保護されます。
Jeff Atwood自身が、StackOverflowブログでStackOverflow.comがユーザー入力を(言語固有ではない用語で)サニタイズする方法について説明しました:https ://blog.stackoverflow.com/2008/06/safe-html-and-xss/
ただし、Justinが指摘しているように、Djangoテンプレートなどを使用すると、HTML出力がサニタイズされる可能性があります。
SQLインジェクションも問題にはなりません。Pythonのすべてのデータベースライブラリ(MySQLdb、cx_Oracleなど)は、渡されたパラメーターを常にサニタイズします。これらのライブラリは、Pythonのすべてのオブジェクトリレーショナルマッパー(Djangoモデルなど)で使用されるため、そこでのサニタイズについても心配する必要はありません。
私はもはやウェブ開発をしていませんが、やったときは次のようなことをしました:
解析が行われない場合は、通常、データを保存するときにデータベースに干渉しないようにデータをエスケープし、データベースから読み取ったすべてをエスケープして、表示するときに html に干渉しないようにします (cgi.escape() で)。パイソン)。
誰かが html 文字などを入力しようとした場合、実際にはテキストとして表示されることを望んでいる可能性があります。そうでない場合は、かなりタフです:)
要するに、データの現在のターゲットに影響を与える可能性があるものを常にエスケープします。
何らかの解析 (マークアップなど) が必要なときは、通常、その言語を html と交差しないセットに保持しようとしたため、(構文エラーを検証した後) 適切にエスケープして保存し、表示時に HTML に解析することができました。ユーザーがそこに入力したデータが html に干渉することを心配する必要があります。
HTML のエスケープも参照してください。
データベースに保存したい文字列入力 (顧客名など) をサニタイズするには、エスケープするか、引用符 (', ") を削除する必要があります。これにより、従来の SQL インジェクションを効果的に防止できます。ユーザーから渡された文字列から SQL クエリを組み立てています。
例 (引用符を完全に削除してもよい場合):
datasetName = datasetName.replace("'","").replace('"',"")
djangoのようなフレームワークを使用している場合、フレームワークは標準フィルターを使用してこれを簡単に行うことができます。実際、そうしないように言わない限り、django は自動的にそれを行うと確信しています。
それ以外の場合は、フォームからの入力を受け入れる前に、ある種の正規表現検証を使用することをお勧めします。あなたの問題に対する特効薬はないと思いますが、 re モジュールを使用すると、必要なものを構築できるはずです。