소스코드
<?
// morla / 10111
// database gets cleared every 5 min
/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/
function checkCredentials($link,$usr,$pass){
$user=mysql_real_escape_string($usr);
$password=mysql_real_escape_string($pass);
$query = "SELECT username from users where username='$user' and password='$password' ";
$res = mysql_query($query, $link);
if(mysql_num_rows($res) > 0){
return True;
}
return False;
}
function validUser($link,$usr){
$user=mysql_real_escape_string($usr);
$query = "SELECT * from users where username='$user'";
$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
return True;
}
}
return False;
}
function dumpData($link,$usr){
$user=mysql_real_escape_string($usr);
$query = "SELECT * from users where username='$user'";
$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
while ($row = mysql_fetch_assoc($res)) {
// thanks to Gobo for reporting this bug!
//return print_r($row);
return print_r($row,true);
}
}
}
return False;
}
function createUser($link, $usr, $pass){
$user=mysql_real_escape_string($usr);
$password=mysql_real_escape_string($pass);
$query = "INSERT INTO users (username,password) values ('$user','$password')";
$res = mysql_query($query, $link);
if(mysql_affected_rows() > 0){
return True;
}
return False;
}
if(array_key_exists("username", $_REQUEST) and array_key_exists("password", $_REQUEST)) {
$link = mysql_connect('localhost', 'natas27', '<censored>');
mysql_select_db('natas27', $link);
if(validUser($link,$_REQUEST["username"])) {
//user exists, check creds
if(checkCredentials($link,$_REQUEST["username"],$_REQUEST["password"])){
echo "Welcome " . htmlentities($_REQUEST["username"]) . "!<br>";
echo "Here is your data:<br>";
$data=dumpData($link,$_REQUEST["username"]);
print htmlentities($data);
}
else{
echo "Wrong password for user: " . htmlentities($_REQUEST["username"]) . "<br>";
}
}
else {
//user doesn't exist
if(createUser($link,$_REQUEST["username"],$_REQUEST["password"])){
echo "User " . htmlentities($_REQUEST["username"]) . " was created!";
}
}
mysql_close($link);
} else {
?>
database는 5분마다 초기화된다고 한다.
username을 입력했을 때 user가 존재하지 않으면 username과 password를 database에 저장한다.
user가 존재하면, checkCredentials 함수로 username과 password를 검사해 일치하면 저장된 username과 password를 출력, 일치하지 않으면 wrong password ~ 이하를 출력한다.
mysql_real_escape_string 함수는 아래의 특수문자 앞에 백슬래시를 붙여 sql injection을 방어한다.
' " \ \x00 \n \r 1x1a(EOF)
우회 방법 : %a1~%fe와 같은 값을 입력하면 백슬래시를 하나의 문자로 취급해 우회할 수 있다고 한다.
https://securitynote.tistory.com/3
htmlentities 함수는 HTML 문자 엔티티에 존재하는 모든 문자를 엔티티로 변환한다.
html_entity_decode()로 디코딩할 수 있다고 한다.
mysql_num_rows 함수란 데이터베이스에서 쿼리를 날려서 나온 레코드들의 개수를 카운트하는 함수로
값이 없으면 0, 있으면 레코드 개수를 반환한다.
username과 password가 일치할 경우
guest/guest로 user를 생성해보았다. 다시 로그인하면 다음과 같이 username과 password가 뜬다.
mysql_real_escape_string함수를 우회해 sql injection을 시도하는 거라고 생각했는데, 앞부분에 놓친 게 있었다.
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
주석으로 공개한 database의 정보를 보면 각각 길이가 64로 설정되어 있다.
natas28의 뒤에 공백을 포함해 64보다 긴 문자열을 전달해보자.
natas28 1
위와 같이 natas28 + 공백 + 1을 username에 넣고 password에는 1을 넣었다.
natas28 1이 생성되었다고 한다.
이제 다시 natas28과 1로 로그인해보자.
natas28로 로그인에 성공하였다!
JWwR438wkgTsNKBbcJoowyysdM82YjeF
'Over the Wire > natas' 카테고리의 다른 글
[OverTheWire:Natas] natas 25 → 26 / natas26 (0) | 2021.08.29 |
---|---|
[OverTheWire:Natas] natas 24 → 25 / natas 25 (0) | 2021.08.15 |
[OverTheWire:Natas] natas 23 → 24 / natas24 (0) | 2021.08.03 |
[OvertheWire:Natas] natas 22 → 23 / natas 23 (0) | 2021.08.03 |
[OvertheWire:Natas] natas 21 → 22 /natas22 (0) | 2021.08.01 |