Lab4 Authentication

Lab Overview

In this lab, you’ll explore authentication. The key problem that authentication addresses is that how to identify the identity of a user. Think online banking system, on which many users are registered. When some user A is transferring money from her account into another user B’s account, how does the online banking system know whether this is the real user A, but not some other (malicious) user C who is in the disguise of A. At first glance, this problem is trivial, for the server can ask the user to input password and check the password to guarantee that this is the correct user, however, the problem will get complicated by the fact that the network packet can be sniffed.
To make the discussion concrete, you will do this lab for a new version Touchstone web server. The new server contains a very simple online banking system. Any user can transfer some money into another user’s account. However, this server contains severe bugs, which presents the fact that without correct and reliable authentication, a malicious user M can transfer money from any user account into her own account. Next, you’ll try to implement some form of more strong authentication system to enhance the server: say, you can add cookies to your server, or you can use some encrypt algorithms to protect sensitive data during data transmission over network.
In a summary, this lab is open-ended, and you can abuse you freedom to present your own design and implement them. Nevertheless to say, the bottom line is that you can guarantee that your solution is feasible.

This lab consists of three parts:
Part A: you will explore identity forgery, in which a malicious user can act as a victim user; 
Part B: you will explore the possibility of information disclosure during network transmission; 
Part C: you will secure the server by designing some cryptography algorithm and adding them to your server.

Exercise 1

这个系统的Bug主要在于进行转账时未对金额和用户进行判断:

  1. 未判断余额是否足够用于本次转账。这可能导致本次转账后余额为负。当余额为负时继续进行转账,使得余额可能小于int所能表示的最小值(根据编译器的不同,int所能表示的最小值可能为-2^31+1或-2^15+1)而造成溢出,导致余额由负变为正。
  2. 未判断转账金额是否为负。这将导致转账后该用户金额不减反增;相反,被转账用户(若该用户存在)金额将减少。
  3. 未判断被转账用户是否为自己。这将导致用户可向自己转账。于是当用户在向自己转账时,由handlePostTransfer函数可知,该用户的数据库信息将被更新两次,而第二次更新后,该用户的余额相当于原有余额加上转账余额,也就是余额增加了。
  4. 未判断被转账用户现有余额和将被转账金额的关系。这将导致本次转账后被转账用户余额超过int所能表示的最大值,使其余额由正变负。
  5. 未判断被转账用户是否存在。这将导致可能向一个不存在的用户转账。

Exercise 2

  • 判断转账金额
int judgeMoney(char *money)
{
  if(money[0] == '-')   //Money can't be negative
    return 0;
  int maxIntLength = getIntLength(INT_MAX);
  if(strlen(money) > maxIntLength)  //Money can't be larger than INT_MAX
    return 0;
  else if(strlen(money) == maxIntLength)    //Money can't be larger than INT_MAX
  {
    char *maxMoney = (char *)malloc(sizeof(char) * maxIntLength);
    sprintf(maxMoney, "%d", INT_MAX);
    if(strcmp(money, maxMoney) > 0)
      return 0;
  }
  return 1;
}
  • 判断被转账用户并调用判断余额函数
if(!judgeMoney(money) || !Db_checkUser(to) || strcmp(from, to) == 0 )   //Can't transfer to yourself or someone not existed
    { 
        handlePostLogin (fd, from, 0, 0);
        return;
    }
  • 判断转账用户和被转账用户余额
int judegeBalance(int money, int fromBalace, int toBalace)
{
    if(money > fromBalace)
        return 0;
    if(INT_MAX - toBalace < money)
        return 0;
    return 1;
}
if(judegeBalance(money, fromBalance, toBalance))
  {
    Db_writeBalance (from, newFromBalance);
    Db_writeBalance (to, newToBalance);
  }

Exercise 3

通过观察handlePost和handlePostTransfer函数可知,服务器在执行转账时并没有对用户进行验证,而是默认用户在登录成功后才能进行转账。因此,我们可以构造一个POST请求来伪装用户进行转账操作。


Exercise 4

为了伪造这个POST请求,我们应该先看看正常的POST请求是什么样。首先,登录一个用户,然后打开Wireshark,选择对lo(localhost)接口进行捕捉。

这里写图片描述

随意填写一个转账用户和金额,并点击”Transfer”

这里写图片描述

这时候可以看到Wireshark已经捕捉了一些包,我们只需观察HTTP的包。从列表中找到一个POST请求的包:

这里写图片描述

复制超文本传输协议中的内容:

这里写图片描述

这里的内容是请求头:

这里写图片描述

再复制下方的请求数据:

这里写图片描述

我们只需把这两部分数据发送给服务器就可以进行“欺骗”转账。其中Content-Length的值必须等于请求数据的长度。


Exercise 5

这里的思路就是:当用户成功登录的时,通过使用加密算法,把用户名和密码以及登录时间进行加密生成cookie,并把这个cookie返回给浏览器。用户在后续的POST的请求中,必须提交cookie,服务器再对cookie进行解密,从中提取用户名和密码来认证该用户。

cookie认证函数:

int confirmCookie(Http_t tree, char *from)
{
    Header_t head = tree->headers;
    while(head)
    {
        if(strcmp(head->key, "Cookie:") != 0)
            head = head->next;
        else
        {
            char **result = jiemi(head->value);
            printf("Get name and pwd from cookie : name = %s, pwd = %s\n", result[0], result[1]);
            if(strcmp(result[0], from) != 0)
            {
                printf("Login user and transfer is not equal\n");
                return 0;
            }
            return Db_checkUserPasswd(result[0], result[1]);
        }
    }
    printf("No cookie\n");
    return 0;
}

在进行转账前对cookie进行认证:

if(confirmCookie(tree, from))   //Confirm cookie
        handlePostTransfer (fd, from, to, m);
    else
    {
        handlePostLogin (fd, from, 0, 0);
        return;
    }

注:cookie只能为ASCII可显字符(33~126),且不能为’;’、’:’和’=’。
自己写的cookie产生和认证


Exercise 6

类似Exercise4的方法,使用wireshark抓包,从中提取cookie:

这里写图片描述

在发送POST请求时把cookie带上即可。由于cookie中可能包含\等字符,所以在发送cookie时,cookie从文件中读取比较方便。

    char req[1024];
    char *req1 ="POST /index.html HTTP/1.1\r\n"
    "Host: 127.0.0.1\r\n"
    "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:23.0) Gecko/20100101 Firefox/23.0\r\n"
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
    "Accept-Language: en-US,en;q=0.5\r\n"
    "Accept-Encoding: gzip, deflate\r\n"
    "Referer: http://127.0.0.1/index.html\r\n";
    char req2[260];    //"Cookie: " + cookie = 260
    FILE * in;
    int i = 0;
    char infile[]="cookie.txt";
    if((in=fopen(infile,"r"))==NULL)
    {
        printf("open failed\n");
        exit(0);
    }
    while(!feof(in) && i < 260)
    req2[i++] = fgetc(in);
    fclose(in);
    char *req3 = "Connection: keep-alive\r\n"
        "Content-Type: application/x-www-form-urlencoded\r\n"
        "Content-Length: 76\r\n"
            "\r\ntransfer_from=tt&transfer_to=kyt&transfer_money=10&submit_transfer=Transfer";
  sprintf(req, "%s%s\r\n%s", req1, req2, req3);
  write(sock_client,req,LEN);

Exercise 7

这里要求给cookie加密。由于Exercise 5里cookie已经加密,所以这里“做个蛋”。


Resources

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值