当前位置: 首页 > 科技观察

Python代码审计实战案例总结:SQL和ORM注入

时间:2023-03-12 17:54:03 科技观察

Python代码审计的方式五花八门,但总而言之,都是在对以往思想的迁移、融合、扩展的基础上形成的。目前,Python代码审计思路呈现去中心化、多元化的趋势。将Python微薄的研发经验和实践中遇到的思路和技巧总结出来,方便朋友们学习和参考。SQL注入和ORM注入的相似度很高,所以放在一起分析总结。他们使用的原则在OWASPTOPTEN中有详细描述,“当不受信任的数据作为命令或查询的一部分发送到解析器时,可能会发生SQL注入、NoSQL注入、操作系统注入和LDAP注入等注入缺陷。攻击来自攻击者的恶意数据可以诱使解析器执行意外命令或在未经适当授权的情况下访问数据。”。1、SQL注入Python中经常存在有风险的SQL语句,在id或name可控的情况下存在安全隐患。可控的参数可以根据语法拼接出我们期望他执行的代码,从而执行原本不期望的代码。sql="selectid,namefromuser_tablewhereid=%sandname=%s"%(id,name)cur.execute(sql)但是在实际案例中,这样执行的SQL语句并不多,属于比较典型的案例。示例代码如下:importurllibimportMySQLdbimportSocketServerfromSimpleHTTPServerimportSimpleHTTPRequestHandlerclassMyHandler(SimpleHTTPRequestHandler):def_set_headers(self):self.send_response(200)self.send_header('Content-type','text/html')self.end_headers()defdo_GET("print%s"%(self.path))hql=urllib.splitquery(self.path)[1]uri_c=str(hql)print('cmd===%s'%(uri_c))sql="selectidfromuser_tablewhereid=%s"%uri_cdb=MySQLdb.connect("localhost","testuser","test123","TESTDB",charset='utf8')cursor=db.cursor()cursor.execute(sql)data=cursor.fetchone()self.wfile.write(data)defstart_server():httpd=SocketServer.TCPServer(("127.0.0.1",8090),MyHandler)print('Startinghttpd...')httpd.serve_forever()if__name__=="__main__":start_server()这是一个简单的HTTP服务器,目前在Python2中运行良好。通过urllib.splitquery获取GET请求的参数,uri_c为请求参数的值。拼接传入SQL语句的值,导致注入问题。这是一个比较简单的。一般情况下,调用链可能比较长,具体取决于平台的设计架构。2、ORM注入(1)sqlalchemyORM注入(CNVD-2019-17301)被认为比较容易理解,以模块为例,不涉及框架。ORM注入是SQL注入的一个特例。ORM模块模板化了SQL语句,所以查找SQL语句字符串的方法不好用。那我们该怎么办呢?根据模块找到执行方法。如果模块有问题,过滤或转义不当,有可控变量,就可能出问题。如何发现和查找PythonORM模块,是时候展示一下小伙伴们的搜索技巧了,不再是老生常谈了。输入下面的案例:fromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportsessionmakerimportsqlalchemyprint("sqlalchemy_version:",sqlalchemy.__version__)engine=create_engine('mysql://root:123456@192.168.56.101:3306/mysql?charset=utf8')DB_Session=sindessionengmaker()session=DB_Session()session.execute('usemysql;')print(session.execute("""select*fromuserwhereUser='root'and11=1;""").fetchall())这是使用sqlalchemy注入的ORM,它有一个用于执行任何SQL语句的接口。理论上,这是一个函数。现实中,大多数程序员认为ORM可以防止SQL注入,而这可能会成为一个漏洞。通过转义可以更好的解决问题,但是官方可能不会重视。另外,sqlalchemy还有几个问题,比如使用order_by注入,使用“limit”和“offset”关键字将注入传递给“select()”函数等,方法也不是严格的使用模块过滤,所以我暂时不谈。(2)DjangoJSONSQL注入(CVE-2019-14234)下面继续看DjangoJSONSQL注入。这个漏洞前人已经分析过了。这个分析有点难度,需要我们懂Django和PostgreSQL。如果觉得难,不妨先学习一下。了解PostgreSQL查询JSON数据主要用到ArrayField、JSONField、HStoreField、如何通过Django查询PostgreSQL、Json.objects.filter()和QuerySet.filter(),准备工作就绪。查询方法如下:#查询方法#查询data数据下整个名为test的字段,内容为'user'Json.objects.filter(data__test='user')orJson.objects.filter(**{"data__test":'user'})由patch判断实现方法使用了self.key_name,QuerySet.filter()的调用与self.key_name的传递有关。紧接着,发现KeyTransformFactory这个类调用了KeyTransform,传入了self.key_name,后面就是字符串拼接。这里就不多做详细说明了,有兴趣的朋友可以跟着流程走。classKeyTextTransform(KeyTransform):operator='->>'...#Stringconcatenation(%s%s%s)"%(lhs,self.operator,lookup)结合注入知识进行实现测试,结果如下.#使用注入#拼接完成SQL语法Json.objects.filter(**{"""data__breed'='"a"')OR11=1OR('d""":'x',})总结本总结PythonSQL注入中SQL注入和ORM注入的挖掘方法及相关案例,SQL注入没有对应的实际案例,写一个简单的案例作为参考,ORM注入是两个案例,关于模块和框架。综合作为实用采供参考,个人实力,可能有疏漏,希望斧头指正。

猜你喜欢