信息安全(privilege-separation)
实验解答如下
一、实验内容:
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:
1. 用户可以转账任何多的钱,及时他没有那么多的钱。
2. 用户可以输入小于零的一个转账数字来增加自己的钱。
3. 用户可以转账给任何人,及时这个人不存在,这个时候钱就进了黑洞了。
4. 用户只能转账整数,这是因为设计的时候只能存整数。
5. 用户可以转账给自己。
Exercise 2:
首先我们需要对转账的数目进行边界检查,然后在对转账的用户进行检查,就可以了。在handle.c文件的handlePostTransfer()函数中添加下列代码
int t = Db_checkUser(to);
if(!t)//user don't exist{
printf("user don't exist!");
return;}
if(money <= 0 ){
printf("can't transefer money<=0!");
return;}
if(!strcmp(from,to)){
printf("can't transfer money to yourself!");
return;}
int fromBalance = Db_readBalance (from);
if(fromBalance < money){
printf("you don't hava enough money!");
return;}
运行后再检查上面的bug,发现实际可行,具体如下图:
Exercise 3:
这次的转账的功能具体是写在handle.c文件中的,其中对于数据库的操作全都写在了sql-lit3/dbutil.c文件中,每次登陆之后,有httpd进行解析看看接受的是什么类型的信息,然后分发给banksv等,然后具体对于请求的解析是由parse.c文件中的相关函数解析的,由于这次添加了POST的请求,所以相比于上次实验多了如何处理POST请求的部分,解析完毕之后就可以交给handle.c进行主要的功能处理了。
Exercise 4:
我们可以借助firefox自带的firebug来查看POST的请求具体的值。
我们可以发现四个参数具体值,其中submit_transfer参数代表了是执行转账操作,下面三个分别是转账人、转账多少、转账给谁。那么我们就可以利用这个来构造一个POST请求,但是这里我们为了方便快捷,可以使用另外一个firefox自带的插件工具Live HTTP headers,利用其中replay功能,进行重放攻击,并且可以任意修改其中的参数,正好适合我们构造POST请求,如下图所示,由aaa转账给bbb,并且很容易从右边的服务器命令行输出的信息判断是成功的:
Exercise 5:
首先我把分成两步,第一步是利用工具构造一个cookie,然后构造post请求,第二步再由服务器返回一个cookie给浏览器。
1. 还是利用firebug创建一个cookie名字是ch值是1,
2. 构建一个带cookie的post请求,发现服务器成功解析了cookie,当然了需要在parse.c中parseHeaders函数加入如下代码,具体位置参照图片中位置。
3. 再观察到底用户的钱有没有正确的处理,下面两张图对比可得知确实转账成功(注意操作时间和余额)。
4. 如果我们构造的请求cookie有错的话会出现下图所示的结果,回到登录界面当然也需要另外再加代码,在handle.c中handlePost函数中添加如下代码:
其中getCookie()代码是取得刚才上一步服务器中解析cookie的值。
5. 利用请求中的Set-Cookie来给浏览器发送一个cookie,这需要在handle.c文件的handlePostLogin函数中添加如下代码:
重新编译服务器代码,运行发现浏览器多了一个我们设置的ch=100的cookie,请看cookie存在时间和value的值。
6. 那么这样一来,浏览器就有来自于服务器的cookie了,重复2-4步骤完全正确。
Exercise 6:
首先利用wirshark监听lo,用来抓虚拟机的包,然后在浏览器进行几次操作以便取得包,再筛选出http请求的包,找到POST request,发现跟利用Live HTTP headers抓到的请求结构差不多,那么很容易就构造一个虚假的POST request,结果跟上面的一样,就不重复放图了。
Exercise 7:
1. 首先需要写三个函数实现添加cookie到数据库(Db_readCookie),从数据库中读取cookie(Db_writeCookie),以及对cookie进行加密(encryp_cookie),这些都放在sql-lite3/dbutil.c文件中,当然得先在user表中添加cookie字段(VARCHAR(50)):
char* Db_readCookie (const char *name)
{
if(DEBUG)
printf("Db_readCookie: name=[%s]\n", name);
if(Db_open(0)!=SUCCESS){
fprintf(stderr
, "open failed![%s]\n"
, sqlite3_errmsg(db));
return 0;
}
char sql[1024];
sprintf(sql, "SELECT cookie from user WHERE name = '%s'", name);
int row, column;
char **result;
char *errorMsg;
int ret = sqlite3_get_table(db, sql, &result, &row, &column, &errorMsg);
if (ret!=SQLITE_OK){
fprintf (stderr
, "error read cookie\n");
return 0;
}
if(DEBUG){
printf("nrow=[%d], column=[%d]\n", row, column);
printf ("======%s\n", (result+1)[column-1]);
}
char *cookies = (result+1)[column-1];
sqlite3_free_table(result);
//Db_exec(db, sql);
sqlite3_close(db);
return cookies;
}
int Db_writeCookie (const char *name
, const char *cookie)
{
if(DEBUG)
printf("Db_writecookie(): name=[%s]\n"
, name);
if(Db_open(0)!=SUCCESS){
fprintf(stderr
, "open failed![%s]\n"
, sqlite3_errmsg(db));
return 0;
}
char sql[1024];
char *errorMsg;
//encryp
char copy_cookie[50];
strcpy(copy_cookie,cookie);
encryp_cookie(copy_cookie);
sprintf(sql, "UPDATE user set cookie=%s where name= '%s'", copy_cookie, name);
int ret = sqlite3_exec(db, sql, 0, 0, &errorMsg);
if (ret!=SQLITE_OK){
fprintf (stderr
, "%s\n"
, "error read cookie");
return 0;
}
if(DEBUG){
printf("Db_writeCookie() succeed\n");
}
sqlite3_close(db);
return 1;
}
//encryption function,key =3
void encryp_cookie(char *cookie)
{
int i = 0;
char temp;
while(cookie[i] != '\0')
{
temp = cookie[i]^3;
cookie[i] = temp;
i++;
}
}
2. 接下来需要在handle.c中handlePost函数里实现解密的部分,其实解密就是用秘钥数字3来进行异或运算即可:
//add to check cookie
char *cookie = getCookie();//cookie: aaa=222
int c_t = 0;
//depart username from cookie
while(cookie[c_t] != '=')
{
c_t++;
}
//decryp cookie
char temp;
c_t++;
int c_i = c_t;
while(cookie[c_t] != '\0')
{
temp = cookie[c_t] ^ 3;
cookie[c_t] = temp;
c_t++;
}
printf("decryp cookie =%s\n",cookie);
if(strcmp(&cookie[c_i],"111")==0) //just compare cookie not include username
handlePostTransfer (fd, from, to, m);
else
{
printf("fault cookie\n");
handlePostLogout(fd);//faile to load index.html
}
4. 我用的cookie值是111,用3进行异或加密之后是222,解密之后也应该是111,结果完全符合,如下图所示:
5. 实验结果,请注意时间的对比,防伪。