下面的代码是关于Python + Django + PostgreSQL的。 但也许问题仅限于psycopg2行为。
我正在研究网络安全性,即SQL注入。仅限学习目的。
这是世界样本数据库(http://pgfoundry.org/frs/?group_id=1000150&release_id=366#world-world-1.0-title-content)。
我发明了这些SQL注入:
1'; drop table city cascade;select 1 where 'me'='me
1'; drop owned by admin;select 1 where 'me'='me
我处于调试模式,所以我可以看到错误(如果有的话)。 嗯,这些注射不会产生任何错误。
但桌子仍然存在。
我可以在psql中执行这些命令:
world=# drop owned by admin;
DROP OWNED
world=# \dt
No relations found.
问题:您能否帮我理解为什么我的SQL注射不会产生相同的结果?
world =#\ dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+-------
public | city | table | admin
public | country | table | admin
public | countrylanguage | table | admin
world =#\ d + city
Table "public.city"
Column | Type | Modifiers | Storage | Stats target | Description
-------------+--------------+-----------+----------+--------------+-------------
id | integer | not null | plain | |
name | text | not null | extended | |
countrycode | character(3) | not null | extended | |
district | text | not null | extended | |
population | integer | not null | plain | |
views.py
class FormView(View):
def get(self, request):
return render(request,
"home/city.html")
def post(self, request):
city = request.POST.get("city")
try:
conn = psycopg2.connect(dbname='world', user='admin', password='password')
except psycopg2.OperationalError:
print("Unable to connect to db!")
exit();
cur = conn.cursor()
select = "select countrycode, district from city where name='{}'".format(city)
cur.execute(select);
selection = cur.fetchall()
return render(request,
"home/city.html",
context={'city': city, 'selection': selection})
city.html
{% extends 'base.html' %}
{% block content %}
<h2>City</h2>
<form method="post">
{% csrf_token %}
<input name="city">
<button>Submit</button>
</form>
<h2>Country code and district for {{ city }}:</h2>
<ul>
{% for row in selection %}
<li>{{ row.0 }} {{ row.1 }}</li>
{% empty %}
<p>Nothing so far.</p>
{% endfor %}
</ul>
{% endblock %}
答案 0 :(得分:0)
conn.commit()缺席。
参考http://initd.org/psycopg/docs/usage.html
因此,如果仅选择丢弃表似乎几乎不可能。
但是如果我们执行类似&#34;插入城市...&#34;之类的东西,那么我们必须使用conn.commit(),在这里我们可以通过SQL注入删除表。