python使用pg数据sql注入分析
内容
审计python使用psycopg2库操作pg数据库中的sql注入
sql注入出现原因
总结有3个原因
1 对外接口中有不可信的数据输入
2 未对输入的数据进行安全性校验(白名单,转义等其他限制)
3 操作数据库时使用函数的方法不对
审计python代码
直接对查数据库拼接字符串和查询方法进行审计
tip1:对输入数据直接拼接后查询
def database():
injectdata = "1"
xcmd= "select * from user where id = " + injectdata #psycopg2库未对数据校验,传入什么参数,execute方法就会执行什么
conn = psycopg2.connect(database="test", user="post", password=passwd, host=ip, port="5432")
cur = conn.cursor()
cur.execute(xcmd)
res = cur.fetchall()
conn.commit()
conn.close()
拼接注入语法:
1 injectdata = “1 and 1=1” 或者 injectdata = “1 or id =2” #查询成功
2 injectdata = " 1’ or id =‘2’ " #查询报错(有安全校验)#log(psycopg2.ProgrammingError: unterminated quoted string at or near “’”
3 injectdata = ‘1;select user’ #查询成功,显示当前用户
4 injectdata = ‘1;select pg_sleep(5)’ #查询成功
说明:"select * from user where id = " + injectdata 这中直接拼接的代码写法对sql注入基本没有安全校验
tip2:对输入数据进行格式化后查询数据库
def database():
injectdata = "1"
xcmd= "select * from user where id = %s"%injectdata #格式化处理
conn = psycopg2.connect(database="test", user="post", password=passwd, host=ip, port="5432")
cur = conn.cursor()
cur.execute(xcmd)
res = cur.fetchall()
conn.commit()
conn.close()
注入语法验证:
1 injectdata = “1 and 1=1” 或者 injectdata = “1 or id =2” #查询成功
2 injectdata = " 1’ " #查询报错(有安全校验)#log(psycopg2.ProgrammingError: unterminated quoted string at or near “’”
3 injectdata = ‘1;select version()’ #查询成功,有版本号返回
4 injectdata = ‘1;select pg_sleep(5)’ #基于时间盲注查询成功
说明:"select * from user where id = %s "%injectdata 这种格式化处理传入数据的写法与tip1中一样,未对数据进行安全性校验
tip3:对输入数据进行格式化后参数化的调用execute函数
def database():
injectdata = "1"
xcmd= "select * from user where id = %s" #格式化处理
conn = psycopg2.connect(database="test", user="post", password=passwd, host=ip, port="5432")
cur = conn.cursor()
cur.execute(xcmd,injectdata) **#or [injectdata] or (injectdata) ,官网给出安全操作sql的调用方法,用传参数的方法调用。**
res = cur.fetchall()
conn.commit()
conn.close()
注入语法:
1 injectdata = “1 and 1=1” 或者 injectdata = “1 or id =2” #报错TypeError: not all arguments converted during string formatting
2 injectdata = " 1’ " # 报错
3 injectdata = ‘1;select version()’ #报错
4 injectdata = ‘1;select pg_sleep(5)’ #报错
python 调用psycopg的sql注入防御方法:
psycopg2最直接最根本的解决方案是用官网提供的传参方式操作数据库。
#the correct conversion (no more SQL injections!) #正确使用(有sql注入防御)
官网地址:http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries
说明:做python白盒代码审计时,重点看psycopg库的使用方法是否是传参调用的。
ps:本段代码只是为了验证python调用psycopg时sql的相关内容,在实际项目中一般看不到这么调用的,如果有这么写的安全问题还有很多(如:没有try,没有数据校验…)